#endif
c->snd.una = c->snd.iss;
c->snd.nxt = c->snd.iss + 1;
- c->rcv.wnd = utcp->mtu;
c->snd.last = c->snd.nxt;
c->snd.cwnd = utcp->mtu;
c->utcp = utcp;
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;
}
pkt.hdr.dst = c->dst;
pkt.hdr.seq = c->snd.iss;
pkt.hdr.ack = 0;
- pkt.hdr.wnd = c->rcv.wnd;
+ pkt.hdr.wnd = c->rcvbuf.maxsize;
pkt.hdr.ctl = SYN;
pkt.hdr.aux = 0x0101;
pkt.init[0] = 1;
pkt->hdr.src = c->src;
pkt->hdr.dst = c->dst;
pkt->hdr.ack = c->rcv.nxt;
- pkt->hdr.wnd = c->snd.wnd;
+ pkt->hdr.wnd = c->rcvbuf.maxsize;
pkt->hdr.ctl = ACK;
pkt->hdr.aux = 0;
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) {
pkt->hdr.src = c->src;
pkt->hdr.dst = c->dst;
- pkt->hdr.wnd = c->rcv.wnd;
+ pkt->hdr.wnd = c->rcvbuf.maxsize;
pkt->hdr.aux = 0;
switch(c->state) {
c->flags = UTCP_TCP;
}
+synack:
// Return SYN+ACK, go to SYN_RECEIVED state
c->snd.wnd = hdr.wnd;
c->rcv.irs = hdr.seq;
pkt.hdr.dst = c->dst;
pkt.hdr.ack = c->rcv.irs + 1;
pkt.hdr.seq = c->snd.iss;
- pkt.hdr.wnd = c->rcv.wnd;
+ pkt.hdr.wnd = c->rcvbuf.maxsize;
pkt.hdr.ctl = SYN | ACK;
if(init) {
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);
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: