From 75efb498e3a5891200e77f9b26e266746d3a971f Mon Sep 17 00:00:00 2001 From: Max Lv Date: Sun, 31 Mar 2013 21:17:17 +0800 Subject: [PATCH] fix the bug in server end --- jconf.c | 14 ++--- local.c | 22 +++---- server.c | 170 +++++++++++++++++++++++++++++++------------------------ utils.h | 19 ++++++- 4 files changed, 130 insertions(+), 95 deletions(-) diff --git a/jconf.c b/jconf.c index 999d7875..3bac630d 100644 --- a/jconf.c +++ b/jconf.c @@ -16,8 +16,8 @@ static char *to_string(const json_value *value) { } else if (value->type == json_null) { return "null"; } else { - LOGE("%d\n", value->type); - FATAL("Invalid config format.\n"); + LOGE("%d", value->type); + FATAL("Invalid config format."); } return 0; } @@ -28,7 +28,7 @@ static int to_int(const json_value *value) { } else if (value->type == json_integer) { return value->u.integer; } else { - FATAL("Invalid config format.\n"); + FATAL("Invalid config format."); } return 0; } @@ -41,16 +41,16 @@ jconf_t *read_jconf(const char* file) { json_value *obj; FILE *f = fopen(file, "r"); - if (f == NULL) FATAL("Invalid config path.\n"); + if (f == NULL) FATAL("Invalid config path."); fseek(f, 0, SEEK_END); long pos = ftell(f); fseek(f, 0, SEEK_SET); - if (pos >= MAX_CONF_SIZE) FATAL("Too large config file.\n"); + if (pos >= MAX_CONF_SIZE) FATAL("Too large config file."); buf = malloc(pos); - if (buf == NULL) FATAL("No enough memory.\n"); + if (buf == NULL) FATAL("No enough memory."); fread(buf, pos, 1, f); fclose(f); @@ -86,7 +86,7 @@ jconf_t *read_jconf(const char* file) { } } } else { - FATAL("Invalid config file\n"); + FATAL("Invalid config file"); } free(buf); diff --git a/local.c b/local.c index 5dddcddd..1f9d3bc0 100644 --- a/local.c +++ b/local.c @@ -54,7 +54,7 @@ int create_and_bind(const char *port) { s = getaddrinfo("0.0.0.0", port, &hints, &result); if (s != 0) { - LOGD("getaddrinfo: %s\n", gai_strerror(s)); + LOGD("getaddrinfo: %s", gai_strerror(s)); return -1; } @@ -81,7 +81,7 @@ int create_and_bind(const char *port) { } if (rp == NULL) { - LOGE("Could not bind\n"); + LOGE("Could not bind"); return -1; } @@ -172,7 +172,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct socks5_request *request = (struct socks5_request *)server->buf; if (request->cmd != 1) { - LOGE("unsupported cmd: %d\n", request->cmd); + LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; response.ver = SVERSION; response.rep = CMD_NOT_SUPPORTED; @@ -208,7 +208,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { addr_to_send[addr_len++] = *(uint8_t *)(server->buf + 4 + 1 + name_len); addr_to_send[addr_len++] = *(uint8_t *)(server->buf + 4 + 1 + name_len + 1); } else { - LOGE("unsupported addrtype: %d\n", request->atyp); + LOGE("unsupported addrtype: %d", request->atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; @@ -233,7 +233,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { int reply_size = 4 + sizeof(struct in_addr) + sizeof(uint16_t); int s = send(server->fd, server->buf, reply_size, 0); if (s < reply_size) { - LOGE("header not complete sent\n"); + LOGE("header not complete sent"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; @@ -295,7 +295,7 @@ static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) { struct remote *remote = remote_ctx->remote; struct server *server = remote->server; - LOGD("remote timeout\n"); + LOGD("remote timeout"); ev_timer_stop(EV_A_ watcher); @@ -661,20 +661,20 @@ int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); // Setup keys - LOGD("calculating ciphers...\n"); + LOGD("calculating ciphers..."); enc_conf_init(password, method); // Setup socket int listenfd; listenfd = create_and_bind(local_port); if (listenfd < 0) { - FATAL("bind() error..\n"); + FATAL("bind() error.."); } if (listen(listenfd, SOMAXCONN) == -1) { - FATAL("listen() error.\n"); + FATAL("listen() error."); } setnonblocking(listenfd); - LOGD("server listening at port %s.\n", local_port); + LOGD("server listening at port %s.", local_port); // Setup proxy context struct listen_ctx listen_ctx; @@ -690,7 +690,7 @@ int main (int argc, char **argv) { struct ev_loop *loop = ev_default_loop(0); if (!loop) { - FATAL("ev_loop error.\n"); + FATAL("ev_loop error."); } ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ); ev_io_start (loop, &listen_ctx.io); diff --git a/server.c b/server.c index c7c6a671..e2d177e2 100644 --- a/server.c +++ b/server.c @@ -36,6 +36,8 @@ #define min(a,b) (((a)<(b))?(a):(b)) static int verbose = 0; +static int remote_conn = 0; +static int server_conn = 0; int setnonblocking(int fd) { int flags; @@ -55,7 +57,7 @@ int create_and_bind(const char *host, const char *port) { s = getaddrinfo(host, port, &hints, &result); if (s != 0) { - LOGE("getaddrinfo: %s\n", gai_strerror(s)); + LOGE("getaddrinfo: %s", gai_strerror(s)); return -1; } @@ -82,7 +84,7 @@ int create_and_bind(const char *host, const char *port) { } if (rp == NULL) { - LOGE("Could not bind\n"); + LOGE("Could not bind"); return -1; } @@ -104,6 +106,7 @@ struct remote *connect_to_remote(char *remote_host, char *remote_port, int timeo return NULL; } + // initilize remote socks sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { @@ -113,11 +116,10 @@ struct remote *connect_to_remote(char *remote_host, char *remote_port, int timeo return NULL; } - // setup remote socks - setnonblocking(sockfd); - struct remote *remote = new_remote(sockfd, timeout); + // setup remote socks + setnonblocking(sockfd); connect(sockfd, res->ai_addr, res->ai_addrlen); // release addrinfo @@ -133,19 +135,16 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct remote *remote = NULL; char *buf = server->buf; - int *buf_len = &server->buf_len; - if (server->stage == 5) { + if (server->stage != 0) { remote = server->remote; buf = remote->buf; - buf_len = &remote->buf_len; } ssize_t r = recv(server->fd, buf, BUF_SIZE, 0); if (r == 0) { // connection closed - *buf_len = 0; close_and_free_server(EV_A_ server); if (remote != NULL) { ev_io_start(EV_A_ &remote->send_ctx->io); @@ -180,7 +179,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); } - return; } else if (s < r) { char *pt = remote->buf; char *et = pt + r; @@ -192,8 +190,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { assert(remote->buf_len >= 0); ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io); - return; } + return; } else if (server->stage == 0) { /* @@ -209,8 +207,9 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { int offset = 0; char atyp = server->buf[offset++]; char host[256]; + char port[64]; memset(host, 0, 256); - int port = 0; + int p = 0; // get remote addr and port if (atyp == 1) { @@ -227,36 +226,47 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { offset += name_len + 1; } else { - LOGE("unsupported addrtype: %d\n", atyp); + LOGE("unsupported addrtype: %d", atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } - port += *(uint8_t *)(server->buf + offset++) << 8; - port += *(uint8_t *)(server->buf + offset); + p += *(uint8_t *)(server->buf + offset++) << 8; + p += *(uint8_t *)(server->buf + offset++); + + sprintf(port, "%d", p); if (verbose) { - LOGD("connect to: %s:%s\n", host, itoa(port)); + LOGD("connect to: %s:%s", host, port); } - struct remote *remote = connect_to_remote(host, itoa(port), server->timeout); + struct remote *remote = connect_to_remote(host, port, server->timeout); if (remote == NULL) { close_and_free_server(EV_A_ server); return; } + server->remote = remote; + remote->server = server; + // listen to remote connected event - ev_io_stop(EV_A_ &server->recv_ctx->io); + ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io); ev_timer_start(EV_A_ &remote->send_ctx->watcher); - remote->server = server; - server->remote = remote; + // XXX: should handel buffer carefully + if (r > offset) { + remote->buf_len = r - offset; + memcpy(remote->buf, server->buf + offset, remote->buf_len); + } server->stage = 4; + return; } + // should not reach here + FATAL("server context error."); } static void server_send_cb (EV_P_ ev_io *w, int revents) { @@ -297,6 +307,7 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) { ev_io_stop(EV_A_ &server_send_ctx->io); if (remote != NULL) { ev_io_start(EV_A_ &remote->recv_ctx->io); + return; } else { LOGE("invalid remote."); close_and_free_remote(EV_A_ remote); @@ -313,7 +324,7 @@ static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) { struct remote *remote = remote_ctx->remote; struct server *server = remote->server; - LOGE("remote timeout\n"); + LOGE("remote timeout"); ev_timer_stop(EV_A_ watcher); @@ -327,7 +338,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { struct server *server = remote->server; if (server == NULL) { - LOGE("invalid server.\n"); + LOGE("invalid server."); close_and_free_remote(EV_A_ remote); return; } @@ -335,7 +346,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { ssize_t r = recv(remote->fd, server->buf, BUF_SIZE, 0); if (verbose) { - LOGD("remote recv: %d byte\n", (int)r); + LOGD("remote recv: %d byte", (int)r); } if (r == 0) { @@ -400,18 +411,20 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { int r = getpeername(remote->fd, (struct sockaddr*)&addr, &len); if (r == 0) { if (verbose) { - LOGD("remote connected.\n"); + LOGD("remote connected."); } remote_send_ctx->connected = 1; - ev_io_stop(EV_A_ &remote_send_ctx->io); - ev_io_stop(EV_A_ &server->send_ctx->io); ev_timer_stop(EV_A_ &remote_send_ctx->watcher); - ev_io_start(EV_A_ &server->recv_ctx->io); ev_io_start(EV_A_ &remote->recv_ctx->io); - server->stage = 5; - return; + + if (remote->buf_len == 0) { + ev_io_stop(EV_A_ &remote_send_ctx->io); + ev_io_start(EV_A_ &server->recv_ctx->io); + return; + } + } else { perror("getpeername"); // not connected @@ -419,53 +432,54 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { close_and_free_server(EV_A_ server); return; } + } + + if (remote->buf_len == 0) { + // close and free + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; } else { - if (remote->buf_len == 0) { - // close and free - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); + // has data to send + ssize_t s = send(remote->fd, remote->buf, + remote->buf_len, 0); + if (s < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + perror("remote_send_send"); + // close and free + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + } + return; + } else if (s < remote->buf_len) { + // partly sent, move memory, wait for the next time to send + char *pt = remote->buf; + char *et = pt + remote->buf_len; + while (pt + s < et) { + *pt = *(pt + s); + pt++; + } + remote->buf_len -= s; + assert(remote->buf_len >= 0); return; } else { - // has data to send - ssize_t s = send(remote->fd, remote->buf, - remote->buf_len, 0); - if (s < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - perror("remote_send_send"); - // close and free - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - } - return; - } else if (s < remote->buf_len) { - // partly sent, move memory, wait for the next time to send - char *pt = remote->buf; - char *et = pt + remote->buf_len; - while (pt + s < et) { - *pt = *(pt + s); - pt++; - } - remote->buf_len -= s; - assert(remote->buf_len >= 0); - return; + // all sent out, wait for reading + remote->buf_len = 0; + ev_io_stop(EV_A_ &remote_send_ctx->io); + if (server != NULL) { + ev_io_start(EV_A_ &server->recv_ctx->io); } else { - // all sent out, wait for reading - remote->buf_len = 0; - ev_io_stop(EV_A_ &remote_send_ctx->io); - if (server != NULL) { - ev_io_start(EV_A_ &server->recv_ctx->io); - } else { - LOGE("invalid server.\n"); - close_and_free_remote(EV_A_ remote); - close_and_free_server(EV_A_ server); - return; - } + LOGE("invalid server."); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); } + return; } } } struct remote* new_remote(int fd, int timeout) { + remote_conn++; struct remote *remote; remote = malloc(sizeof(struct remote)); remote->recv_ctx = malloc(sizeof(struct remote_ctx)); @@ -483,6 +497,7 @@ struct remote* new_remote(int fd, int timeout) { } void free_remote(struct remote *remote) { + remote_conn--; if (remote != NULL) { if (remote->server != NULL) { remote->server->remote = NULL; @@ -501,9 +516,13 @@ void close_and_free_remote(EV_P_ struct remote *remote) { close(remote->fd); free_remote(remote); } + if (verbose) { + LOGD("current remote connection: %d", remote_conn); + } } struct server* new_server(int fd) { + server_conn++; struct server *server; server = malloc(sizeof(struct server)); server->recv_ctx = malloc(sizeof(struct server_ctx)); @@ -530,6 +549,7 @@ struct server* new_server(int fd) { } void free_server(struct server *server) { + server_conn--; if (server != NULL) { if (server->remote != NULL) { server->remote->server = NULL; @@ -551,6 +571,9 @@ void close_and_free_server(EV_P_ struct server *server) { close(server->fd); free_server(server); } + if (verbose) { + LOGD("current server connection: %d", server_conn); + } } static void accept_cb (EV_P_ ev_io *w, int revents) { @@ -563,7 +586,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) { setnonblocking(serverfd); if (verbose) { - LOGD("accept a connection.\n"); + LOGD("accept a connection."); } struct server *server = new_server(serverfd); @@ -650,14 +673,11 @@ int main (int argc, char **argv) { signal(SIGPIPE, SIG_IGN); // Setup keys - LOGD("calculating ciphers...\n"); + LOGD("calculating ciphers..."); enc_conf_init(password, method); // Inilitialize ev loop - struct ev_loop *loop = ev_default_loop(0); - if (!loop) { - FATAL("ev_loop error.\n"); - } + struct ev_loop *loop = EV_DEFAULT; // bind to each interface while (server_num > 0) { @@ -668,13 +688,13 @@ int main (int argc, char **argv) { int listenfd; listenfd = create_and_bind(host, server_port); if (listenfd < 0) { - FATAL("bind() error..\n"); + FATAL("bind() error.."); } if (listen(listenfd, SOMAXCONN) == -1) { - FATAL("listen() error.\n"); + FATAL("listen() error."); } setnonblocking(listenfd); - LOGD("server listening at port %s.\n", server_port); + LOGD("server listening at port %s.", server_port); // Setup proxy context struct listen_ctx listen_ctx; diff --git a/utils.h b/utils.h index 8e700bd9..1c2515da 100644 --- a/utils.h +++ b/utils.h @@ -1,8 +1,23 @@ #ifndef _UTILS_H #define _UTILS_H -#define LOGD(...) ((void)fprintf(stdout, __VA_ARGS__)) -#define LOGE(...) ((void)fprintf(stderr, __VA_ARGS__)) +#define STR(x) #x +#define TOSTR(x) STR(x) +#define TIME_FORMAT "%F %T" + +#define LOGD(format, ...) do {\ + time_t now = time(NULL);\ + char timestr[20];\ + strftime(timestr, 20, TIME_FORMAT, localtime(&now));\ + fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, ##__VA_ARGS__);}\ +while(0) + +#define LOGE(format, ...) do {\ + time_t now = time(NULL);\ + char timestr[20];\ + strftime(timestr, 20, TIME_FORMAT, localtime(&now));\ + fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format " on File: %s Line: %s\n", timestr, ##__VA_ARGS__, __FILE__, TOSTR(__LINE__));}\ +while(0) void FATAL(const char *msg); void usage(void);