Skip to content

Commit

Permalink
ruleset: async callback pattern
Browse files Browse the repository at this point in the history
Signed-off-by: He Xian <[email protected]>
  • Loading branch information
hexian000 committed Jan 14, 2025
1 parent a94b2d1 commit 16cf51e
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 76 deletions.
10 changes: 2 additions & 8 deletions src/api_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,9 @@ static void handle_ruleset_rpcall(
.func = rpcall_return,
.data = ctx,
};
struct ruleset_state *rpcstate = ruleset_rpcall(r, reader, &callback);
const bool ok = ruleset_rpcall(r, &ctx->rpcstate, reader, &callback);
stream_close(reader);
if (rpcstate == NULL) {
if (!ok) {
/* no callback */
ctx->state = STATE_RESPONSE;
size_t len;
Expand All @@ -501,12 +501,6 @@ static void handle_ruleset_rpcall(
ev_io_start(loop, &ctx->w_send);
return;
}
if (ctx->state != STATE_YIELD) {
/* rpcall_return is called */
return;
}
/* rpcall_return is not called yet */
ctx->rpcstate = rpcstate;
}

static void handle_ruleset_invoke(
Expand Down
30 changes: 19 additions & 11 deletions src/forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,22 +283,27 @@ forward_idle_cb(struct ev_loop *loop, struct ev_idle *watcher, int revents)
.loop = loop,
.data = ctx,
};
struct ruleset_state *state;
bool ok;
switch (addr->type) {
case ATYP_INET:
state = ruleset_route(ruleset, request, NULL, NULL, &callback);
ok = ruleset_route(
ruleset, &ctx->ruleset_state, request, NULL, NULL,
&callback);
break;
case ATYP_INET6:
state = ruleset_route6(ruleset, request, NULL, NULL, &callback);
ok = ruleset_route6(
ruleset, &ctx->ruleset_state, request, NULL, NULL,
&callback);
break;
case ATYP_DOMAIN:
state = ruleset_resolve(
ruleset, request, NULL, NULL, &callback);
ok = ruleset_resolve(
ruleset, &ctx->ruleset_state, request, NULL, NULL,
&callback);
break;
default:
FAIL();
}
if (state == NULL) {
if (!ok) {
forward_ctx_close(loop, ctx);
return;
}
Expand Down Expand Up @@ -419,19 +424,22 @@ tproxy_idle_cb(struct ev_loop *loop, struct ev_idle *watcher, int revents)
.loop = loop,
.data = ctx,
};
struct ruleset_state *state;
bool ok;
switch (dest.sa.sa_family) {
case AF_INET:
state = ruleset_route(ruleset, addr_str, NULL, NULL, &callback);
ok = ruleset_route(
ruleset, &ctx->ruleset_state, addr_str, NULL, NULL,
&callback);
break;
case AF_INET6:
state = ruleset_route6(
ruleset, addr_str, NULL, NULL, &callback);
ok = ruleset_route6(
ruleset, &ctx->ruleset_state, addr_str, NULL, NULL,
&callback);
break;
default:
FAIL();
}
if (state == NULL) {
if (!ok) {
forward_ctx_close(loop, ctx);
return;
}
Expand Down
7 changes: 4 additions & 3 deletions src/http_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,10 @@ static void idle_cb(struct ev_loop *loop, struct ev_idle *watcher, int revents)
.loop = loop,
.data = ctx,
};
struct ruleset_state *state = ruleset_resolve(
ruleset, addr_str, username, password, &callback);
if (state == NULL) {
const bool ok = ruleset_resolve(
ruleset, &ctx->ruleset_state, addr_str, username, password,
&callback);
if (!ok) {
http_resp_errpage(&ctx->parser, HTTP_INTERNAL_SERVER_ERROR);
ctx->state = STATE_RESPONSE;
ev_io_start(loop, &ctx->w_send);
Expand Down
49 changes: 28 additions & 21 deletions src/ruleset.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,12 @@ void ruleset_cancel(struct ruleset_state *state)
}
}

struct ruleset_state *ruleset_rpcall(
struct ruleset *r, struct stream *code,
bool ruleset_rpcall(
struct ruleset *r, struct ruleset_state **state, struct stream *code,
const struct ruleset_rpcall_cb *callback)
{
const bool ok = ruleset_pcall(r, cfunc_rpcall, 2, 1, code, callback);
const bool ok =
ruleset_pcall(r, cfunc_rpcall, 3, 1, state, code, callback);
if (!ok) {
return NULL;
}
Expand All @@ -260,42 +261,48 @@ bool ruleset_gc(struct ruleset *restrict r)
return ruleset_pcall(r, cfunc_gc, 0, 0);
}

static struct ruleset_state *dispatch_req(
struct ruleset *restrict r, const char *func, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback)
static bool dispatch_req(
struct ruleset *restrict r, struct ruleset_state **state,
const char *func, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback)
{
lua_State *restrict L = r->L;
const bool ok = ruleset_pcall(
r, cfunc_request, 5, 1, (void *)func, (void *)request,
(void *)username, (void *)password, (void *)callback);
r, cfunc_request, 6, 1, (void *)state, (void *)func,
(void *)request, (void *)username, (void *)password,
(void *)callback);
if (!ok) {
LOGW_F("ruleset.%s: %s", func, ruleset_geterror(r, NULL));
return NULL;
}
return lua_touserdata(L, -1);
}

struct ruleset_state *ruleset_resolve(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback)
bool ruleset_resolve(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback)
{
return dispatch_req(
r, "resolve", request, username, password, callback);
r, state, "resolve", request, username, password, callback);
}

struct ruleset_state *ruleset_route(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback)
bool ruleset_route(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback)
{
return dispatch_req(r, "route", request, username, password, callback);
return dispatch_req(
r, state, "route", request, username, password, callback);
}

struct ruleset_state *ruleset_route6(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback)
bool ruleset_route6(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback)
{
return dispatch_req(r, "route6", request, username, password, callback);
return dispatch_req(
r, state, "route6", request, username, password, callback);
}

void ruleset_vmstats(
Expand Down
25 changes: 14 additions & 11 deletions src/ruleset.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ struct ruleset_rpcall_cb {
void (*func)(void *data, const char *result, size_t resultlen);
void *data;
};
struct ruleset_state *ruleset_rpcall(
struct ruleset *r, struct stream *code,
bool ruleset_rpcall(
struct ruleset *r, struct ruleset_state **state, struct stream *code,
const struct ruleset_rpcall_cb *callback);

bool ruleset_update(
Expand All @@ -47,15 +47,18 @@ struct ruleset_request_cb {
struct ev_loop *loop;
void *data;
};
struct ruleset_state *ruleset_resolve(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback);
struct ruleset_state *ruleset_route(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback);
struct ruleset_state *ruleset_route6(
struct ruleset *r, const char *request, const char *username,
const char *password, const struct ruleset_request_cb *callback);
bool ruleset_resolve(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback);
bool ruleset_route(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback);
bool ruleset_route6(
struct ruleset *r, struct ruleset_state **state, const char *request,
const char *username, const char *password,
const struct ruleset_request_cb *callback);

void ruleset_vmstats(const struct ruleset *r, struct ruleset_vmstats *s);
const char *
Expand Down
32 changes: 18 additions & 14 deletions src/ruleset/cfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,16 @@ struct dialreq;
int cfunc_request(lua_State *restrict L)
{
check_memlimit(L);
ASSERT(lua_gettop(L) == 5);
const char *func = lua_touserdata(L, 1);
const char *request = lua_touserdata(L, 2);
const char *username = lua_touserdata(L, 3);
const char *password = lua_touserdata(L, 4);
const struct ruleset_request_cb *in_cb = lua_touserdata(L, 5);
struct ruleset_state *restrict ud =
ASSERT(lua_gettop(L) == 6);
struct ruleset_state **pstate = lua_touserdata(L, 1);
const char *func = lua_touserdata(L, 2);
const char *request = lua_touserdata(L, 3);
const char *username = lua_touserdata(L, 4);
const char *password = lua_touserdata(L, 5);
const struct ruleset_request_cb *in_cb = lua_touserdata(L, 6);
struct ruleset_state *restrict state =
lua_newuserdata(L, sizeof(struct ruleset_state));
*ud = (struct ruleset_state){
*state = (struct ruleset_state){
.type = RCB_REQUEST,
.request = { NULL, NULL, NULL },
};
Expand Down Expand Up @@ -103,9 +104,10 @@ int cfunc_request(lua_State *restrict L)
req = NULL;
}
lua_pushvalue(L, 1);
ud->request = *in_cb;
ud->request.func(ud->request.loop, ud->request.data, req);
ud->request.func = NULL;
state->request = *in_cb;
*pstate = state;
state->request.func(state->request.loop, state->request.data, req);
state->request.func = NULL;
return 1;
}

Expand Down Expand Up @@ -176,9 +178,10 @@ static int rpcall_finish(lua_State *restrict L)
int cfunc_rpcall(lua_State *restrict L)
{
check_memlimit(L);
ASSERT(lua_gettop(L) == 2);
struct stream *stream = lua_touserdata(L, 1);
const struct ruleset_rpcall_cb *in_cb = lua_touserdata(L, 2);
ASSERT(lua_gettop(L) == 3);
struct ruleset_state **pstate = lua_touserdata(L, 1);
struct stream *stream = lua_touserdata(L, 2);
const struct ruleset_rpcall_cb *in_cb = lua_touserdata(L, 3);
struct ruleset_state *restrict state =
lua_newuserdata(L, sizeof(struct ruleset_state));
*state = (struct ruleset_state){
Expand Down Expand Up @@ -215,6 +218,7 @@ int cfunc_rpcall(lua_State *restrict L)
lua_pop(L, 1);
lua_xmove(L, co, 1);
state->rpcall = *in_cb;
*pstate = state;
/* lua stack: state co; co stack: chunk */
aux_resume(L, 2, 0);
lua_settop(L, 1);
Expand Down
19 changes: 11 additions & 8 deletions src/socks.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,24 +819,27 @@ static void idle_cb(struct ev_loop *loop, struct ev_idle *watcher, int revents)
.loop = loop,
.data = ctx,
};
struct ruleset_state *state;
bool ok;
switch (addr->type) {
case ATYP_DOMAIN:
state = ruleset_resolve(
ruleset, request, username, password, &callback);
ok = ruleset_resolve(
ruleset, &ctx->ruleset_state, request, username,
password, &callback);
break;
case ATYP_INET:
state = ruleset_route(
ruleset, request, username, password, &callback);
ok = ruleset_route(
ruleset, &ctx->ruleset_state, request, username,
password, &callback);
break;
case ATYP_INET6:
state = ruleset_route6(
ruleset, request, username, password, &callback);
ok = ruleset_route6(
ruleset, &ctx->ruleset_state, request, username,
password, &callback);
break;
default:
FAIL();
}
if (state == NULL) {
if (!ok) {
socks_sendrsp(ctx, false);
socks_ctx_close(loop, ctx);
return;
Expand Down

0 comments on commit 16cf51e

Please sign in to comment.