fprintf(stderr, "closing...\n");
utcp_close(c);
+ fprintf(stderr, "\nTesting connection with huge data transfer\n\n");
+
+ c = utcp_connect(b, 7, do_recv, NULL);
+ utcp_set_sndbuf(c, 10240);
+ char buf[20480] = "buf";
+
+ len = utcp_send(c, buf, sizeof buf);
+ if(len != 10240)
+ fprintf(stderr, "Error: utcp_send() returned %zd, expected 10240\n", len);
+
+ fprintf(stderr, "closing...\n");
+ utcp_close(c);
+
+
return 0;
}
}
static void ack(struct utcp_connection *c, bool sendatleastone) {
- uint32_t left = seqdiff(c->snd.last, c->snd.nxt);
+ int32_t left = seqdiff(c->snd.last, c->snd.nxt);
int32_t cwndleft = c->snd.cwnd - seqdiff(c->snd.nxt, c->snd.una);
char *data = c->sndbuf + seqdiff(c->snd.nxt, c->snd.una);
+ fprintf(stderr, "ack, left=%d, cwndleft=%d, sendatleastone=%d\n", left, cwndleft, sendatleastone);
+ if(left < 0)
+ abort();
+
if(cwndleft <= 0)
cwndleft = 0;
data += seglen;
left -= seglen;
+ if(c->state != ESTABLISHED && !left && seglen) {
+ switch(c->state) {
+ case FIN_WAIT_1:
+ case CLOSING:
+ seglen--;
+ pkt.hdr.ctl |= FIN;
+ break;
+ default:
+ break;
+ }
+ }
+
print_packet(c->utcp, "send", &pkt, sizeof pkt.hdr + seglen);
c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + seglen);
} while(left);
newbufsize = c->maxsndbufsize;
else
newbufsize = c->sndbufsize * 2;
+ if(bufused + len > newbufsize) {
+ if(bufused + len > c->maxsndbufsize)
+ newbufsize = c->maxsndbufsize;
+ else
+ newbufsize = bufused + len;
+ }
char *newbuf = realloc(c->sndbuf, newbufsize);
if(newbuf) {
c->sndbuf = newbuf;
c->snd.cwnd += utcp->mtu;
if(c->snd.cwnd > c->maxsndbufsize)
c->snd.cwnd = c->maxsndbufsize;
+ debug("%p increasing cwnd to %u\n", utcp, c->snd.cwnd);
+
+ // Check if we have sent a FIN that is now ACKed.
+ switch(c->state) {
+ case FIN_WAIT_1:
+ if(c->snd.una == c->snd.last)
+ set_state(c, FIN_WAIT_2);
+ break;
+ case CLOSING:
+ if(c->snd.una == c->snd.last) {
+ gettimeofday(&c->conn_timeout, NULL);
+ c->conn_timeout.tv_sec += 60;
+ set_state(c, TIME_WAIT);
+ }
+ break;
+ default:
+ break;
+ }
} else {
if(!len) {
c->dupack++;
set_state(c, CLOSING);
break;
case FIN_WAIT_2:
+ gettimeofday(&c->conn_timeout, NULL);
+ c->conn_timeout.tv_sec += 60;
set_state(c, TIME_WAIT);
break;
case CLOSE_WAIT:
return 0;
}
- // Send FIN
+ c->snd.last++;
- struct hdr hdr;
-
- hdr.src = c->src;
- hdr.dst = c->dst;
- hdr.seq = c->snd.nxt;
- hdr.ack = c->rcv.nxt;
- hdr.wnd = c->snd.wnd;
- hdr.ctl = FIN | ACK;
-
- c->snd.nxt += 1;
-
- print_packet(c->utcp, "send", &hdr, sizeof hdr);
- c->utcp->send(c->utcp, &hdr, sizeof hdr);
+ ack(c, false);
return 0;
}