From 08a35fd1bb626ba29bae9346f281ba415f724afb Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 12 Nov 2014 09:54:27 +0800 Subject: [PATCH] handle sigterm and sigkill --- src/acl.c | 3 +- src/{include.h => common.h} | 6 +- src/json.c | 4 +- src/json.h | 288 ++++++++++++++++++------------------ src/local.c | 140 ++++++++++++++---- src/local.h | 22 +-- src/redir.c | 27 +++- src/redir.h | 13 -- src/server.c | 58 ++++++-- src/server.h | 19 +-- src/shadowsocks.h | 31 ++-- src/tunnel.c | 20 ++- src/tunnel.h | 15 +- src/udprelay.c | 31 +++- src/udprelay.h | 3 +- 15 files changed, 390 insertions(+), 290 deletions(-) rename src/{include.h => common.h} (91%) diff --git a/src/acl.c b/src/acl.c index 88265bc5..f9b5bf11 100644 --- a/src/acl.c +++ b/src/acl.c @@ -69,7 +69,8 @@ int init_acl(const char *path) cork_string_array_init(&acl_domain_array); FILE *f = fopen(path, "r"); - if (f == NULL) { + if (f == NULL) + { LOGE("Invalid acl path."); return -1; } diff --git a/src/include.h b/src/common.h similarity index 91% rename from src/include.h rename to src/common.h index dc218ffe..18a609bf 100644 --- a/src/include.h +++ b/src/common.h @@ -1,5 +1,5 @@ /* - * include.h - Provide global definitions + * common.h - Provide global definitions * * Copyright (C) 2013 - 2014, Max Lv * @@ -37,7 +37,7 @@ #endif -int udprelay_init(const char *server_host, const char *server_port, +int init_udprelay(const char *server_host, const char *server_port, #ifdef UDPRELAY_LOCAL const char *remote_host, const char *remote_port, #ifdef UDPRELAY_TUNNEL @@ -49,4 +49,6 @@ int udprelay_init(const char *server_host, const char *server_port, #endif int method, int timeout, const char *iface); +void free_udprelay(void); + #endif // _INCLUDE_H diff --git a/src/json.c b/src/json.c index 0ef381ed..74c5d698 100644 --- a/src/json.c +++ b/src/json.c @@ -392,10 +392,10 @@ json_value * json_parse_ex (json_settings * settings, else { top->u.object.values [top->u.object.length].name - = (json_char *) top->_reserved.object_mem; + = (json_char *) top->_reserved.object_mem; top->u.object.values [top->u.object.length].name_length - = string_length; + = string_length; (*(json_char **) &top->_reserved.object_mem) += string_length + 1; } diff --git a/src/json.h b/src/json.h index 6175e12f..8ac9ed9d 100644 --- a/src/json.h +++ b/src/json.h @@ -54,216 +54,216 @@ extern "C" #endif -typedef struct -{ - unsigned long max_memory; - int settings; + typedef struct + { + unsigned long max_memory; + int settings; - /* Custom allocator support (leave null to use malloc/free) - */ + /* Custom allocator support (leave null to use malloc/free) + */ - void * (* mem_alloc) (size_t, int zero, void * user_data); - void (* mem_free) (void *, void * user_data); + void * (* mem_alloc) (size_t, int zero, void * user_data); + void (* mem_free) (void *, void * user_data); - void * user_data; /* will be passed to mem_alloc and mem_free */ + void * user_data; /* will be passed to mem_alloc and mem_free */ -} json_settings; + } json_settings; #define json_enable_comments 0x01 -typedef enum -{ - json_none, - json_object, - json_array, - json_integer, - json_double, - json_string, - json_boolean, - json_null - -} json_type; - -extern const struct _json_value json_value_none; + typedef enum + { + json_none, + json_object, + json_array, + json_integer, + json_double, + json_string, + json_boolean, + json_null -typedef struct _json_value -{ - struct _json_value * parent; + } json_type; - json_type type; + extern const struct _json_value json_value_none; - union + typedef struct _json_value { - int boolean; - json_int_t integer; - double dbl; + struct _json_value * parent; + + json_type type; - struct + union { - unsigned int length; - json_char * ptr; /* null terminated */ + int boolean; + json_int_t integer; + double dbl; - } string; + struct + { + unsigned int length; + json_char * ptr; /* null terminated */ - struct - { - unsigned int length; + } string; struct { - json_char * name; - unsigned int name_length; + unsigned int length; + + struct + { + json_char * name; + unsigned int name_length; - struct _json_value * value; + struct _json_value * value; - } * values; + } * values; #if defined(__cplusplus) && __cplusplus >= 201103L - decltype(values) begin () const - { - return values; - } - decltype(values) end () const - { - return values + length; - } + decltype(values) begin () const + { + return values; + } + decltype(values) end () const + { + return values + length; + } #endif - } object; + } object; - struct - { - unsigned int length; - struct _json_value ** values; + struct + { + unsigned int length; + struct _json_value ** values; #if defined(__cplusplus) && __cplusplus >= 201103L - decltype(values) begin () const - { - return values; - } - decltype(values) end () const - { - return values + length; - } + decltype(values) begin () const + { + return values; + } + decltype(values) end () const + { + return values + length; + } #endif - } array; + } array; - } u; + } u; - union - { - struct _json_value * next_alloc; - void * object_mem; + union + { + struct _json_value * next_alloc; + void * object_mem; - } _reserved; + } _reserved; - /* Some C++ operator sugar */ + /* Some C++ operator sugar */ #ifdef __cplusplus -public: - - inline _json_value () - { - memset (this, 0, sizeof (_json_value)); - } + public: - inline const struct _json_value &operator [] (int index) const - { - if (type != json_array || index < 0 - || ((unsigned int) index) >= u.array.length) + inline _json_value () { - return json_value_none; + memset (this, 0, sizeof (_json_value)); } - return *u.array.values [index]; - } + inline const struct _json_value &operator [] (int index) const + { + if (type != json_array || index < 0 + || ((unsigned int) index) >= u.array.length) + { + return json_value_none; + } - inline const struct _json_value &operator [] (const char * index) const - { - if (type != json_object) - return json_value_none; + return *u.array.values [index]; + } - for (unsigned int i = 0; i < u.object.length; ++ i) - if (!strcmp (u.object.values [i].name, index)) - return *u.object.values [i].value; + inline const struct _json_value &operator [] (const char * index) const + { + if (type != json_object) + return json_value_none; - return json_value_none; - } + for (unsigned int i = 0; i < u.object.length; ++ i) + if (!strcmp (u.object.values [i].name, index)) + return *u.object.values [i].value; - inline operator const char * () const - { - switch (type) + return json_value_none; + } + + inline operator const char * () const { - case json_string: - return u.string.ptr; + switch (type) + { + case json_string: + return u.string.ptr; - default: - return ""; - }; - } + default: + return ""; + }; + } - inline operator json_int_t () const - { - switch (type) + inline operator json_int_t () const { - case json_integer: - return u.integer; + switch (type) + { + case json_integer: + return u.integer; - case json_double: - return (json_int_t) u.dbl; + case json_double: + return (json_int_t) u.dbl; - default: - return 0; - }; - } + default: + return 0; + }; + } - inline operator bool () const - { - if (type != json_boolean) - return false; + inline operator bool () const + { + if (type != json_boolean) + return false; - return u.boolean != 0; - } + return u.boolean != 0; + } - inline operator double () const - { - switch (type) + inline operator double () const { - case json_integer: - return (double) u.integer; + switch (type) + { + case json_integer: + return (double) u.integer; - case json_double: - return u.dbl; + case json_double: + return u.dbl; - default: - return 0; - }; - } + default: + return 0; + }; + } #endif -} json_value; + } json_value; -json_value * json_parse (const json_char * json, - size_t length); + json_value * json_parse (const json_char * json, + size_t length); #define json_error_max 128 -json_value * json_parse_ex (json_settings * settings, - const json_char * json, - size_t length, - char * error); + json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error); -void json_value_free (json_value *); + void json_value_free (json_value *); -/* Not usually necessary, unless you used a custom mem_alloc and now want to - * use a custom mem_free. - */ -void json_value_free_ex (json_settings * settings, - json_value *); + /* Not usually necessary, unless you used a custom mem_alloc and now want to + * use a custom mem_free. + */ + void json_value_free_ex (json_settings * settings, + json_value *); #ifdef __cplusplus diff --git a/src/local.c b/src/local.c index 3eb14484..46846273 100644 --- a/src/local.c +++ b/src/local.c @@ -85,6 +85,25 @@ static int nofile = 0; #endif #endif +static void server_recv_cb (EV_P_ ev_io *w, int revents); +static void server_send_cb (EV_P_ ev_io *w, int revents); +static void remote_recv_cb (EV_P_ ev_io *w, int revents); +static void remote_send_cb (EV_P_ ev_io *w, int revents); +static void accept_cb (EV_P_ ev_io *w, int revents); +static void signal_cb (EV_P_ ev_signal *w, int revents); + +static int create_and_bind (const char *addr, const char *port); +static struct remote* connect_to_remote (struct listen_ctx *listener, const char *host, const char *port); +static void free_remote (struct remote *remote); +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); + +static struct remote* new_remote (int fd, int timeout); +static struct server* new_server (int fd, int method); + +static TAILQ_HEAD(connection_head, server) connections; + #ifndef __MINGW32__ int setnonblocking(int fd) { @@ -161,6 +180,17 @@ int create_and_bind(const char *addr, const char *port) return listen_sock; } +static void free_connections(struct ev_loop *loop) +{ + struct server *iter; + while ((iter = TAILQ_FIRST(&connections)) != NULL) + { + struct remote *remote = iter->remote; + close_and_free_server(loop, iter); + close_and_free_remote(loop, remote); + } +} + static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct server_ctx *server_recv_ctx = (struct server_ctx *)w; @@ -730,7 +760,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) } } -struct remote* new_remote(int fd, int timeout) +static struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); @@ -787,7 +817,7 @@ static void close_and_free_remote(EV_P_ struct remote *remote) } } -struct server* new_server(int fd, int method) +static struct server* new_server(int fd, int method) { struct server *server; server = malloc(sizeof(struct server)); @@ -816,35 +846,37 @@ struct server* new_server(int fd, int method) server->e_ctx = NULL; server->d_ctx = NULL; } + + TAILQ_INSERT_HEAD(&connections, server, entries); + return server; } static void free_server(struct server *server) { - if (server != NULL) + TAILQ_REMOVE(&connections, server, entries); + + if (server->remote != 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); + 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) @@ -917,6 +949,18 @@ static struct remote* connect_to_remote(struct listen_ctx *listener, return remote; } +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); + } + } +} void accept_cb (EV_P_ ev_io *w, int revents) { @@ -1097,11 +1141,18 @@ int main (int argc, char **argv) #ifdef __MINGW32__ winsock_init(); -#else +#endif + // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGABRT, SIG_IGN); -#endif + + 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 keys LOGD("initialize ciphers... %s", method); @@ -1136,7 +1187,7 @@ int main (int argc, char **argv) listen_ctx.iface = iface; listen_ctx.method = m; - struct ev_loop *loop = ev_default_loop(0); + struct ev_loop *loop = EV_DEFAULT; if (!loop) { FATAL("ev_loop error."); @@ -1148,15 +1199,24 @@ int main (int argc, char **argv) if (udprelay) { LOGD("udprelay enabled."); - udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, m, listen_ctx.timeout, iface); + init_udprelay(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, m, listen_ctx.timeout, iface); } // setuid if (user != NULL) run_as(user); + // Init connections + TAILQ_INIT(&connections); + ev_run (loop, 0); + free_connections(loop); + free_udprelay(); + + ev_io_stop(loop, &listen_ctx.io); + free(listen_ctx.remote_addr); + #ifdef __MINGW32__ winsock_cleanup(); #endif @@ -1198,11 +1258,18 @@ int start_ss_local_server(profile_t profile) #ifdef __MINGW32__ winsock_init(); -#else +#endif + // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGABRT, SIG_IGN); -#endif + + 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 keys LOGD("initialize ciphers... %s", method); @@ -1234,7 +1301,7 @@ int start_ss_local_server(profile_t profile) listen_ctx.method = m; listen_ctx.iface = NULL; - struct ev_loop *loop = ev_default_loop(0); + struct ev_loop *loop = EV_DEFAULT; if (!loop) { FATAL("ev_loop error."); @@ -1246,11 +1313,20 @@ int start_ss_local_server(profile_t profile) if (udprelay) { LOGD("udprelay enabled."); - udprelay_init(local_addr, local_port_str, remote_host, remote_port_str, m, listen_ctx.timeout, NULL); + init_udprelay(local_addr, local_port_str, remote_host, remote_port_str, m, listen_ctx.timeout, NULL); } + // Init connections + TAILQ_INIT(&connections); + ev_run (loop, 0); + free_connections(loop); + free_udprelay(); + + ev_io_stop(loop, &listen_ctx.io); + free(listen_ctx.remote_addr); + #ifdef __MINGW32__ winsock_cleanup(); #endif diff --git a/src/local.h b/src/local.h index f213befa..de792199 100644 --- a/src/local.h +++ b/src/local.h @@ -23,11 +23,12 @@ #ifndef _LOCAL_H #define _LOCAL_H +#include #include #include "encrypt.h" #include "jconf.h" -#include "include.h" +#include "common.h" struct listen_ctx { @@ -61,6 +62,8 @@ struct server struct server_ctx *send_ctx; struct listen_ctx *listener; struct remote *remote; + + TAILQ_ENTRY(server) entries; }; struct remote_ctx @@ -84,21 +87,4 @@ struct remote struct addrinfo *addr_info; }; -// exported for library use -int create_and_bind(const char *addr, const char *port); -void accept_cb (EV_P_ ev_io *w, int revents); - -static struct remote* connect_to_remote(struct listen_ctx *listener, const char *host, const char *port); -static void server_recv_cb (EV_P_ ev_io *w, int revents); -static void server_send_cb (EV_P_ ev_io *w, int revents); -static void remote_recv_cb (EV_P_ ev_io *w, int revents); -static void remote_send_cb (EV_P_ ev_io *w, int revents); -static void free_remote(struct remote *remote); -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); - -struct remote* new_remote(int fd, int timeout); -struct server* new_server(int fd, int method); - #endif // _LOCAL_H diff --git a/src/redir.c b/src/redir.c index 7e445193..dd810c70 100644 --- a/src/redir.c +++ b/src/redir.c @@ -64,6 +64,21 @@ #define IP6T_SO_ORIGINAL_DST 80 #endif +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); +static void remote_recv_cb (EV_P_ ev_io *w, int revents); +static void remote_send_cb (EV_P_ ev_io *w, int revents); + +static struct remote* new_remote(int fd, int timeout); +static struct server* new_server(int fd, int method); + +static void free_remote(struct remote *remote); +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 getdestaddr(int fd, struct sockaddr_storage *destaddr) { socklen_t socklen = sizeof(*destaddr); @@ -510,7 +525,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) } } -struct remote* new_remote(int fd, int timeout) +static struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); @@ -530,7 +545,7 @@ struct remote* new_remote(int fd, int timeout) return remote; } -void free_remote(struct remote *remote) +static void free_remote(struct remote *remote) { if (remote != NULL) { @@ -548,7 +563,7 @@ void free_remote(struct remote *remote) } } -void close_and_free_remote(EV_P_ struct remote *remote) +static void close_and_free_remote(EV_P_ struct remote *remote) { if (remote != NULL) { @@ -560,7 +575,7 @@ void close_and_free_remote(EV_P_ struct remote *remote) } } -struct server* new_server(int fd, int method) +static struct server* new_server(int fd, int method) { struct server *server; server = malloc(sizeof(struct server)); @@ -591,7 +606,7 @@ struct server* new_server(int fd, int method) return server; } -void free_server(struct server *server) +static void free_server(struct server *server) { if (server != NULL) { @@ -619,7 +634,7 @@ void free_server(struct server *server) } } -void close_and_free_server(EV_P_ struct server *server) +static void close_and_free_server(EV_P_ struct server *server) { if (server != NULL) { diff --git a/src/redir.h b/src/redir.h index 99e192c9..e2c9673a 100644 --- a/src/redir.h +++ b/src/redir.h @@ -78,17 +78,4 @@ struct remote struct server *server; }; - -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); -static void remote_recv_cb (EV_P_ ev_io *w, int revents); -static void remote_send_cb (EV_P_ ev_io *w, int revents); -struct remote* new_remote(int fd, int timeout); -void free_remote(struct remote *remote); -void close_and_free_remote(EV_P_ struct remote *remote); -struct server* new_server(int fd, int method); -void free_server(struct server *server); -void close_and_free_server(EV_P_ struct server *server); - #endif // _LOCAL_H diff --git a/src/server.c b/src/server.c index f0ccd789..f626f646 100644 --- a/src/server.c +++ b/src/server.c @@ -62,6 +62,24 @@ #define BUF_SIZE 2048 #endif +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); +static void remote_recv_cb (EV_P_ ev_io *w, int revents); +static void remote_send_cb (EV_P_ ev_io *w, int revents); +static void server_resolve_cb(EV_P_ ev_io *w, int revents); +static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents); + +static struct remote* new_remote(int fd); +static struct server* new_server(int fd, struct listen_ctx *listener); +static struct remote *connect_to_remote(struct addrinfo *res, struct server *server); + +static void free_remote(struct remote *remote); +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 @@ -165,7 +183,7 @@ int create_and_bind(const char *host, const char *port) return listen_sock; } -struct remote *connect_to_remote(struct addrinfo *res, struct server *server) +static struct remote *connect_to_remote(struct addrinfo *res, struct server *server) { int sockfd; int opt = 1; @@ -196,30 +214,38 @@ struct remote *connect_to_remote(struct addrinfo *res, struct server *server) #endif #ifdef TCP_FASTOPEN - if (fast_open) { + if (fast_open) + { ssize_t s = sendto(sockfd, server->buf + server->buf_idx, server->buf_len, MSG_FASTOPEN, res->ai_addr, res->ai_addrlen); - if (s == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (s == -1) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { // The remote server doesn't support tfo or it's the first connection to the server. // It will automatically fall back to conventional TCP. } - else if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT || errno == ENOPROTOOPT) { + else if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT || errno == ENOPROTOOPT) + { LOGE("fast open is not supported on this platform"); connect(sockfd, res->ai_addr, res->ai_addrlen); } - else { + else + { ERROR("sendto"); } } - else if (s < server->buf_len) { + else if (s < server->buf_len) + { server->buf_idx += s; server->buf_len -= s; } - else { + else + { server->buf_idx = 0; server->buf_len = 0; } - } else + } + else #endif connect(sockfd, res->ai_addr, res->ai_addrlen); @@ -799,7 +825,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) } } -struct remote* new_remote(int fd) +static struct remote* new_remote(int fd) { if (verbose) remote_conn++; @@ -821,7 +847,7 @@ struct remote* new_remote(int fd) return remote; } -void free_remote(struct remote *remote) +static void free_remote(struct remote *remote) { if (remote != NULL) { @@ -839,7 +865,7 @@ void free_remote(struct remote *remote) } } -void close_and_free_remote(EV_P_ struct remote *remote) +static void close_and_free_remote(EV_P_ struct remote *remote) { if (remote != NULL) { @@ -855,7 +881,7 @@ void close_and_free_remote(EV_P_ struct remote *remote) } } -struct server* new_server(int fd, struct listen_ctx *listener) +static struct server* new_server(int fd, struct listen_ctx *listener) { if (verbose) server_conn++; @@ -893,7 +919,7 @@ struct server* new_server(int fd, struct listen_ctx *listener) return server; } -void free_server(struct server *server) +static void free_server(struct server *server) { if (server != NULL) { @@ -921,7 +947,7 @@ void free_server(struct server *server) } } -void close_and_free_server(EV_P_ struct server *server) +static void close_and_free_server(EV_P_ struct server *server) { if (server != NULL) { @@ -1180,7 +1206,7 @@ int main (int argc, char **argv) if (udprelay) { LOGD("udprelay enabled."); - udprelay_init(server_host[0], server_port, dns_thread_num, m, listen_ctx->timeout, iface); + init_udprelay(server_host[0], server_port, dns_thread_num, m, listen_ctx->timeout, iface); } // setuid diff --git a/src/server.h b/src/server.h index d56204a9..bd4d2c37 100644 --- a/src/server.h +++ b/src/server.h @@ -30,7 +30,7 @@ #include "jconf.h" #include "asyncns.h" -#include "include.h" +#include "common.h" struct listen_ctx { @@ -85,21 +85,4 @@ struct remote struct server *server; }; - -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); -static void remote_recv_cb (EV_P_ ev_io *w, int revents); -static void remote_send_cb (EV_P_ ev_io *w, int revents); -static void server_resolve_cb(EV_P_ ev_io *w, int revents); -static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents); - -struct remote* new_remote(int fd); -struct remote *connect_to_remote(struct addrinfo *res, struct server *server); -void free_remote(struct remote *remote); -void close_and_free_remote(EV_P_ struct remote *remote); -struct server* new_server(int fd, struct listen_ctx *listener); -void free_server(struct server *server); -void close_and_free_server(EV_P_ struct server *server); - #endif // _SERVER_H diff --git a/src/shadowsocks.h b/src/shadowsocks.h index 6939da10..29b098fb 100644 --- a/src/shadowsocks.h +++ b/src/shadowsocks.h @@ -22,10 +22,11 @@ #ifndef _SHADOWSOCKS_H #define _SHADOWSOCKS_H -typedef struct { +typedef struct +{ /* Required */ char *remote_host; // hostname or ip of remote server - char *local_addr; // local ip to bind + char *local_addr; // local ip to bind char *method; // encryption method char *password; // password of remote server int remote_port; // port number of remote server @@ -59,21 +60,21 @@ const profile_t EXAMPLE_PROFILE = { */ #ifdef __cplusplus -extern "C"{ +extern "C" { #endif -/* - * Create and start a shadowsocks local server. - * - * Calling this function will block the current thread forever if the server - * starts successfully. - * - * Make sure start the server in a seperate process to avoid any potential - * memory and socket leak. - * - * If failed, -1 is returned. Errors will output to the log file. -*/ -int start_ss_local_server(profile_t profile); + /* + * Create and start a shadowsocks local server. + * + * Calling this function will block the current thread forever if the server + * starts successfully. + * + * Make sure start the server in a seperate process to avoid any potential + * memory and socket leak. + * + * If failed, -1 is returned. Errors will output to the log file. + */ + int start_ss_local_server(profile_t profile); #ifdef __cplusplus } diff --git a/src/tunnel.c b/src/tunnel.c index 8a7cd8fe..26332de7 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -67,6 +67,20 @@ #define BUF_SIZE 2048 #endif +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); +static void remote_recv_cb (EV_P_ ev_io *w, int revents); +static void remote_send_cb (EV_P_ ev_io *w, int revents); + +static struct remote* new_remote(int fd, int timeout); +static struct server* new_server(int fd, int method); + +static void free_remote(struct remote *remote); +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; @@ -508,7 +522,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) } } -struct remote* new_remote(int fd, int timeout) +static struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); @@ -558,7 +572,7 @@ static void close_and_free_remote(EV_P_ struct remote *remote) } } -struct server* new_server(int fd, int method) +static struct server* new_server(int fd, int method) { struct server *server; server = malloc(sizeof(struct server)); @@ -866,7 +880,7 @@ int main (int argc, char **argv) if (udprelay) { LOGD("udprelay enabled."); - udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, + init_udprelay(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, tunnel_addr, m, listen_ctx.timeout, iface); } diff --git a/src/tunnel.h b/src/tunnel.h index 8bfc8ba2..d2dced58 100644 --- a/src/tunnel.h +++ b/src/tunnel.h @@ -27,7 +27,7 @@ #include "encrypt.h" #include "jconf.h" -#include "include.h" +#include "common.h" struct listen_ctx { @@ -82,17 +82,4 @@ struct remote struct server *server; }; -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); -static void remote_recv_cb (EV_P_ ev_io *w, int revents); -static void remote_send_cb (EV_P_ ev_io *w, int revents); -static void free_remote(struct remote *remote); -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); - -struct remote* new_remote(int fd, int timeout); -struct server* new_server(int fd, int method); - #endif // _TUNNEL_H diff --git a/src/udprelay.c b/src/udprelay.c index 271952dd..fbb9d614 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -81,6 +81,9 @@ extern int verbose; +static struct server_ctx *server_ctx = NULL; +struct resolve_ctx *resolve_ctx = NULL; + #ifndef __MINGW32__ static int setnonblocking(int fd) { @@ -895,7 +898,7 @@ void free_cb(void *element) close_and_free_remote(EV_DEFAULT, remote_ctx); } -int udprelay_init(const char *server_host, const char *server_port, +int init_udprelay(const char *server_host, const char *server_port, #ifdef UDPRELAY_LOCAL const char *remote_host, const char *remote_port, #ifdef UDPRELAY_TUNNEL @@ -907,7 +910,6 @@ int udprelay_init(const char *server_host, const char *server_port, #endif int method, int timeout, const char *iface) { - // Inilitialize ev loop struct ev_loop *loop = EV_DEFAULT; @@ -925,7 +927,7 @@ int udprelay_init(const char *server_host, const char *server_port, { FATAL("asyncns failed"); } - struct resolve_ctx *resolve_ctx = malloc(sizeof(struct resolve_ctx)); + resolve_ctx = malloc(sizeof(struct resolve_ctx)); resolve_ctx->asyncns = asyncns; int asyncnsfd = asyncns_fd(asyncns); @@ -941,7 +943,7 @@ int udprelay_init(const char *server_host, const char *server_port, } setnonblocking(serverfd); - struct server_ctx *server_ctx = new_server_ctx(serverfd); + server_ctx = new_server_ctx(serverfd); server_ctx->timeout = timeout; server_ctx->method = method; server_ctx->iface = iface; @@ -962,3 +964,24 @@ int udprelay_init(const char *server_host, const char *server_port, return 0; } +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); + free(resolve_ctx); + resolve_ctx = NULL; + } +#endif + if (server_ctx != NULL) + { + ev_io_stop(loop, &server_ctx->io); + close(server_ctx->fd); + cache_delete(server_ctx->conn_cache, 0); + free(server_ctx); + server_ctx = NULL; + } +} diff --git a/src/udprelay.h b/src/udprelay.h index 3f347540..83693db1 100644 --- a/src/udprelay.h +++ b/src/udprelay.h @@ -35,7 +35,7 @@ #include "cache.h" -#include "include.h" +#include "common.h" #define MAX_UDP_PACKET_SIZE (64 * 1024) @@ -47,7 +47,6 @@ struct server_ctx int timeout; const char *iface; struct cache *conn_cache; - char *buf; // server send from, remote recv into #ifdef UDPRELAY_REMOTE asyncns_t *asyncns; #endif