commit 7846fc0071e903619227d7dde41dc5aaa91c0d70 Author: Jeffrey Wang jeffreyw@stanford.edu Date: Thu Dec 8 09:17:19 2011 +0000
fixing another blocksize bug and making transmit timer handling work properly in failure cases
git-svn-id: svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@178 a58ff0ac-194c-e011-a152-003048836090 --- src/protocol/chop.cc | 34 +++++++++++++++++++++++++++++----- src/util.cc | 25 +++++++++++++++++++++++++ src/util.h | 7 +++++++ 3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc index f960fbb..51d3195 100644 --- a/src/protocol/chop.cc +++ b/src/protocol/chop.cc @@ -299,6 +299,7 @@ chop_send_block(conn_t *d, chop_header hdr; struct evbuffer_iovec v; uint8_t *p; + struct timeval *exp_time = NULL;
log_assert(evbuffer_get_length(block) == 0); log_assert(evbuffer_get_length(source) >= length); @@ -332,10 +333,17 @@ chop_send_block(conn_t *d, if (evbuffer_commit_space(block, &v, 1)) goto fail;
- // TODO: this should be moved after the steg transmit, but currently that - // prevents conn_transmit_soon calls inside steg transmit - if (dest->must_transmit_timer) + /* save the expiration time of the must_transmit_timer in case of failure */ + if (dest->must_transmit_timer) { + exp_time = new struct timeval; + if (evtimer_pending(dest->must_transmit_timer, exp_time)) { + log_debug("saved must_transmit_timer value in case of failure"); + } else { + delete exp_time; + exp_time = NULL; + } evtimer_del(dest->must_transmit_timer); + }
if (dest->steg->transmit(block, dest)) goto fail_committed; @@ -352,6 +360,10 @@ chop_send_block(conn_t *d, ckt->sent_fin = true; log_debug(dest, "sent %lu+%u byte block [flags %04hx]", (unsigned long)CHOP_WIRE_HDR_LEN, length, flags); + + if (exp_time != NULL) + delete exp_time; + return 0;
fail: @@ -360,6 +372,18 @@ chop_send_block(conn_t *d, fail_committed: evbuffer_drain(block, evbuffer_get_length(block)); log_warn(dest, "allocation or buffer copy failed"); + + /* restore timer if necessary */ + if (exp_time != NULL) { + if (!evtimer_pending(dest->must_transmit_timer, NULL)) { + struct timeval cur_time, timeout; + gettimeofday(&cur_time, NULL); + timeval_subtract(exp_time, &cur_time, &timeout); + evtimer_add(dest->must_transmit_timer, &timeout); + } + delete exp_time; + } + return -1; }
@@ -524,13 +548,13 @@ must_transmit_timer_cb(evutil_socket_t, short, void *arg) return; } room = conn->steg->transmit_room(conn); - if (!room) { + if (room <= CHOP_BLOCK_OVERHD) { log_warn(conn, "must transmit, but no transmit room"); return; }
log_debug(conn, "must transmit"); - chop_send_targeted(conn->circuit, conn, room); + chop_send_targeted(conn->circuit, conn, room - CHOP_BLOCK_OVERHD); }
/* Receive subroutines. */ diff --git a/src/util.cc b/src/util.cc index 79bfbd6..9987871 100644 --- a/src/util.cc +++ b/src/util.cc @@ -704,3 +704,28 @@ void logpfx(LOG_SEV_DEBUG, FN, cn); logfmt(LOG_SEV_DEBUG, format); } + +/************************* Time Functions **************************/ + +int timeval_subtract(struct timeval *x, struct timeval *y, + struct timeval *result) { + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} diff --git a/src/util.h b/src/util.h index 5dccad3..392d15a 100644 --- a/src/util.h +++ b/src/util.h @@ -273,4 +273,11 @@ void log_debug(conn_t *conn,const char *format, ...) __FILE__, __LINE__, #expr); \ } while (0)
+/***** Time. *****/ + +/** Compute x - y and store the value result. Returns 1 if the difference is + negative, and 0 otherwise. **/ +int timeval_subtract(struct timeval *x, struct timeval *y, + struct timeval *result); + #endif