diff --git a/Makefile b/Makefile index 0d1e44f..1104290 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TARGET = ciadpi CPPFLAGS = -D_DEFAULT_SOURCE -CFLAGS += -I. -std=c99 -O2 -Wall -Wno-unused -Wextra -pedantic +CFLAGS += -I. -std=c99 -O2 -Wall -Wno-unused -Wextra -Wno-unused-parameter -pedantic WIN_LDFLAGS = -lws2_32 -lmswsock HEADERS = conev.h desync.h error.h extend.h kavl.h mpool.h packets.h params.h proxy.h win_service.h diff --git a/conev.c b/conev.c index f4c6d49..e2db92b 100644 --- a/conev.c +++ b/conev.c @@ -43,7 +43,7 @@ struct poolhd *init_pool(int count) } -struct eval *add_event(struct poolhd *pool, enum eid type, +struct eval *add_event(struct poolhd *pool, evcb_t cb, int fd, int e) { assert(fd > 0); @@ -57,7 +57,7 @@ struct eval *add_event(struct poolhd *pool, enum eid type, val->mod_iter = pool->iters; val->fd = fd; val->index = pool->count; - val->type = type; + val->cb = cb; #ifndef NOEPOLL struct epoll_event ev = { .events = EPOLLRDHUP | e, .data = {val} }; @@ -81,6 +81,9 @@ struct eval *add_event(struct poolhd *pool, enum eid type, void del_event(struct poolhd *pool, struct eval *val) { assert(val->fd >= -1 && val->mod_iter <= pool->iters); + LOG(LOG_S, "close: fd=%d (pair=%d), recv: %zd, rounds: %d\n", + val->fd, val->pair ? val->pair->fd : -1, + val->recv_count, val->round_count); if (val->fd == -1) { return; } @@ -117,7 +120,7 @@ void del_event(struct poolhd *pool, struct eval *val) val->pair = 0; del_event(pool, e); } - assert(pool->count > 0); + assert(pool->count >= 0); } @@ -214,6 +217,26 @@ int mod_etype(struct poolhd *pool, struct eval *val, int type) #endif +void loop_event(struct poolhd *pool) +{ + struct eval *val; + int i = -1, etype; + + while (!pool->brk) { + val = next_event(pool, &i, &etype); + if (!val) { + if (get_e() == EINTR) + continue; + uniperror("(e)poll"); + break; + } + int ret = (*val->cb)(pool, val, etype); + if (ret < 0) { + del_event(pool, val); + } + } +} + struct buffer *buff_get(struct buffer *root, size_t size) { struct buffer *prev = root; diff --git a/conev.h b/conev.h index 0d280f4..2eac303 100644 --- a/conev.h +++ b/conev.h @@ -33,39 +33,21 @@ #define POLLRDHUP 0 #endif +struct poolhd; +struct eval; +typedef int (*evcb_t)(struct poolhd *, struct eval *, int); + union sockaddr_u { struct sockaddr sa; struct sockaddr_in in; struct sockaddr_in6 in6; }; -enum eid { - EV_ACCEPT, - EV_REQUEST, - EV_CONNECT, - EV_IGNORE, - EV_TUNNEL, - EV_UDP_TUNNEL, - EV_FIRST_TUNNEL -}; - #define FLAG_S4 1 #define FLAG_S5 2 #define FLAG_CONN 4 #define FLAG_HTTP 8 -#ifdef EID_STR -char *eid_name[] = { - "EV_ACCEPT", - "EV_REQUEST", - "EV_CONNECT", - "EV_IGNORE", - "EV_TUNNEL", - "EV_UDP_TUNNEL", - "EV_FIRST_TUNNEL" -}; -#endif - struct buffer { size_t size; unsigned int offset; @@ -78,7 +60,7 @@ struct eval { int fd; int index; unsigned long long mod_iter; - enum eid type; + evcb_t cb; struct eval *pair; struct buffer *buff; int flag; @@ -103,12 +85,14 @@ struct poolhd { struct pollfd *pevents; #endif unsigned long long iters; + bool brk; + struct buffer *root_buff; }; struct poolhd *init_pool(int count); -struct eval *add_event(struct poolhd *pool, enum eid type, int fd, int e); +struct eval *add_event(struct poolhd *pool, evcb_t cb, int fd, int e); struct eval *add_pair(struct poolhd *pool, struct eval *val, int sfd, int e); @@ -120,6 +104,8 @@ struct eval *next_event(struct poolhd *pool, int *offs, int *type); int mod_etype(struct poolhd *pool, struct eval *val, int type); +void loop_event(struct poolhd *pool); + struct buffer *buff_get(struct buffer *root, size_t size); void buff_destroy(struct buffer *root); diff --git a/extend.c b/extend.c index 0ed1380..d4cc709 100644 --- a/extend.c +++ b/extend.c @@ -125,7 +125,7 @@ static int cache_add(const union sockaddr_u *dst, int m) int connect_hook(struct poolhd *pool, struct eval *val, - const union sockaddr_u *dst, int next) + const union sockaddr_u *dst, evcb_t next) { int m = cache_get(dst); val->cache = (m == 0); @@ -155,7 +155,7 @@ static int reconnect(struct poolhd *pool, struct eval *val, int m) struct eval *client = val->pair; - if (create_conn(pool, client, &val->addr, EV_FIRST_TUNNEL)) { + if (create_conn(pool, client, &val->addr, &on_first_tunnel)) { return -1; } val->pair = 0; @@ -345,8 +345,8 @@ static int on_response(struct poolhd *pool, struct eval *val, static inline void free_first_req(struct eval *client) { - client->type = EV_TUNNEL; - client->pair->type = EV_TUNNEL; + client->cb = &on_tunnel; + client->pair->cb = &on_tunnel; client->buff->lock = 0; client->buff->offset = 0; } @@ -429,7 +429,7 @@ int on_first_tunnel(struct poolhd *pool, struct eval *val, int etype) uniperror("mod_etype"); return -1; } - val->pair->type = EV_FIRST_TUNNEL; + val->pair->cb = &on_first_tunnel; return send_saved_req(pool, val->pair); } ssize_t n = tcp_recv_hook(pool, val, buff); diff --git a/extend.h b/extend.h index 6e8d916..e940a31 100644 --- a/extend.h +++ b/extend.h @@ -8,7 +8,7 @@ int socket_mod(int fd); int connect_hook(struct poolhd *pool, struct eval *val, - const union sockaddr_u *dst, int next); + const union sockaddr_u *dst, evcb_t next); ssize_t tcp_send_hook(struct poolhd *pool, struct eval *remote, struct buffer *buff, ssize_t n); diff --git a/proxy.c b/proxy.c index 9454d1f..f96a86b 100644 --- a/proxy.c +++ b/proxy.c @@ -1,5 +1,3 @@ -#define EID_STR - #include "proxy.h" #include @@ -43,10 +41,10 @@ #endif -int NOT_EXIT = 1; +int server_fd; static void on_cancel(int sig) { - if (sig) NOT_EXIT = 0; + shutdown(server_fd, SHUT_RDWR); } @@ -401,7 +399,7 @@ static int remote_sock(union sockaddr_u *dst, int type) int create_conn(struct poolhd *pool, - struct eval *val, const union sockaddr_u *dst, int next) + struct eval *val, const union sockaddr_u *dst, evcb_t next) { union sockaddr_u addr = *dst; @@ -466,7 +464,7 @@ int create_conn(struct poolhd *pool, pair->addr = *dst; #endif pair->flag = FLAG_CONN; - val->type = EV_IGNORE; + val->cb = &on_ignore; return 0; } @@ -480,7 +478,7 @@ static int udp_associate(struct poolhd *pool, if (ufd < 0) { return -1; } - struct eval *pair = add_event(pool, EV_UDP_TUNNEL, ufd, POLLIN); + struct eval *pair = add_event(pool, &on_udp_tunnel, ufd, POLLIN); if (!pair) { close(ufd); return -1; @@ -514,7 +512,7 @@ static int udp_associate(struct poolhd *pool, close(cfd); return -1; } - struct eval *client = add_event(pool, EV_UDP_TUNNEL, cfd, POLLIN); + struct eval *client = add_event(pool, &on_udp_tunnel, cfd, POLLIN); if (!client) { del_event(pool, pair); close(cfd); @@ -525,7 +523,7 @@ static int udp_associate(struct poolhd *pool, LOG(LOG_S, "udp associate: fds=%d,%d,%d addr=%s:%d\n", ufd, cfd, val->fd, ADDR_STR, ntohs(dst->in.sin_port)); } - val->type = EV_IGNORE; + val->cb = &on_ignore; val->pair = client; client->pair = pair; pair->pair = val; @@ -581,7 +579,7 @@ static inline int transp_conn(struct poolhd *pool, struct eval *val) LOG(LOG_E, "connect to self, ignore\n"); return -1; } - int error = connect_hook(pool, val, &remote, EV_CONNECT); + int error = connect_hook(pool, val, &remote, &on_connect); if (error) { uniperror("connect_hook"); return -1; @@ -590,7 +588,7 @@ static inline int transp_conn(struct poolhd *pool, struct eval *val) } #endif -static int on_accept(struct poolhd *pool, const struct eval *val) +static int on_accept(struct poolhd *pool, struct eval *val, int et) { union sockaddr_u client; struct eval *rval; @@ -607,6 +605,7 @@ static int on_accept(struct poolhd *pool, const struct eval *val) get_e() == EINPROGRESS) break; uniperror("accept"); + pool->brk = 1; return -1; } LOG(LOG_S, "accept: fd=%d\n", c); @@ -630,7 +629,7 @@ static int on_accept(struct poolhd *pool, const struct eval *val) close(c); continue; } - if (!(rval = add_event(pool, EV_REQUEST, c, POLLIN))) { + if (!(rval = add_event(pool, &on_request, c, POLLIN))) { close(c); continue; } @@ -646,7 +645,7 @@ static int on_accept(struct poolhd *pool, const struct eval *val) } -static int on_tunnel(struct poolhd *pool, struct eval *val, int etype) +int on_tunnel(struct poolhd *pool, struct eval *val, int etype) { ssize_t n = 0; struct eval *pair = val->pair; @@ -714,7 +713,7 @@ static int on_tunnel(struct poolhd *pool, struct eval *val, int etype) } -static int on_udp_tunnel(struct poolhd *pool, struct eval *val) +int on_udp_tunnel(struct poolhd *pool, struct eval *val, int et) { struct buffer *buff = buff_get(pool->root_buff, params.bfsize); @@ -800,7 +799,7 @@ static int on_udp_tunnel(struct poolhd *pool, struct eval *val) } -static inline int on_request(struct poolhd *pool, struct eval *val) +int on_request(struct poolhd *pool, struct eval *val, int et) { union sockaddr_u dst = {0}; struct buffer *buff = buff_get(pool->root_buff, params.bfsize); @@ -830,7 +829,7 @@ static inline int on_request(struct poolhd *pool, struct eval *val) case S_CMD_CONN: s5e = s5_get_addr(buff->data, n, &dst, SOCK_STREAM); if (s5e >= 0) { - error = connect_hook(pool, val, &dst, EV_CONNECT); + error = connect_hook(pool, val, &dst, &on_connect); } break; case S_CMD_AUDP: @@ -861,7 +860,7 @@ static inline int on_request(struct poolhd *pool, struct eval *val) uniperror("send"); return -1; } - error = connect_hook(pool, val, &dst, EV_CONNECT); + error = connect_hook(pool, val, &dst, &on_connect); } else if (params.http_connect && n > 7 && !memcmp(buff->data, "CONNECT", 7)) { @@ -870,7 +869,7 @@ static inline int on_request(struct poolhd *pool, struct eval *val) if (http_get_addr(buff->data, n, &dst)) { return -1; } - error = connect_hook(pool, val, &dst, EV_CONNECT); + error = connect_hook(pool, val, &dst, &on_connect); } else { LOG(LOG_E, "ss: invalid version: 0x%x (%zd)\n", *buff->data, n); @@ -887,11 +886,11 @@ static inline int on_request(struct poolhd *pool, struct eval *val) } -static inline int on_connect(struct poolhd *pool, struct eval *val, int e) +int on_connect(struct poolhd *pool, struct eval *val, int et) { int error = 0; socklen_t len = sizeof(error); - if (e) { + if (et & POLLERR) { if (getsockopt(val->fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len)) { uniperror("getsockopt SO_ERROR"); @@ -904,43 +903,36 @@ static inline int on_connect(struct poolhd *pool, struct eval *val, int e) uniperror("mod_etype"); return -1; } - int t = params.auto_level <= AUTO_NOBUFF - ? EV_TUNNEL : EV_FIRST_TUNNEL; - val->type = t; - val->pair->type = t; + evcb_t t = params.auto_level <= AUTO_NOBUFF + ? &on_tunnel : &on_first_tunnel; + val->cb = t; + val->pair->cb = t; } if (resp_error(val->pair->fd, error, val->pair->flag) < 0) { uniperror("send"); return -1; } - return e ? -1 : 0; + return error ? -1 : 0; } -static void close_conn(struct poolhd *pool, struct eval *val) +int on_ignore(struct poolhd *pool, struct eval *val, int etype) { - struct eval *cval = val; - do { - LOG(LOG_S, "close: fd=%d (pair=%d), recv: %zd, rounds: %d\n", - cval->fd, cval->pair ? cval->pair->fd : -1, - cval->recv_count, cval->round_count); - cval = cval->pair; - } while (cval && cval != val); - del_event(pool, val); + return (etype & (POLLHUP | POLLERR)) ? -1 : 0; } -int event_loop(int srvfd) +int start_event_loop(int srvfd) { - size_t bfsize = params.bfsize; + server_fd = srvfd; struct poolhd *pool = init_pool(params.max_open * 2 + 1); if (!pool) { close(srvfd); return -1; } - if (!add_event(pool, EV_ACCEPT, srvfd, POLLIN)) { + if (!add_event(pool, &on_accept, srvfd, POLLIN)) { destroy_pool(pool); close(srvfd); return -1; @@ -950,65 +942,8 @@ int event_loop(int srvfd) destroy_pool(pool); return -1; } + loop_event(pool); - struct eval *val; - int i = -1, etype; - - while (NOT_EXIT) { - val = next_event(pool, &i, &etype); - if (!val) { - if (get_e() == EINTR) - continue; - uniperror("(e)poll"); - break; - } - assert(val->type >= 0 - && val->type < sizeof(eid_name)/sizeof(*eid_name)); - LOG(LOG_L, "new event: fd: %d, evt: %s, mod_iter: %llu\n", val->fd, eid_name[val->type], val->mod_iter); - - switch (val->type) { - case EV_ACCEPT: - if ((etype & POLLHUP) || - on_accept(pool, val)) - NOT_EXIT = 0; - continue; - - case EV_REQUEST: - if ((etype & POLLHUP) || - on_request(pool, val)) - close_conn(pool, val); - continue; - - case EV_FIRST_TUNNEL: - if (on_first_tunnel(pool, val, etype)) - close_conn(pool, val); - continue; - - case EV_TUNNEL: - if (on_tunnel(pool, val, etype)) - close_conn(pool, val); - continue; - - case EV_UDP_TUNNEL: - if (on_udp_tunnel(pool, val)) - close_conn(pool, val); - continue; - - case EV_CONNECT: - if (on_connect(pool, val, etype & POLLERR)) - close_conn(pool, val); - continue; - - case EV_IGNORE: - if (etype & (POLLHUP | POLLERR | POLLRDHUP)) - close_conn(pool, val); - continue; - - default: - LOG(LOG_E, "???\n"); - NOT_EXIT = 0; - } - } LOG(LOG_S, "exit\n"); destroy_pool(pool); return 0; @@ -1056,5 +991,5 @@ int run(const union sockaddr_u *srv) if (fd < 0) { return -1; } - return event_loop(fd); + return start_event_loop(fd); } diff --git a/proxy.h b/proxy.h index 6b54ca0..66e98d7 100644 --- a/proxy.h +++ b/proxy.h @@ -87,11 +87,21 @@ struct s5_rep { void map_fix(union sockaddr_u *addr, char f6); int create_conn(struct poolhd *pool, - struct eval *val, const union sockaddr_u *dst, int next); + struct eval *val, const union sockaddr_u *dst, evcb_t next); int listen_socket(const union sockaddr_u *srv); -int event_loop(int srvfd); +int on_tunnel(struct poolhd *pool, struct eval *val, int etype); + +int on_udp_tunnel(struct poolhd *pool, struct eval *val, int et); + +int on_request(struct poolhd *pool, struct eval *val, int et); + +int on_connect(struct poolhd *pool, struct eval *val, int et); + +int on_ignore(struct poolhd *pool, struct eval *val, int etype); + +int start_event_loop(int srvfd); int run(const union sockaddr_u *srv);