mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-08 16:11:18 +00:00
Close connection fast if both sides sent FIN
This commit is contained in:
1 parent
8dbfcbff58
commit
fc0e1ee311
2 files changed
+26
-6
No files matched your search
+13
-3
@@ -4108,6 +4108,8 @@ struct connstate {
|
|||||||
#define MIP_TTYPE_FIN 4 // FIN sent, waiting until terminating the connection
|
#define MIP_TTYPE_FIN 4 // FIN sent, waiting until terminating the connection
|
||||||
uint8_t tmiss; // Number of keep-alive misses
|
uint8_t tmiss; // Number of keep-alive misses
|
||||||
struct mg_iobuf raw; // For TLS only. Incoming raw data
|
struct mg_iobuf raw; // For TLS only. Incoming raw data
|
||||||
|
bool fin_sent; // We have sent FIN to the peer
|
||||||
|
bool fin_rcvd; // We have received FIN from the peer
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@@ -4722,7 +4724,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handle_tls_recv(struct mg_connection *c) {
|
static void handle_tls_recv(struct mg_connection *c) {
|
||||||
size_t avail = mg_tls_pending(c);
|
size_t avail = mg_tls_pending(c);
|
||||||
size_t min = avail > MG_MAX_RECV_SIZE ? MG_MAX_RECV_SIZE : avail;
|
size_t min = avail > MG_MAX_RECV_SIZE ? MG_MAX_RECV_SIZE : avail;
|
||||||
struct mg_iobuf *io = &c->recv;
|
struct mg_iobuf *io = &c->recv;
|
||||||
if (io->size - io->len < min && !mg_iobuf_resize(io, io->len + min)) {
|
if (io->size - io->len < min && !mg_iobuf_resize(io, io->len + min)) {
|
||||||
@@ -4736,7 +4738,7 @@ static void handle_tls_recv(struct mg_connection *c) {
|
|||||||
// Decrypted successfully - trigger MG_EV_READ
|
// Decrypted successfully - trigger MG_EV_READ
|
||||||
io->len += (size_t) n;
|
io->len += (size_t) n;
|
||||||
mg_call(c, MG_EV_READ, &n);
|
mg_call(c, MG_EV_READ, &n);
|
||||||
} // else n < 0: outstanding data to be moved to c->recv
|
} // else n < 0: outstanding data to be moved to c->recv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4752,21 +4754,28 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
// closure process
|
// closure process
|
||||||
uint8_t flags = TH_ACK;
|
uint8_t flags = TH_ACK;
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
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) {
|
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||||
if (s->seq == mg_htonl(pkt->tcp->ack)) { // Simultaneous closure ?
|
if (s->seq == mg_htonl(pkt->tcp->ack)) { // Simultaneous closure ?
|
||||||
s->seq++; // Yes. Increment our SEQ
|
s->seq++; // Yes. Increment our SEQ
|
||||||
} else { // Otherwise,
|
} else { // Otherwise,
|
||||||
s->seq = mg_htonl(pkt->tcp->ack); // Set to peer's ACK
|
s->seq = mg_htonl(pkt->tcp->ack); // Set to peer's ACK
|
||||||
}
|
}
|
||||||
|
if (s->fin_sent) c->is_closing = 1; // Both sides closed, we're done
|
||||||
} else {
|
} else {
|
||||||
flags |= TH_FIN;
|
flags |= TH_FIN;
|
||||||
c->is_draining = 1;
|
c->is_draining = 1;
|
||||||
|
s->fin_sent = true;
|
||||||
settmout(c, MIP_TTYPE_FIN);
|
settmout(c, MIP_TTYPE_FIN);
|
||||||
}
|
}
|
||||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
} else if (pkt->pay.len == 0) {
|
} else if (pkt->pay.len == 0) {
|
||||||
// TODO(cpq): handle this peer's ACK
|
// If we receive a final ACK in TCP closure, close immediately,
|
||||||
|
// don't wait until MIP_TTYPE_FIN timeout expires
|
||||||
|
if (s->fin_rcvd && s->fin_sent) {
|
||||||
|
c->is_closing = true;
|
||||||
|
}
|
||||||
} else if (seq != s->ack) {
|
} else if (seq != s->ack) {
|
||||||
uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
||||||
if (s->ack == ack) {
|
if (s->ack == ack) {
|
||||||
@@ -5213,6 +5222,7 @@ static void init_closure(struct mg_connection *c) {
|
|||||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
|
||||||
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
||||||
settmout(c, MIP_TTYPE_FIN);
|
settmout(c, MIP_TTYPE_FIN);
|
||||||
|
s->fin_sent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-3
@@ -28,6 +28,8 @@ struct connstate {
|
|||||||
#define MIP_TTYPE_FIN 4 // FIN sent, waiting until terminating the connection
|
#define MIP_TTYPE_FIN 4 // FIN sent, waiting until terminating the connection
|
||||||
uint8_t tmiss; // Number of keep-alive misses
|
uint8_t tmiss; // Number of keep-alive misses
|
||||||
struct mg_iobuf raw; // For TLS only. Incoming raw data
|
struct mg_iobuf raw; // For TLS only. Incoming raw data
|
||||||
|
bool fin_sent; // We have sent FIN to the peer
|
||||||
|
bool fin_rcvd; // We have received FIN from the peer
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@@ -642,7 +644,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handle_tls_recv(struct mg_connection *c) {
|
static void handle_tls_recv(struct mg_connection *c) {
|
||||||
size_t avail = mg_tls_pending(c);
|
size_t avail = mg_tls_pending(c);
|
||||||
size_t min = avail > MG_MAX_RECV_SIZE ? MG_MAX_RECV_SIZE : avail;
|
size_t min = avail > MG_MAX_RECV_SIZE ? MG_MAX_RECV_SIZE : avail;
|
||||||
struct mg_iobuf *io = &c->recv;
|
struct mg_iobuf *io = &c->recv;
|
||||||
if (io->size - io->len < min && !mg_iobuf_resize(io, io->len + min)) {
|
if (io->size - io->len < min && !mg_iobuf_resize(io, io->len + min)) {
|
||||||
@@ -656,7 +658,7 @@ static void handle_tls_recv(struct mg_connection *c) {
|
|||||||
// Decrypted successfully - trigger MG_EV_READ
|
// Decrypted successfully - trigger MG_EV_READ
|
||||||
io->len += (size_t) n;
|
io->len += (size_t) n;
|
||||||
mg_call(c, MG_EV_READ, &n);
|
mg_call(c, MG_EV_READ, &n);
|
||||||
} // else n < 0: outstanding data to be moved to c->recv
|
} // else n < 0: outstanding data to be moved to c->recv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,21 +674,28 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
|
|||||||
// closure process
|
// closure process
|
||||||
uint8_t flags = TH_ACK;
|
uint8_t flags = TH_ACK;
|
||||||
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
|
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) {
|
if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
|
||||||
if (s->seq == mg_htonl(pkt->tcp->ack)) { // Simultaneous closure ?
|
if (s->seq == mg_htonl(pkt->tcp->ack)) { // Simultaneous closure ?
|
||||||
s->seq++; // Yes. Increment our SEQ
|
s->seq++; // Yes. Increment our SEQ
|
||||||
} else { // Otherwise,
|
} else { // Otherwise,
|
||||||
s->seq = mg_htonl(pkt->tcp->ack); // Set to peer's ACK
|
s->seq = mg_htonl(pkt->tcp->ack); // Set to peer's ACK
|
||||||
}
|
}
|
||||||
|
if (s->fin_sent) c->is_closing = 1; // Both sides closed, we're done
|
||||||
} else {
|
} else {
|
||||||
flags |= TH_FIN;
|
flags |= TH_FIN;
|
||||||
c->is_draining = 1;
|
c->is_draining = 1;
|
||||||
|
s->fin_sent = true;
|
||||||
settmout(c, MIP_TTYPE_FIN);
|
settmout(c, MIP_TTYPE_FIN);
|
||||||
}
|
}
|
||||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
|
||||||
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
|
||||||
} else if (pkt->pay.len == 0) {
|
} else if (pkt->pay.len == 0) {
|
||||||
// TODO(cpq): handle this peer's ACK
|
// If we receive a final ACK in TCP closure, close immediately,
|
||||||
|
// don't wait until MIP_TTYPE_FIN timeout expires
|
||||||
|
if (s->fin_rcvd && s->fin_sent) {
|
||||||
|
c->is_closing = true;
|
||||||
|
}
|
||||||
} else if (seq != s->ack) {
|
} else if (seq != s->ack) {
|
||||||
uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
|
||||||
if (s->ack == ack) {
|
if (s->ack == ack) {
|
||||||
@@ -1133,6 +1142,7 @@ static void init_closure(struct mg_connection *c) {
|
|||||||
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
|
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
|
||||||
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
|
||||||
settmout(c, MIP_TTYPE_FIN);
|
settmout(c, MIP_TTYPE_FIN);
|
||||||
|
s->fin_sent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user