diff --git a/conev.h b/conev.h index ac0c261..2c8bfeb 100644 --- a/conev.h +++ b/conev.h @@ -4,6 +4,7 @@ #include #include +#include "params.h" #ifndef __linux__ #define NOEPOLL @@ -48,12 +49,6 @@ 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; -}; - #define FLAG_S4 1 #define FLAG_S5 2 #define FLAG_CONN 4 @@ -85,8 +80,7 @@ struct eval { ssize_t round_sent; unsigned int round_count; - int attempt; - bool cache; + struct desync_params *dp; bool mark; // bool restore_ttl; diff --git a/desync.c b/desync.c index 2e0e97f..623a99e 100644 --- a/desync.c +++ b/desync.c @@ -25,9 +25,7 @@ #include #include #endif -#define STR_MODE -#include "params.h" #include "packets.h" #include "error.h" @@ -512,7 +510,7 @@ static void tamp(char *buffer, size_t bfsize, ssize_t *n, ssize_t desync(struct poolhd *pool, struct eval *val, struct buffer *buff, ssize_t *np, bool *wait) { - struct desync_params dp = params.dp[val->pair->attempt]; + struct desync_params dp = *val->pair->dp; struct proto_info info = { 0 }; int sfd = val->fd; @@ -665,10 +663,8 @@ ssize_t desync(struct poolhd *pool, } -int pre_desync(int sfd, int dp_c) +int pre_desync(int sfd, struct desync_params *dp) { - struct desync_params *dp = ¶ms.dp[dp_c]; - #ifdef __linux__ if (dp->drop_sack && drop_sack(sfd)) { return -1; @@ -677,14 +673,13 @@ int pre_desync(int sfd, int dp_c) return 0; } -int post_desync(int sfd, int dp_c) +int post_desync(int sfd, struct desync_params *dp) { - struct desync_params *dp = ¶ms.dp[dp_c]; - #ifdef __linux__ + int nop = 0; if (dp->drop_sack) { if (setsockopt(sfd, SOL_SOCKET, - SO_DETACH_FILTER, &dp_c, sizeof(dp_c)) == -1) { + SO_DETACH_FILTER, &nop, sizeof(nop)) == -1) { uniperror("setsockopt SO_DETACH_FILTER"); return -1; } @@ -695,10 +690,8 @@ int post_desync(int sfd, int dp_c) ssize_t desync_udp(int sfd, char *buffer, - ssize_t n, const struct sockaddr *dst, int dp_c) + ssize_t n, const struct sockaddr *dst, struct desync_params *dp) { - struct desync_params *dp = ¶ms.dp[dp_c]; - if (LOG_ENABLED) { INIT_HEX_STR(buffer, (n > 16 ? 16 : n)); LOG(LOG_S, "bytes: %s (%zd)\n", HEX_STR, n); diff --git a/desync.h b/desync.h index c4cb1c9..52728d7 100644 --- a/desync.h +++ b/desync.h @@ -1,10 +1,13 @@ #ifndef DESYNC_H #define DESYNC_H +#define STR_MODE + #include #include #include "conev.h" +#include "params.h" #ifdef _WIN32 #include @@ -14,13 +17,13 @@ ssize_t desync(struct poolhd *pool, struct eval *val, struct buffer *buff, ssize_t *n, bool *wait); -ssize_t desync_udp(int sfd, char *buffer, ssize_t n, const struct sockaddr *dst, int dp_c); +ssize_t desync_udp(int sfd, char *buffer, ssize_t n, const struct sockaddr *dst, struct desync_params *dp); int setttl(int fd, int ttl); -int pre_desync(int sfd, int dp_c); +int pre_desync(int sfd, struct desync_params *dp); -int post_desync(int sfd, int dp_c); +int post_desync(int sfd, struct desync_params *dp); struct proto_info { char init, type; diff --git a/extend.c b/extend.c index d7065cc..33cfae3 100644 --- a/extend.c +++ b/extend.c @@ -72,43 +72,48 @@ static ssize_t serialize_addr(const union sockaddr_u *dst, } -static int cache_get(const union sockaddr_u *dst) +static void cache_del(const union sockaddr_u *dst) +{ + uint8_t key[KEY_SIZE] = { 0 }; + int len = serialize_addr(dst, key, sizeof(key)); + + INIT_ADDR_STR((*dst)); + LOG(LOG_S, "delete ip: %s\n", ADDR_STR); + mem_delete(params.mempool, (char *)key, len); +} + + +static struct elem_i *cache_get(const union sockaddr_u *dst) { uint8_t key[KEY_SIZE] = { 0 }; int len = serialize_addr(dst, key, sizeof(key)); struct elem_i *val = (struct elem_i *)mem_get(params.mempool, (char *)key, len); if (!val) { - return -1; + return 0; } time_t t = time(0); if (t > val->time + params.cache_ttl) { LOG(LOG_S, "time=%jd, now=%jd, ignore\n", (intmax_t)val->time, (intmax_t)t); + mem_delete(params.mempool, (char *)key, len); return 0; } - return val->m; + return val; } -static int cache_add(const union sockaddr_u *dst, int m) +static struct elem_i *cache_add(const union sockaddr_u *dst) { - assert(m >= 0 && m < params.dp_count); - uint8_t key[KEY_SIZE] = { 0 }; int len = serialize_addr(dst, key, sizeof(key)); INIT_ADDR_STR((*dst)); - if (m == 0) { - LOG(LOG_S, "delete ip: %s\n", ADDR_STR); - mem_delete(params.mempool, (char *)key, len); - return 0; - } - LOG(LOG_S, "save ip: %s, m=%d\n", ADDR_STR, m); + LOG(LOG_S, "save ip: %s\n", ADDR_STR); time_t t = time(0); char *key_d = malloc(len); if (!key_d) { - return -1; + return 0; } memcpy(key_d, key, len); @@ -116,38 +121,33 @@ static int cache_add(const union sockaddr_u *dst, int m) if (!val) { uniperror("mem_add"); free(key_d); - return -1; + return 0; } - val->m = m; val->time = t; - return 0; + return val; } int connect_hook(struct poolhd *pool, struct eval *val, const union sockaddr_u *dst, evcb_t next) { - int m = val->attempt; - if (!m) { - m = cache_get(dst); - val->cache = (m == 0); + struct desync_params *dp = val->dp, *init_dp; + if (!dp) { + struct elem_i *e = cache_get(dst); + dp = e ? e->dp : params.dp; } - int init_m = m; + init_dp = dp; - m = m < 0 ? 0 : m; - struct desync_params *dp; - - for (; ; m++) { - if (m == params.dp_count) { + for (; ; dp = dp->next) { + if (!dp) { return -1; } - dp = ¶ms.dp[m]; - if ((!dp->detect || m == init_m) + if ((!dp->detect || dp == init_dp) && check_l34(dp, SOCK_STREAM, dst)) { break; } } - val->attempt = m; + val->dp = dp; if (dp->custom_dst) { union sockaddr_u addr = dp->custom_dst_addr; @@ -173,12 +173,12 @@ int socket_mod(int fd) } -static int reconnect(struct poolhd *pool, struct eval *val, int m) +static int reconnect(struct poolhd *pool, struct eval *val, struct desync_params *dp) { assert(val->flag == FLAG_CONN); struct eval *client = val->pair; - client->attempt = m; + client->dp = dp; if (connect_hook(pool, client, &val->addr, &on_tunnel)) { return -1; @@ -187,7 +187,6 @@ static int reconnect(struct poolhd *pool, struct eval *val, int m) del_event(pool, val); client->cb = &on_tunnel; - client->cache = 1; if (!client->buff) { client->buff = buff_pop(pool, client->sq_buff->size); @@ -288,33 +287,34 @@ static bool check_round(const int *nr, int r) static int on_trigger(int type, struct poolhd *pool, struct eval *val) { - int m = val->pair->attempt + 1; + struct desync_params *dp = val->pair->dp->next; struct buffer *pair_buff = val->pair->sq_buff; bool can_reconn = ( - pair_buff && pair_buff->lock && !val->recv_count - && params.auto_level > AUTO_NOBUFF + pair_buff && pair_buff->lock + && !val->recv_count + && params.auto_level > AUTO_NOBUFF ); if (!can_reconn && params.auto_level <= AUTO_NOSAVE) { return -1; } - for (; m < params.dp_count; m++) { - struct desync_params *dp = ¶ms.dp[m]; + for (; dp; dp = dp->next) { if (!dp->detect) { break; } if (!(dp->detect & type)) { continue; } - if (can_reconn) { - return reconnect(pool, val, m); + struct elem_i *e = cache_add(&val->addr); + if (e) { + e->dp = dp; } - cache_add(&val->addr, m); - break; - } - if (m >= params.dp_count && m > 1) { - cache_add(&val->addr, 0); + if (can_reconn) { + return reconnect(pool, val, dp); + } + return -1; } + cache_del(&val->addr); return -1; } @@ -348,13 +348,12 @@ static int on_fin(struct poolhd *pool, struct eval *val) static int on_response(struct poolhd *pool, struct eval *val, const char *resp, ssize_t sn) { - int m = val->pair->attempt + 1; + struct desync_params *dp = val->pair->dp->next; char *req = val->pair->sq_buff->data; ssize_t qn = val->pair->sq_buff->size; - for (; m < params.dp_count; m++) { - struct desync_params *dp = ¶ms.dp[m]; + for (; dp; dp = dp->next) { if (!dp->detect) { return -1; } @@ -368,8 +367,8 @@ static int on_response(struct poolhd *pool, struct eval *val, break; } } - if (m < params.dp_count) { - return reconnect(pool, val, m); + if (dp) { + return reconnect(pool, val, dp); } return -1; } @@ -384,31 +383,30 @@ static inline void free_first_req(struct poolhd *pool, struct eval *client) static int setup_conn(struct eval *client, const char *buffer, ssize_t n) { - int m = client->attempt, init_m = m; + struct desync_params *dp = client->dp, *init_dp = dp; - for (; m < params.dp_count; m++) { - struct desync_params *dp = ¶ms.dp[m]; - if ((!dp->detect || m == init_m) - && (m == init_m || check_l34(dp, SOCK_STREAM, &client->pair->addr)) + for (; dp; dp = dp->next) { + if ((!dp->detect || dp == init_dp) + && (dp == init_dp || check_l34(dp, SOCK_STREAM, &client->pair->addr)) && check_proto_tcp(dp->proto, buffer, n) && (!dp->hosts || check_host(dp->hosts, buffer, n))) { break; } } - if (m >= params.dp_count) { - LOG(LOG_E, "drop connection (m=%d)\n", m); + if (!dp) { + LOG(LOG_E, "drop connection\n"); return -1; } - if (params.auto_level > AUTO_NOBUFF && params.dp_count > 1) { + if (params.auto_level > AUTO_NOBUFF && params.dp->next) { client->mark = is_tls_chello(buffer, n); } - client->attempt = m; + client->dp = dp; if (params.timeout && set_timeout(client->pair->fd, params.timeout)) { return -1; } - if (pre_desync(client->pair->fd, client->attempt)) { + if (pre_desync(client->pair->fd, client->dp)) { return -1; } return 0; @@ -421,7 +419,7 @@ static int cancel_setup(struct eval *remote) set_timeout(remote->fd, 0)) { return -1; } - if (post_desync(remote->fd, remote->pair->attempt)) { + if (post_desync(remote->fd, remote->pair->dp)) { return -1; } return 0; @@ -442,12 +440,12 @@ ssize_t tcp_send_hook(struct poolhd *pool, && setup_conn(client, buff->data, *n) < 0) { return -1; } - int m = client->attempt, r = client->round_count; - if (!check_round(params.dp[m].rounds, r)) { + int r = client->round_count; + if (!check_round(client->dp->rounds, r)) { skip = 1; } else { - LOG(LOG_S, "desync TCP: group=%d, round=%d, fd=%d\n", m, r, remote->fd); + LOG(LOG_S, "desync TCP: group=%d, round=%d, fd=%d\n", client->dp->id, r, remote->fd); sn = desync(pool, remote, buff, n, wait); } } @@ -496,7 +494,7 @@ ssize_t tcp_recv_hook(struct poolhd *pool, val->pair->part_sent = 0; } if (val->flag == FLAG_CONN && !val->round_sent) { - int *nr = params.dp[val->pair->attempt].rounds; + int *nr = val->pair->dp->rounds; if (check_round(nr, val->round_count) && !check_round(nr, val->round_count + 1) @@ -529,11 +527,6 @@ ssize_t tcp_recv_hook(struct poolhd *pool, return 0; } free_first_req(pool, val->pair); - int m = val->pair->attempt; - - if (val->pair->cache && cache_add(&val->addr, m) < 0) { - return -1; - } } return n; } @@ -543,26 +536,26 @@ ssize_t udp_hook(struct eval *val, char *buffer, ssize_t n, const union sockaddr_u *dst) { struct eval *pair = val->pair->pair; + int r = pair->round_count; - int m = pair->attempt, r = pair->round_count; - if (!m) { - for (; m < params.dp_count; m++) { - struct desync_params *dp = ¶ms.dp[m]; + struct desync_params *dp = pair->dp; + if (!dp) { + for (dp = params.dp; ; dp = dp->next) { + if (!dp) { + return -1; + } if (!dp->detect && check_l34(dp, SOCK_DGRAM, dst)) { break; } } - if (m >= params.dp_count) { - return -1; - } - pair->attempt = m; + pair->dp = dp; } - if (!check_round(params.dp[m].rounds, r)) { + if (!check_round(dp->rounds, r)) { return send(val->fd, buffer, n, 0); } - LOG(LOG_S, "desync UDP: group=%d, round=%d, fd=%d\n", m, r, val->fd); - return desync_udp(val->fd, buffer, n, &dst->sa, m); + LOG(LOG_S, "desync UDP: group=%d, round=%d, fd=%d\n", dp->id, r, val->fd); + return desync_udp(val->fd, buffer, n, &dst->sa, dp); } diff --git a/main.c b/main.c index 2042a5f..2bcf29a 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "proxy.h" #include "packets.h" #include "error.h" +#include "conev.h" #ifndef _WIN32 #include @@ -538,6 +539,21 @@ void *add(void **root, int *n, size_t ss) } +static struct desync_params *add_group(struct desync_params *prev) +{ + struct desync_params *dp = calloc(1, sizeof(*prev)); + if (!dp) { + return 0; + } + if (prev) { + dp->prev = prev; + prev->next = dp; + } + params.dp_n++; + return dp; +} + + #ifdef DAEMON int init_pid_file(const char *fname) { @@ -579,41 +595,41 @@ void clear_params(void) mem_destroy(params.mempool); params.mempool = 0; } - if (params.dp) { - for (int i = 0; i < params.dp_count; i++) { - struct desync_params s = params.dp[i]; - if (s.parts != 0) { - free(s.parts); - s.parts = 0; - } - if (s.tlsrec != 0) { - free(s.tlsrec); - s.tlsrec = 0; - } - if (s.fake_data.data != 0) { - free(s.fake_data.data); - s.fake_data.data = 0; - } - if (s.file_ptr != 0) { - free(s.file_ptr); - s.file_ptr = 0; - } - if (s.hosts != 0) { - mem_destroy(s.hosts); - s.hosts = 0; - } - if (s.ipset != 0) { - mem_destroy(s.ipset); - s.hosts = 0; - } - if (s.fake_sni_list != 0) { - free(s.fake_sni_list); - s.fake_sni_list = 0; - } + struct desync_params *dp = params.dp; + while (dp) { + if (dp->parts != 0) { + free(dp->parts); + dp->parts = 0; } - free(params.dp); - params.dp = 0; + if (dp->tlsrec != 0) { + free(dp->tlsrec); + dp->tlsrec = 0; + } + if (dp->fake_data.data != 0) { + free(dp->fake_data.data); + dp->fake_data.data = 0; + } + if (dp->file_ptr != 0) { + free(dp->file_ptr); + dp->file_ptr = 0; + } + if (dp->hosts != 0) { + mem_destroy(dp->hosts); + dp->hosts = 0; + } + if (dp->ipset != 0) { + mem_destroy(dp->ipset); + dp->hosts = 0; + } + if (dp->fake_sni_list != 0) { + free(dp->fake_sni_list); + dp->fake_sni_list = 0; + } + struct desync_params *t = dp; + dp = dp->next; + free(t); } + params.dp = 0; } @@ -662,12 +678,12 @@ int main(int argc, char **argv) int curr_optind = 1; - struct desync_params *dp = add((void *)¶ms.dp, - ¶ms.dp_count, sizeof(struct desync_params)); + struct desync_params *dp = add_group(0); if (!dp) { clear_params(); return -1; } + params.dp = dp; while (!invalid && (rez = getopt_long( argc, argv, opt, options, 0)) != -1) { @@ -771,8 +787,7 @@ int main(int argc, char **argv) if (!(dp->hosts || dp->proto || dp->pf[0] || dp->detect || dp->ipset)) { all_limited = 0; } - dp = add((void *)¶ms.dp, ¶ms.dp_count, - sizeof(struct desync_params)); + dp = add_group(dp); if (!dp) { clear_params(); return -1; @@ -803,6 +818,7 @@ int main(int argc, char **argv) params.auto_level = AUTO_NOSAVE; } dp->_optind = optind; + dp->id = params.dp_n - 1; break; case 'B': @@ -814,14 +830,19 @@ int main(int argc, char **argv) continue; } val = strtol(optarg, &end, 0); - if (val < 1 || val >= params.dp_count || *end) + struct desync_params *itdp = params.dp; + + while (itdp && itdp->id != val - 1) { + itdp = itdp->next; + } + if (!itdp) invalid = 1; else { curr_optind = optind; - optind = params.dp[val - 1]._optind; + optind = itdp->_optind; } break; - + case 'u': val = strtol(optarg, &end, 0); if (val <= 0 || *end) @@ -1134,8 +1155,7 @@ int main(int argc, char **argv) return -1; } if (all_limited) { - dp = add((void *)¶ms.dp, - ¶ms.dp_count, sizeof(struct desync_params)); + dp = add_group(dp); if (!dp) { clear_params(); return -1; diff --git a/mpool.h b/mpool.h index 440219e..28d36f0 100644 --- a/mpool.h +++ b/mpool.h @@ -18,7 +18,7 @@ struct elem { struct elem_i { struct elem i; - int m; + void *dp; time_t time; }; diff --git a/params.h b/params.h index e2fb297..eaaa2c7 100644 --- a/params.h +++ b/params.h @@ -7,7 +7,6 @@ #include #include "mpool.h" -#include "conev.h" #ifdef _WIN32 #include @@ -60,6 +59,12 @@ static const char *demode_str[] = { }; #endif +union sockaddr_u { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; +}; + struct part { int m; int flag; @@ -106,10 +111,15 @@ struct desync_params { ssize_t file_size; int _optind; + int id; + int fail_count; + + struct desync_params *prev; + struct desync_params *next; }; struct params { - int dp_count; + int dp_n; struct desync_params *dp; int await_int; bool wait_send;