if(c->state == CLOSED) {
debug(c, "got packet for closed connection\n");
- return 0;
+ goto reset;
}
// It is for an existing connection.
}
}
- if(hdr.ctl & ACK && (seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0)) {
- debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used);
-
- // Ignore unacceptable RST packets.
- if(hdr.ctl & RST) {
- return 0;
- }
-
- goto reset;
- }
-
// 2. Handle RST packets
if(hdr.ctl & RST) {
// 3. Advance snd.una
+ if(seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0) {
+ debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used);
+ goto reset;
+ }
+
advanced = seqdiff(hdr.ack, c->snd.una);
if(advanced) {
- if(c->reapable && !is_reliable(c)) {
- // TODO: we should also send RST for reliable connections
- goto reset;
- }
-
// RTT measurement
if(c->rtt_start.tv_sec) {
if(c->rtt_seq == hdr.ack) {
return 0;
case ESTABLISHED:
+ break;
+
case FIN_WAIT_1:
case FIN_WAIT_2:
+ if(c->reapable) {
+ // We already closed the connection and are not interested in more data.
+ goto reset;
+ }
+
break;
case CLOSE_WAIT:
hdr.src = c->src;
hdr.dst = c->dst;
hdr.seq = c->snd.nxt;
- hdr.ack = 0;
+ hdr.ack = c->rcv.nxt;
hdr.wnd = 0;
hdr.ctl = RST;
}
int utcp_close(struct utcp_connection *c) {
- if(c->rcvbuf.used) {
- return reset_connection(c) ? 0 : -1;
- }
-
if(utcp_shutdown(c, SHUT_RDWR) && errno != ENOTCONN) {
return -1;
}