Refactored 'fragment' to 'struct fragment' and moved window macros

This commit is contained in:
frekky 2016-03-15 21:04:48 +08:00
parent fa4bc66d44
commit 25a6457e12
4 changed files with 85 additions and 76 deletions

View File

@ -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));

View File

@ -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);

View File

@ -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));

View File

@ -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);