ptr += 2;
}
+ bool has_data = len || (hdr.ctl & (SYN | FIN));
+
// Try to match the packet to an existing connection
struct utcp_connection *c = find_connection(utcp, hdr.dst, hdr.src);
// It is for an existing connection.
- uint32_t prevrcvnxt = c->rcv.nxt;
-
// 1. Drop invalid packets.
// 1a. Drop packets that should not happen in our current state.
break;
}
- // 1b. Drop packets with a sequence number not in our receive window.
+ // 1b. Discard data that is not in our receive window.
if(is_reliable(c)) {
bool acceptable;
// 3. Advance snd.una
advanced = seqdiff(hdr.ack, c->snd.una);
- prevrcvnxt = c->rcv.nxt;
if(advanced) {
// RTT measurement
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);
}
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;
}
// Now we send something back if:
- // - we advanced rcv.nxt (ie, we got some data that needs to be ACKed)
+ // - we received data, so we have to send back an ACK
// -> sendatleastone = true
// - or we got an ack, so we should maybe send a bit more data
// -> sendatleastone = false
if(is_reliable(c) || hdr.ctl & SYN || hdr.ctl & FIN) {
- ack(c, len || prevrcvnxt != c->rcv.nxt);
+ ack(c, has_data);
}
return 0;
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;
}
}
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;
}
}