Browse Source

handle sigterm and sigkill

pull/148/head
Max Lv 10 years ago
parent
commit
08a35fd1bb
15 changed files with 390 additions and 290 deletions
  1. 3
      src/acl.c
  2. 6
      src/common.h
  3. 4
      src/json.c
  4. 288
      src/json.h
  5. 140
      src/local.c
  6. 22
      src/local.h
  7. 27
      src/redir.c
  8. 13
      src/redir.h
  9. 58
      src/server.c
  10. 19
      src/server.h
  11. 31
      src/shadowsocks.h
  12. 20
      src/tunnel.c
  13. 15
      src/tunnel.h
  14. 31
      src/udprelay.c
  15. 3
      src/udprelay.h

3
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;
}

src/include.h → src/common.h

@ -1,5 +1,5 @@
/*
* include.h - Provide global definitions
* common.h - Provide global definitions
*
* Copyright (C) 2013 - 2014, Max Lv <max.c.lv@gmail.com>
*
@ -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

4
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;
}

288
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

140
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

22
src/local.h

@ -23,11 +23,12 @@
#ifndef _LOCAL_H
#define _LOCAL_H
#include <sys/queue.h>
#include <ev.h>
#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

27
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)
{

13
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

58
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

19
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

31
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
}

20
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);
}

15
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

31
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;
}
}

3
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

Loading…
Cancel
Save