From 693b198887df9f3dd348e1b182d6fb3e87cc3bb3 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 12 Nov 2014 17:16:25 +0800 Subject: [PATCH] refine server end --- src/local.c | 35 ++++++++------ src/server.c | 122 +++++++++++++++++++++++++++++++++++++------------ src/server.h | 3 ++ src/udprelay.c | 8 +++- src/udprelay.h | 1 + 5 files changed, 124 insertions(+), 45 deletions(-) diff --git a/src/local.c b/src/local.c index b88161c0..0839fbfe 100644 --- a/src/local.c +++ b/src/local.c @@ -698,20 +698,18 @@ static struct remote * new_remote(int fd, int timeout) static void free_remote(struct remote *remote) { - if (remote != NULL) { - if (remote->server != NULL) { - remote->server->remote = NULL; - } - if (remote->buf != NULL) { - free(remote->buf); - } - if (remote->addr_info != NULL) { - freeaddrinfo(remote->addr_info); - } - free(remote->recv_ctx); - free(remote->send_ctx); - free(remote); + if (remote->server != NULL) { + remote->server->remote = NULL; + } + if (remote->buf != NULL) { + free(remote->buf); + } + if (remote->addr_info != NULL) { + freeaddrinfo(remote->addr_info); } + free(remote->recv_ctx); + free(remote->send_ctx); + free(remote); } static void close_and_free_remote(EV_P_ struct remote *remote) @@ -1133,6 +1131,9 @@ int main(int argc, char **argv) winsock_cleanup(); #endif + ev_signal_stop(EV_DEFAULT, &sigint_watcher); + ev_signal_stop(EV_DEFAULT, &sigterm_watcher); + return 0; } #else @@ -1238,15 +1239,21 @@ int start_ss_local_server(profile_t profile) // Clean up free_connections(loop); - free_udprelay(); + if (udprelay) { + free_udprelay(); + } ev_io_stop(loop, &listen_ctx.io); free(listen_ctx.remote_addr); + close(listen_ctx.fd); #ifdef __MINGW32__ winsock_cleanup(); #endif + ev_signal_stop(EV_DEFAULT, &sigint_watcher); + ev_signal_stop(EV_DEFAULT, &sigterm_watcher); + // cannot reach here return 0; } diff --git a/src/server.c b/src/server.c index 4d042875..fa14bca0 100644 --- a/src/server.c +++ b/src/server.c @@ -37,6 +37,8 @@ #include #include +#include + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -62,6 +64,7 @@ #define BUF_SIZE 2048 #endif +static void signal_cb(EV_P_ ev_signal *w, int revents); static void accept_cb(EV_P_ ev_io *w, int revents); static void server_recv_cb(EV_P_ ev_io *w, int revents); static void server_send_cb(EV_P_ ev_io *w, int revents); @@ -80,7 +83,6 @@ static void close_and_free_remote(EV_P_ struct remote *remote); static void free_server(struct server *server); static void close_and_free_server(EV_P_ struct server *server); - int verbose = 0; int udprelay = 0; #ifdef TCP_FASTOPEN @@ -92,6 +94,20 @@ static int nofile = 0; static int remote_conn = 0; static int server_conn = 0; +static struct cork_dllist connections; + +static void free_connections(struct ev_loop *loop) +{ + struct cork_dllist_item *curr; + for (curr = cork_dllist_start(&connections); !cork_dllist_is_end(&connections, curr); + curr = curr->next) { + struct server *server = cork_container_of(curr, struct server, entries); + struct remote *remote = server->remote; + close_and_free_server(loop, server); + close_and_free_remote(loop, remote); + } +} + int setnonblocking(int fd) { int flags; @@ -743,17 +759,15 @@ static struct remote * new_remote(int fd) static void free_remote(struct remote *remote) { - if (remote != NULL) { - if (remote->server != NULL) { - remote->server->remote = NULL; - } - if (remote->buf != NULL) { - free(remote->buf); - } - free(remote->recv_ctx); - free(remote->send_ctx); - free(remote); + if (remote->server != NULL) { + remote->server->remote = NULL; + } + if (remote->buf != NULL) { + free(remote->buf); } + free(remote->recv_ctx); + free(remote->send_ctx); + free(remote); } static void close_and_free_remote(EV_P_ struct remote *remote) @@ -805,30 +819,33 @@ static struct server * new_server(int fd, struct listen_ctx *listener) server->buf_len = 0; server->buf_idx = 0; server->remote = NULL; + + cork_dllist_add(&connections, &server->entries); + return server; } static void free_server(struct server *server) { - if (server != NULL) { - if (server->remote != NULL) { - server->remote->server = NULL; - } - if (server->e_ctx != NULL) { - cipher_context_release(&server->e_ctx->evp); - free(server->e_ctx); - } - if (server->d_ctx != NULL) { - cipher_context_release(&server->d_ctx->evp); - free(server->d_ctx); - } - if (server->buf != NULL) { - free(server->buf); - } - free(server->recv_ctx); - free(server->send_ctx); - free(server); + cork_dllist_remove(&server->entries); + + if (server->remote != NULL) { + server->remote->server = NULL; + } + if (server->e_ctx != NULL) { + cipher_context_release(&server->e_ctx->evp); + free(server->e_ctx); + } + if (server->d_ctx != NULL) { + cipher_context_release(&server->d_ctx->evp); + free(server->d_ctx); } + if (server->buf != NULL) { + free(server->buf); + } + free(server->recv_ctx); + free(server->send_ctx); + free(server); } static void close_and_free_server(EV_P_ struct server *server) @@ -850,6 +867,17 @@ static void close_and_free_server(EV_P_ struct server *server) } } +static void signal_cb(EV_P_ ev_signal *w, int revents) +{ + if (revents & EV_SIGNAL) { + switch (w->signum) { + case SIGINT: + case SIGTERM: + ev_unloop(EV_A_ EVUNLOOP_ALL); + } + } +} + static void accept_cb(EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; @@ -1025,6 +1053,13 @@ int main(int argc, char **argv) signal(SIGCHLD, SIG_IGN); signal(SIGABRT, SIG_IGN); + struct ev_signal sigint_watcher; + struct ev_signal sigterm_watcher; + ev_signal_init(&sigint_watcher, signal_cb, SIGINT); + ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); + ev_signal_start(EV_DEFAULT, &sigint_watcher); + ev_signal_start(EV_DEFAULT, &sigterm_watcher); + // setup asyncns asyncns_t *asyncns; if (!(asyncns = asyncns_new(dns_thread_num))) { @@ -1094,8 +1129,37 @@ int main(int argc, char **argv) run_as(user); } + // Init connections + cork_dllist_init(&connections); + // start ev loop ev_run(loop, 0); + + if (verbose) { + LOGD("closed nicely."); + } + + // Clean up + listen_ctx = &listen_ctx_list[0]; + ev_io_stop(loop, &listen_ctx->io); + asyncns_free(listen_ctx->asyncns); + close(listen_ctx->fd); + + for (int i = 1; i <= server_num; i++) { + listen_ctx = &listen_ctx_list[i]; + ev_io_stop(loop, &listen_ctx->io); + close(listen_ctx->fd); + } + + free_connections(loop); + + if (udprelay) { + free_udprelay(); + } + + ev_signal_stop(EV_DEFAULT, &sigint_watcher); + ev_signal_stop(EV_DEFAULT, &sigterm_watcher); + return 0; } diff --git a/src/server.h b/src/server.h index 86768b26..2f5dc21a 100644 --- a/src/server.h +++ b/src/server.h @@ -25,6 +25,7 @@ #include #include +#include #include "encrypt.h" #include "jconf.h" @@ -62,6 +63,8 @@ struct server { struct server_ctx *send_ctx; struct listen_ctx *listen_ctx; struct remote *remote; + + struct cork_dllist_item entries; }; struct remote_ctx { diff --git a/src/udprelay.c b/src/udprelay.c index b1ef3273..bd23fb1f 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -880,11 +880,13 @@ int init_udprelay(const char *server_host, const char *server_port, FATAL("asyncns failed"); } resolve_ctx = malloc(sizeof(struct resolve_ctx)); - resolve_ctx->asyncns = asyncns; int asyncnsfd = asyncns_fd(asyncns); ev_io_init(&resolve_ctx->io, query_resolve_cb, asyncnsfd, EV_READ); ev_io_start(loop, &resolve_ctx->io); + + resolve_ctx->asyncns = asyncns; + resolve_ctx->asyncnsfd = asyncnsfd; #endif // Bind to port @@ -920,8 +922,10 @@ void free_udprelay() struct ev_loop *loop = EV_DEFAULT; #ifdef UDPRELAY_REMOTE if (resolve_ctx != NULL) { - asyncns_free(resolve_ctx->asyncns); ev_io_stop(loop, &resolve_ctx->io); + asyncns_free(resolve_ctx->asyncns); + + close(resolve_ctx->asyncnsfd); free(resolve_ctx); resolve_ctx = NULL; } diff --git a/src/udprelay.h b/src/udprelay.h index 98c96489..0d38a83e 100644 --- a/src/udprelay.h +++ b/src/udprelay.h @@ -62,6 +62,7 @@ struct server_ctx { struct resolve_ctx { ev_io io; asyncns_t *asyncns; + int asyncnsfd; }; struct query_ctx {