diff options
-rw-r--r-- | src/client.c | 67 | ||||
-rw-r--r-- | src/server.c | 1 | ||||
-rw-r--r-- | src/udpastcp.c | 1 |
3 files changed, 40 insertions, 29 deletions
diff --git a/src/client.c b/src/client.c index 3967950..1e761b8 100644 --- a/src/client.c +++ b/src/client.c @@ -8,20 +8,14 @@ #include <stdlib.h> #include <string.h> #include <sys/socket.h> -#include <sys/types.h> -#include <sys/uio.h> #include <unistd.h> -#ifdef CRYPTO -#include <sodium/core.h> -#include <sodium/crypto_secretbox.h> -#include <sodium/randombytes.h> -#endif - #include "common.h" #include "client.h" #include "uthash.h" +#define PORTS_IN_INT sizeof(int) * CHAR_BIT + struct o_c_rsock { struct sockaddr *r_addr; struct o_c_sock *o_socks_by_lport; @@ -30,6 +24,7 @@ struct o_c_rsock { UT_hash_handle hh; int fd; socklen_t r_addrlen; + unsigned int used_ports[32768 / PORTS_IN_INT]; }; struct o_c_sock { @@ -46,8 +41,6 @@ struct o_c_sock { int8_t syn_retries; }; -#define PORTS_IN_INT sizeof(int) * CHAR_BIT - struct c_data { const char *r_host; const char *r_port; @@ -55,7 +48,6 @@ struct c_data { struct o_c_rsock *o_rsocks; struct sockaddr_storage pkt_addr; socklen_t s_addrlen; - unsigned int used_ports[32768 / PORTS_IN_INT]; int s_sock; int i_sock; }; @@ -64,14 +56,35 @@ static struct c_data *global_c_data; static const uint8_t tcp_syn_retry_timeouts[] = { 3, 6, 12, 24, 0 }; +static inline int check_resv_port(unsigned int *used_ports, uint16_t port) { + if (used_ports[port / PORTS_IN_INT] & (1 << port % PORTS_IN_INT)) { + used_ports[port / PORTS_IN_INT] |= 1 << port % PORTS_IN_INT; + return port; + } + return 0; +} + /* reserve a local TCP port (local addr, remote addr, remote port are usually * fixed in the tuple) */ static uint16_t reserve_port(unsigned int *used_ports) { - // pick a starting port for the search - uint16_t spoff = random() % 32768; - size_t smoff = spoff / PORTS_IN_INT; - unsigned int ioff; - size_t moff; + uint16_t port; + // randomly try 16 places + for (int i = 1; i <= 16; i++) { + long r = random(); + + port = 32768 + r; + if (check_resv_port(used_ports, port)) + return port; + + port = 32768 + (r << 16); + if (check_resv_port(used_ports, port)) + return port; + } + + // give up and go sequentially + + uint16_t ioff, spoff = port; + size_t moff, smoff = spoff / PORTS_IN_INT; /* two step process: * +-----------------------------+-----------------------+ @@ -127,7 +140,7 @@ static void c_sock_cleanup(EV_P_ struct o_c_sock *sock, int stopping) { } if (!stopping) { - free_port(sock->rsock->c_data->used_ports, sock->l_port); + free_port(sock->rsock->used_ports, sock->l_port); ev_timer_stop(EV_A_ &sock->tm_w); HASH_DELETE(hh_lp, sock->rsock->o_socks_by_lport, sock); @@ -170,7 +183,7 @@ static void c_syn_tm_cb(EV_P_ ev_timer *w, int revents __attribute__((unused))) } } -static void cc_cb(struct ev_loop *loop __attribute__((unused)), ev_io *w, int revents __attribute__((unused))) { +static void cc_cb(struct ev_loop *loop, ev_io *w, int revents __attribute__((unused))) { DBG("-- entering cc_cb --"); struct o_c_rsock *rsock = w->data; @@ -294,15 +307,6 @@ static void cs_cb(EV_P_ ev_io *w, int revents __attribute__((unused))) { DBG("could not locate matching socket for client, initializing new connection"); sock = calloc(1, sizeof(*sock)); - uint16_t l_port = reserve_port(c_data->used_ports); - DBG("using port %hu", l_port); - if (!l_port) { - fputs("we ran out of ports?\n", stderr); - ev_break(EV_A_ EVBREAK_ONE); - return; - } - sock->l_port = htons(l_port); - struct addrinfo *res; DBG("looking up %s:%s", c_data->r_host, c_data->r_port); // TODO: make this asynchronous @@ -349,6 +353,15 @@ static void cs_cb(EV_P_ ev_io *w, int revents __attribute__((unused))) { HASH_ADD_KEYPTR(hh, c_data->o_rsocks, sock->rsock->r_addr, sock->rsock->r_addrlen, sock->rsock); } + uint16_t l_port = reserve_port(sock->rsock->used_ports); + DBG("using port %hu", l_port); + if (!l_port) { + fputs("we ran out of ports?\n", stderr); + ev_break(EV_A_ EVBREAK_ONE); + return; + } + sock->l_port = htons(l_port); + HASH_ADD_KEYPTR(hh_ca, c_data->o_socks_by_caddr, sock->c_address, addresslen, sock); HASH_ADD(hh_lp, sock->rsock->o_socks_by_lport, l_port, sizeof(in_port_t), sock); diff --git a/src/server.c b/src/server.c index a776d5a..158c0af 100644 --- a/src/server.c +++ b/src/server.c @@ -1,6 +1,5 @@ #include <assert.h> #include <ev.h> -#include <limits.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> diff --git a/src/udpastcp.c b/src/udpastcp.c index cdd73d2..7230c93 100644 --- a/src/udpastcp.c +++ b/src/udpastcp.c @@ -1,4 +1,3 @@ -#include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdio.h> |