aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--tcp.c33
1 files changed, 11 insertions, 22 deletions
diff --git a/tcp.c b/tcp.c
index 6c6a6dd..e9d3be7 100644
--- a/tcp.c
+++ b/tcp.c
@@ -970,26 +970,27 @@ static int tcp_is_dupack(int s, uint32_t ack_seq)
}
/**
- * tcp_sock_consume() - Consume (discard) data from socket buffer
+ * tcp_sock_consume() - Consume (discard) data from buffer, update ACK sequence
* @s: File descriptor number for socket
* @ack_seq: ACK sequence, host order
- *
- * Return: negative on invalid sequence, 0 otherwise
*/
-static int tcp_sock_consume(int s, uint32_t ack_seq)
+static void tcp_sock_consume(int s, uint32_t ack_seq)
{
int to_ack;
/* Implicitly take care of wrap-arounds */
to_ack = ack_seq - tc[s].seq_ack_from_tap;
+ /* Simply ignore out-of-order ACKs: we already consumed the data we
+ * needed from the buffer, and we won't rewind back to a lower ACK
+ * sequence.
+ */
if (to_ack < 0)
- return -EIO;
+ return;
recv(s, NULL, to_ack, MSG_DONTWAIT | MSG_TRUNC);
- tc[s].seq_ack_from_tap = ack_seq;
- return 0;
+ tc[s].seq_ack_from_tap = ack_seq;
}
/**
@@ -1146,12 +1147,7 @@ void tcp_tap_handler(struct ctx *c, int af, void *addr, char *in, size_t len)
if (len == off)
retrans = tcp_is_dupack(s, ntohl(th->ack_seq));
- if (tcp_sock_consume(s, ntohl(th->ack_seq))) {
- tcp_rst(c, s);
- return;
- }
-
- tc[s].seq_ack_from_tap = ntohl(th->ack_seq);
+ tcp_sock_consume(s, ntohl(th->ack_seq));
if (retrans)
tc[s].seq_to_tap = tc[s].seq_ack_from_tap;
@@ -1177,10 +1173,7 @@ void tcp_tap_handler(struct ctx *c, int af, void *addr, char *in, size_t len)
break;
case CLOSE_WAIT:
- if (tcp_sock_consume(s, ntohl(th->ack_seq))) {
- tcp_rst(c, s);
- return;
- }
+ tcp_sock_consume(s, ntohl(th->ack_seq));
if (skip < len - off &&
tcp_send_to_sock(c, s, in + off + skip, len - off - skip,
@@ -1282,11 +1275,7 @@ void tcp_sock_handler(struct ctx *c, int s, uint32_t events)
shutdown(s, SHUT_RD);
tcp_data_from_sock(c, s);
tcp_send_to_tap(c, s, FIN | ACK, NULL, 0);
-
- if (tcp_sock_consume(s, tc[s].seq_ack_from_tap)) {
- tcp_rst(c, s);
- return;
- }
+ tcp_sock_consume(s, tc[s].seq_ack_from_tap);
}
}
}