mirror of
https://github.com/cesanta/mongoose.git
synced 2025-08-06 13:37:34 +08:00
Fix ignoring SEQ on FIN
This commit is contained in:
parent
6769223ce1
commit
467fbf4bb4
@ -4836,10 +4836,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
||||
uint32_t rem_ip;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (pkt->tcp->flags & TH_FIN) {
|
||||
uint8_t flags = TH_ACK;
|
||||
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
|
||||
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
|
||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||
return;
|
||||
}
|
||||
// If we initiated the closure, we reply with ACK upon receiving FIN
|
||||
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
||||
// closure process
|
||||
uint8_t flags = TH_ACK;
|
||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
||||
s->fin_rcvd = true;
|
||||
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||
|
@ -688,10 +688,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
||||
uint32_t rem_ip;
|
||||
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
|
||||
if (pkt->tcp->flags & TH_FIN) {
|
||||
uint8_t flags = TH_ACK;
|
||||
if (mg_ntohl(pkt->tcp->seq) != s->ack) {
|
||||
MG_VERBOSE(("ignoring FIN, SEQ != ACK: %x %x", mg_ntohl(pkt->tcp->seq), s->ack));
|
||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
|
||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||
return;
|
||||
}
|
||||
// If we initiated the closure, we reply with ACK upon receiving FIN
|
||||
// If we didn't initiate it, we reply with FIN as part of the normal TCP
|
||||
// closure process
|
||||
uint8_t flags = TH_ACK;
|
||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
||||
s->fin_rcvd = true;
|
||||
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||
|
@ -120,7 +120,7 @@ static bool if_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
|
||||
static size_t if_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
struct driver_data *driver_data = (struct driver_data *) ifp->driver_data;
|
||||
if (!driver_data->len) return 0;
|
||||
if (driver_data->len == 0) return 0;
|
||||
if (len > driver_data->len) len = driver_data->len;
|
||||
memcpy(buf, driver_data->buf, len);
|
||||
driver_data->len = 0; // cleaning up the buffer
|
||||
@ -142,10 +142,10 @@ static void create_tcp_pkt(struct eth *e, struct ip *ip, uint32_t seq,
|
||||
t.ack = mg_htonl(ack);
|
||||
t.off = 5 << 4;
|
||||
memcpy(s_driver_data.buf, e, sizeof(*e));
|
||||
ip->len = mg_htons((uint16_t)(sizeof(*ip) + sizeof(struct tcp) + payload_len));
|
||||
memcpy(s_driver_data.buf + sizeof(*e), ip, sizeof(*ip));
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(struct tcp));
|
||||
s_driver_data.len =
|
||||
sizeof(*e) + sizeof(*ip) + sizeof(struct tcp) + payload_len;
|
||||
memcpy(s_driver_data.buf + sizeof(*e) + sizeof(*ip), &t, sizeof(t));
|
||||
s_driver_data.len = sizeof(*e) + sizeof(*ip) + sizeof(t) + payload_len;
|
||||
}
|
||||
|
||||
static void init_tcp_handshake(struct eth *e, struct ip *ip, struct tcp *tcp,
|
||||
@ -199,13 +199,10 @@ static void test_retransmit(void) {
|
||||
// setting the IP header
|
||||
memset(&ip, 0, sizeof(ip));
|
||||
ip.ver = 4 << 4, ip.proto = 6;
|
||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
||||
|
||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||
|
||||
// packet with seq_no = 1001
|
||||
ip.len =
|
||||
mg_htons(sizeof(struct ip) + sizeof(struct tcp) + /* TCP Payload */ 2);
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
@ -253,6 +250,39 @@ static void test_retransmit(void) {
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1005))); // OK
|
||||
|
||||
// packet with seq_no = 1005 got delayed, send FIN with seq_no = 1007
|
||||
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN, 0);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
start = mg_millis();
|
||||
while (!received_response(&s_driver_data)) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
now = mg_millis() - start;
|
||||
if (now > 2 * MIP_TCP_ACK_MS)
|
||||
ASSERT(0); // response should have been received by now
|
||||
}
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1005))); // dup ACK
|
||||
|
||||
// retransmitting packet with seq_no = 1005
|
||||
create_tcp_pkt(&e, &ip, 1005, 1, TH_PUSH | TH_ACK, 2);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == TH_ACK));
|
||||
ASSERT((t->ack == mg_htonl(1007))); // OK
|
||||
|
||||
// retransmitting FIN packet with seq_no = 1007
|
||||
create_tcp_pkt(&e, &ip, 1007, 1, TH_FIN | TH_ACK, 0);
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
while (!received_response(&s_driver_data)) mg_mgr_poll(&mgr, 0);
|
||||
t = (struct tcp *) (s_driver_data.buf + sizeof(struct eth) +
|
||||
sizeof(struct ip));
|
||||
ASSERT((t->flags == (TH_FIN | TH_ACK))); // check we respond with FIN ACK
|
||||
ASSERT((t->ack == mg_htonl(1008))); // OK
|
||||
|
||||
s_driver_data.len = 0;
|
||||
mg_mgr_free(&mgr);
|
||||
}
|
||||
@ -285,12 +315,10 @@ static void test_frag_recv_path(void) {
|
||||
// setting the IP header
|
||||
memset(&ip, 0, sizeof(ip));
|
||||
ip.ver = 0x45, ip.proto = 6;
|
||||
ip.len = mg_htons(sizeof(ip) + sizeof(struct tcp));
|
||||
|
||||
init_tcp_handshake(&e, &ip, t, &mgr);
|
||||
|
||||
// send fragmented TCP packet
|
||||
ip.len = mg_htons(sizeof(struct ip) + sizeof(struct tcp) + 1000);
|
||||
ip.frag |= IP_MORE_FRAGS_MSK; // setting More Fragments bit to 1
|
||||
create_tcp_pkt(&e, &ip, 1001, 1, TH_PUSH | TH_ACK, 1000);
|
||||
s_sent_fragment = 1; // "enable" fn
|
||||
|
Loading…
Reference in New Issue
Block a user