X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=utcp.c;h=5d630694df96100f57e780f855a32cc63f7674bc;hb=f97e64bcb266c37a8eb24c3e8286272c02756e6e;hp=2ed32175dc0f98c9b2bc045f7a62fb43caeb5089;hpb=7baf55a28cf48163c007ee2ff56678371d78c990;p=utcp diff --git a/utcp.c b/utcp.c index 2ed3217..5d63069 100644 --- a/utcp.c +++ b/utcp.c @@ -415,13 +415,13 @@ static void update_rtt(struct utcp_connection *c, uint32_t rtt) { if(!utcp->srtt) { utcp->srtt = rtt; utcp->rttvar = rtt / 2; - utcp->rto = rtt + max(2 * rtt, CLOCK_GRANULARITY); } else { utcp->rttvar = (utcp->rttvar * 3 + absdiff(utcp->srtt, rtt)) / 4; utcp->srtt = (utcp->srtt * 7 + rtt) / 8; - utcp->rto = utcp->srtt + max(utcp->rttvar, CLOCK_GRANULARITY); } + utcp->rto = utcp->srtt + max(4 * utcp->rttvar, CLOCK_GRANULARITY); + if(utcp->rto > MAX_RTO) { utcp->rto = MAX_RTO; } @@ -629,6 +629,8 @@ ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) { if(is_reliable(c) || (c->state != SYN_SENT && c->state != SYN_RECEIVED)) { len = buffer_put(&c->sndbuf, data, len); + } else { + return 0; } if(len <= 0) { @@ -1055,6 +1057,7 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) { c->flags = UTCP_TCP; } +synack: // Return SYN+ACK, go to SYN_RECEIVED state c->snd.wnd = hdr.wnd; c->rcv.irs = hdr.seq; @@ -1313,8 +1316,10 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) { assert(data_acked >= 0); +#ifndef NDEBUG int32_t bufused = seqdiff(c->snd.last, c->snd.una); assert(data_acked <= bufused); +#endif if(data_acked) { buffer_get(&c->sndbuf, NULL, data_acked); @@ -1346,7 +1351,7 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) { case CLOSING: if(c->snd.una == c->snd.last) { gettimeofday(&c->conn_timeout, NULL); - c->conn_timeout.tv_sec += 60; + c->conn_timeout.tv_sec += utcp->timeout; set_state(c, TIME_WAIT); } @@ -1410,6 +1415,9 @@ skip_ack: break; case SYN_RECEIVED: + // This is a retransmit of a SYN, send back the SYNACK. + goto synack; + case ESTABLISHED: case FIN_WAIT_1: case FIN_WAIT_2: @@ -1505,7 +1513,7 @@ skip_ack: case FIN_WAIT_2: gettimeofday(&c->conn_timeout, NULL); - c->conn_timeout.tv_sec += 60; + c->conn_timeout.tv_sec += utcp->timeout; set_state(c, TIME_WAIT); break; @@ -1918,8 +1926,14 @@ void utcp_reset_timers(struct utcp *utcp) { continue; } - c->rtrx_timeout = now; - c->conn_timeout = then; + if(timerisset(&c->rtrx_timeout)) { + c->rtrx_timeout = now; + } + + if(timerisset(&c->conn_timeout)) { + c->conn_timeout = then; + } + c->rtt_start.tv_sec = 0; } @@ -2070,19 +2084,24 @@ void utcp_expect_data(struct utcp_connection *c, bool expect) { } void utcp_offline(struct utcp *utcp, bool offline) { + struct timeval now; + gettimeofday(&now, NULL); + for(int i = 0; i < utcp->nconnections; i++) { struct utcp_connection *c = utcp->connections[i]; - if(!c->reapable) { - utcp_expect_data(c, offline); - - // If we are online again, reset the retransmission timers, but keep the connection timeout as it is, - // to prevent peers toggling online/offline state frequently from keeping connections alive - // if there is no progress in sending actual data. - if(!offline) { - gettimeofday(&utcp->connections[i]->rtrx_timeout, NULL); - utcp->connections[i]->rtt_start.tv_sec = 0; + if(c->reapable) { + continue; + } + + utcp_expect_data(c, offline); + + if(!offline) { + if(timerisset(&c->rtrx_timeout)) { + c->rtrx_timeout = now; } + + utcp->connections[i]->rtt_start.tv_sec = 0; } }