diff --git a/src/client.c b/src/client.c index 750edae..e403002 100644 --- a/src/client.c +++ b/src/client.c @@ -688,7 +688,7 @@ send_next_frag(int fd) int code, id; static int datacmc = 0; static char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789"; - fragment *f; + struct fragment *f; size_t buflen; /* Get next fragment to send */ @@ -1080,11 +1080,11 @@ handshake_waitdns(int dns_fd, char *buf, size_t buflen, char cmd, int timeout) } int -parse_data(uint8_t *data, size_t len, fragment *f, int *immediate) +parse_data(uint8_t *data, size_t len, struct fragment *f, int *immediate) { size_t headerlen = DOWNSTREAM_HDR; int ping; - memset(f, 0, sizeof(fragment)); + memset(f, 0, sizeof(struct fragment)); f->seqID = data[0]; @@ -1164,7 +1164,7 @@ tunnel_dns(int tun_fd, int dns_fd) struct query q; size_t datalen, buflen; uint8_t buf[64*1024], cbuf[64*1024], *data; - fragment f; + struct fragment f; int read, compressed, res, immediate; memset(&q, 0, sizeof(q)); diff --git a/src/client.h b/src/client.h index 3078269..b6fb9c0 100644 --- a/src/client.h +++ b/src/client.h @@ -53,7 +53,7 @@ void client_set_interval(int, int); int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize); int client_tunnel(int tun_fd, int dns_fd); -int parse_data(uint8_t *data, size_t len, fragment *f, int *immediate); +int parse_data(uint8_t *data, size_t len, struct fragment *f, int *immediate); int handshake_waitdns(int dns_fd, char *buf, size_t buflen, char cmd, int timeout); void handshake_switch_options(int dns_fd, int lazy, int compression, char denc); int send_ping(int fd, int ping_response, int ack, int timeout); diff --git a/src/window.c b/src/window.c index 72a0ad5..b870b62 100644 --- a/src/window.c +++ b/src/window.c @@ -31,11 +31,37 @@ int window_debug = 0; + +/* Window debugging macro */ +#ifdef DEBUG_BUILD +#define WDEBUG(...) if (window_debug) {\ + TIMEPRINT("[WINDOW-DEBUG] (%s:%d) ", __FILE__, __LINE__);\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n");\ + } +#else +#define WDEBUG(...) +#endif + +/* Window-specific macros */ +/* Gets index of fragment o fragments after window start */ +#define AFTER(w, o) ((w->window_start + o) % w->length) + +/* Check if fragment index a is within window_buffer *w */ +#define INWINDOW_INDEX(w, a) ((w->window_start < w->window_end) ? \ + (a >= w->window_start && a <= w->window_end) : \ + ((a >= w->window_start && a <= w->length - 1) || \ + (a >= 0 && a <= w->window_end))) + +/* Wrap index x to a value within the window buffer length */ +#define WRAP(x) ((x) % w->length) + + struct frag_buffer * window_buffer_init(size_t length, unsigned windowsize, unsigned fragsize, int dir) { struct frag_buffer *buf; - buf = calloc(sizeof(struct frag_buffer), 1); + buf = calloc(1, sizeof(struct frag_buffer)); if (!buf) { errx(1, "Failed to allocate window buffer memory!"); } @@ -46,7 +72,7 @@ window_buffer_init(size_t length, unsigned windowsize, unsigned fragsize, int di errx(fragsize, "Fragsize too large! Please recompile with larger MAX_FRAGSIZE!"); } - buf->frags = calloc(length, sizeof(fragment)); + buf->frags = calloc(length, sizeof(struct fragment)); if (!buf->frags) { errx(1, "Failed to allocate fragment buffer!"); } @@ -83,7 +109,7 @@ window_buffer_resize(struct frag_buffer *w, size_t length) WDEBUG("Resizing window buffer with things still in it! This will cause problems!"); } if (w->frags) free(w->frags); - w->frags = calloc(length, sizeof(fragment)); + w->frags = calloc(length, sizeof(struct fragment)); if (!w->frags) { errx(1, "Failed to resize window buffer!"); } @@ -104,7 +130,7 @@ window_buffer_clear(struct frag_buffer *w) { if (!w) return; - memset(w->frags, 0, w->length * sizeof(fragment)); + memset(w->frags, 0, w->length * sizeof(struct fragment)); window_buffer_reset(w); } @@ -117,10 +143,10 @@ window_buffer_available(struct frag_buffer *w) /* Places a fragment in the window after the last one */ int -window_append_fragment(struct frag_buffer *w, fragment *src) +window_append_fragment(struct frag_buffer *w, struct fragment *src) { if (window_buffer_available(w) < 1) return 0; - memcpy(&w->frags[w->last_write], src, sizeof(fragment)); + memcpy(&w->frags[w->last_write], src, sizeof(struct fragment)); w->last_write = WRAP(w->last_write + 1); w->numitems ++; return 1; @@ -128,14 +154,14 @@ window_append_fragment(struct frag_buffer *w, fragment *src) ssize_t -window_process_incoming_fragment(struct frag_buffer *w, fragment *f) +window_process_incoming_fragment(struct frag_buffer *w, struct fragment *f) /* Handles fragment received from the sending side (RECV) * Returns index of fragment in window or <0 if dropped * The next ACK MUST be for this fragment */ { /* Check if packet is in window */ unsigned startid, endid, offset; - fragment *fd; + struct fragment *fd; startid = w->start_seq_id; endid = (w->start_seq_id + w->windowsize) % MAX_SEQ_ID; offset = SEQ_OFFSET(startid, f->seqID); @@ -169,7 +195,7 @@ window_process_incoming_fragment(struct frag_buffer *w, fragment *f) } } - memcpy(fd, f, sizeof(fragment)); + memcpy(fd, f, sizeof(struct fragment)); w->numitems ++; fd->retries = 0; @@ -181,6 +207,17 @@ window_process_incoming_fragment(struct frag_buffer *w, fragment *f) return dest; } +/* Perform wrapped iteration of statement with pos = (begin to end) wrapped at + * max, executing statement f for every value of pos. */ +#define ITER_FORWARD(begin, end, max, pos, f) { \ + if (end >= begin) \ + for (pos = begin; pos < end && pos < max; pos++) {f}\ + else {\ + for (pos = begin; pos < max; pos++) {f}\ + for (pos = 0; pos < end && pos < max; pos++) {f}\ + }\ + } + /* Reassembles first complete sequence of fragments into data. (RECV) * Returns length of data reassembled, or 0 if no data reassembled */ size_t @@ -198,7 +235,7 @@ window_reassemble_data(struct frag_buffer *w, uint8_t *data, size_t maxlen, int } if (compression) *compression = 1; - fragment *f; + struct fragment *f; size_t i; unsigned curseq; int end = 0; @@ -253,7 +290,7 @@ window_reassemble_data(struct frag_buffer *w, uint8_t *data, size_t maxlen, int /* Clear all used fragments */ size_t p; ITER_FORWARD(w->chunk_start, WRAP(w->chunk_start + i + 1), w->length, p, - memset(&w->frags[p], 0, sizeof(fragment)); + memset(&w->frags[p], 0, sizeof(struct fragment)); ); w->chunk_start = WRAP(woffs + 1); w->numitems -= i + 1; @@ -267,7 +304,7 @@ window_sending(struct frag_buffer *w, struct timeval *nextresend) *nextresend is time before the next frag will be resent */ { struct timeval age, now, oldest; - fragment *f; + struct fragment *f; size_t tosend = 0; oldest.tv_sec = 0; @@ -311,11 +348,11 @@ window_sending(struct frag_buffer *w, struct timeval *nextresend) /* Returns next fragment to be sent or NULL if nothing (SEND) * This also handles packet resends, timeouts etc. */ -fragment * +struct fragment * window_get_next_sending_fragment(struct frag_buffer *w, int *other_ack) { struct timeval age, now; - fragment *f = NULL; + struct fragment *f = NULL; if (*other_ack >= MAX_SEQ_ID || *other_ack < 0) *other_ack = -1; @@ -360,7 +397,7 @@ window_get_next_sending_fragment(struct frag_buffer *w, int *other_ack) int window_get_next_ack(struct frag_buffer *w) { - fragment *f; + struct fragment *f; for (size_t i = 0; i < w->windowsize; i++) { f = &w->frags[WRAP(w->window_start + i)]; if (f->len > 0 && f->acks <= 0) { @@ -375,7 +412,7 @@ window_get_next_ack(struct frag_buffer *w) void window_ack(struct frag_buffer *w, int seqid) { - fragment *f; + struct fragment *f; if (seqid < 0 || seqid > MAX_SEQ_ID) return; for (size_t i = 0; i < w->windowsize; i++) { f = &w->frags[AFTER(w, i)]; @@ -406,7 +443,7 @@ window_tick(struct frag_buffer *w) if (w->direction == WINDOW_SENDING) { WDEBUG("Clearing old fragments in SENDING window."); w->numitems --; /* Clear old fragments */ - memset(&w->frags[w->window_start], 0, sizeof(fragment)); + memset(&w->frags[w->window_start], 0, sizeof(struct fragment)); } w->window_start = AFTER(w, 1); @@ -428,7 +465,7 @@ window_add_outgoing_data(struct frag_buffer *w, uint8_t *data, size_t len, int c } compressed &= 1; size_t offset = 0; - static fragment f; + struct fragment f; WDEBUG("add data len %lu, %lu frags, max fragsize %u", len, n, w->maxfraglen); for (size_t i = 0; i < n; i++) { memset(&f, 0, sizeof(f)); diff --git a/src/window.h b/src/window.h index fc412f7..6255ff1 100644 --- a/src/window.h +++ b/src/window.h @@ -22,11 +22,28 @@ #define MAX_SEQ_ID 256 #define MAX_FRAGSIZE 4096 -/* Window function definitions. */ #define WINDOW_SENDING 1 #define WINDOW_RECVING 0 -typedef struct fragment { +/* Generic ring-buffer macros */ + +/* Distance (going forwards) between a and b in window of length l */ +#define DISTF(l, a, b) (((a > b) ? a-b : l-a+b-1) % l) + +/* Distance backwards between a and b in window of length l */ +#define DISTB(l, a, b) (((a < b) ? l-b+a-1 : a-b) % l) + +/* Check if sequence ID a is within sequence range start to end */ +#define INWINDOW_SEQ(start, end, a) ((start < end) ? \ + (a >= start && a <= end) : \ + ((a >= start && a <= MAX_SEQ_ID - 1) || \ + (a <= end))) + +/* Find the wrapped offset between sequence IDs start and a + * Note: the maximum possible offset is MAX_SEQ_ID - 1 */ +#define SEQ_OFFSET(start, a) ((a >= start) ? a - start : MAX_SEQ_ID - start + a) + +struct fragment { size_t len; /* Length of fragment data (0 if fragment unused) */ unsigned seqID; /* fragment sequence ID */ int ack_other; /* other way ACK seqID (>=0) or unset (<0) */ @@ -37,10 +54,10 @@ typedef struct fragment { unsigned retries; /* number of times has been sent or dupes recv'd */ struct timeval lastsent; /* timestamp of most recent send attempt */ int acks; /* number of times packet has been ack'd */ -} fragment; +}; struct frag_buffer { - fragment *frags; /* pointer to array of data fragments */ + struct fragment *frags; /* pointer to array of data fragments */ unsigned windowsize; /* Max number of fragments in flight */ unsigned maxfraglen; /* Max outgoing fragment data size */ size_t length; /* Length of buffer */ @@ -59,55 +76,10 @@ struct frag_buffer { extern int window_debug; -/* Window debugging macro */ -#ifdef DEBUG_BUILD -#define WDEBUG(...) if (window_debug) {\ - TIMEPRINT("[WINDOW-DEBUG] (%s:%d) ", __FILE__, __LINE__);\ - fprintf(stderr, __VA_ARGS__);\ - fprintf(stderr, "\n");\ - } -#else -#define WDEBUG(...) -#endif -/* Gets index of fragment o fragments after window start */ -#define AFTER(w, o) ((w->window_start + o) % w->length) -/* Distance (going forwards) between a and b in window of length l */ -#define DISTF(l, a, b) (((a > b) ? a-b : l-a+b-1) % l) +/* Window function definitions. */ -/* Distance backwards between a and b in window of length l */ -#define DISTB(l, a, b) (((a < b) ? l-b+a-1 : a-b) % l) - -/* Check if fragment index a is within window_buffer *w */ -#define INWINDOW_INDEX(w, a) ((w->window_start < w->window_end) ? \ - (a >= w->window_start && a <= w->window_end) : \ - ((a >= w->window_start && a <= w->length - 1) || \ - (a >= 0 && a <= w->window_end))) - -/* Check if sequence ID a is within sequence range start to end */ -#define INWINDOW_SEQ(start, end, a) ((start < end) ? \ - (a >= start && a <= end) : \ - ((a >= start && a <= MAX_SEQ_ID - 1) || \ - (a <= end))) - -/* Find the wrapped offset between sequence IDs start and a - * Note: the maximum possible offset is MAX_SEQ_ID - 1 */ -#define SEQ_OFFSET(start, a) ((a >= start) ? a - start : MAX_SEQ_ID - start + a) - -/* Wrap index x to a value within the window buffer length */ -#define WRAP(x) ((x) % w->length) - -/* Perform wrapped iteration of statement with pos = (begin to end) wrapped at - * max, executing statement f for every value of pos. */ -#define ITER_FORWARD(begin, end, max, pos, f) { \ - if (end >= begin) \ - for (pos = begin; pos < end && pos < max; pos++) {f}\ - else {\ - for (pos = begin; pos < max; pos++) {f}\ - for (pos = 0; pos < end && pos < max; pos++) {f}\ - }\ - } /* Window buffer creation and housekeeping */ struct frag_buffer *window_buffer_init(size_t length, unsigned windowsize, unsigned fragsize, int dir); @@ -124,10 +96,10 @@ void window_buffer_reset(struct frag_buffer *w); size_t window_buffer_available(struct frag_buffer *w); /* Places a fragment in the window after the last one */ -int window_append_fragment(struct frag_buffer *w, fragment *src); +int window_append_fragment(struct frag_buffer *w, struct fragment *src); /* Handles fragment received from the sending side (RECV) */ -ssize_t window_process_incoming_fragment(struct frag_buffer *w, fragment *f); +ssize_t window_process_incoming_fragment(struct frag_buffer *w, struct fragment *f); /* Reassembles first complete sequence of fragments into data. (RECV) * Returns length of data reassembled, or 0 if no data reassembled */ @@ -137,7 +109,7 @@ size_t window_reassemble_data(struct frag_buffer *w, uint8_t *data, size_t maxle size_t window_sending(struct frag_buffer *w, struct timeval *); /* Returns next fragment to be sent or NULL if nothing (SEND) */ -fragment *window_get_next_sending_fragment(struct frag_buffer *w, int *other_ack); +struct fragment *window_get_next_sending_fragment(struct frag_buffer *w, int *other_ack); /* Gets the seqid of next fragment to be ACK'd (RECV) */ int window_get_next_ack(struct frag_buffer *w);