diff --git a/mongoose.c b/mongoose.c index 30213817..db675f79 100644 --- a/mongoose.c +++ b/mongoose.c @@ -8280,6 +8280,14 @@ void mg_multicast_restore(struct mg_connection *c, uint8_t *from) { #define MG_TCPIP_WIN 6000 // TCP window size #endif +#ifndef MG_TCPIP_MIN_MSS +#define MG_TCPIP_MIN_MSS 64 // Minimum peer MSS +#endif + +#ifndef MG_TCPIP_TXQ_ALIGN +#define MG_TCPIP_TXQ_ALIGN 1024 // Retransmit queue allocation quantum +#endif + struct connstate { uint32_t seq, ack; // TCP seq/ack counters uint64_t timer; // TCP timer (see 'ttype' below) @@ -9581,7 +9589,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, } s = (struct connstate *) (c + 1); s->retransmit = lsn->mgr->ifp->enable_tcp_retransmit; - s->txq.align = MG_IO_SIZE; + s->txq.align = MG_TCPIP_TXQ_ALIGN; s->dmss = mss; // from options in client SYN s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); s->win = mg_ntohs(pkt->tcp->win), s->maxseq = (uint32_t) (s->seq + s->win); @@ -9683,6 +9691,7 @@ static size_t txq_next(struct connstate *s, uint8_t **buf) { } static bool txq_add(struct connstate *s, const void *buf, size_t len) { + assert(len > 0); uint32_t n = (uint32_t) len; size_t off = s->txq.len, total = sizeof(n) + len; if (mg_iobuf_add(&s->txq, off, NULL, total) != total) return false; @@ -9960,8 +9969,11 @@ static bool handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) { if (kind == 0) break; // End of Option List if (len < 2 || opts[1] == 0 || opts[1] > len) return false; // Malformed optlen = opts[1]; - if (kind == 2 && optlen == 4) // set received MSS - s->dmss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); + if (kind == 2 && optlen == 4) { // set received MSS + uint16_t mss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); + if (mss == 0 || mss < MG_TCPIP_MIN_MSS) return false; + s->dmss = mss; + } } MG_VERBOSE(("kind: %u, optlen: %u, len: %d\n", kind, optlen, len)); opts += optlen; @@ -10464,6 +10476,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { // If L2 address is not set, make a random one; fill MTU mg_l2_init(ifp); ifp->mtu = ifp->l2mtu; + if (MG_ENABLE_TCPIP_TCPRTX) ifp->enable_tcp_retransmit = true; if (ifp->dhcp_name[0] == '\0') // If DHCP name is not set, use "mip" memcpy(ifp->dhcp_name, "mip", 4); @@ -10519,7 +10532,7 @@ void mg_connect_resolved(struct mg_connection *c) { uint8_t *l2addr; struct connstate *s = (struct connstate *) (c + 1); s->retransmit = ifp->enable_tcp_retransmit; - s->txq.align = MG_IO_SIZE; + s->txq.align = MG_TCPIP_TXQ_ALIGN; c->is_resolving = 0; if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE; c->loc.port = mg_htons(ifp->eport++); diff --git a/mongoose.h b/mongoose.h index 995617ab..8b844644 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1456,6 +1456,14 @@ struct timeval { #define MG_ENABLE_TCPIP_DRIVER_INIT 1 // enabled built-in driver for #endif // Mongoose built-in network stack +#ifndef MG_ENABLE_TCPIP_TCPRTX +#define MG_ENABLE_TCPIP_TCPRTX 0 // TCP retransmission queue +#endif + +#ifndef MG_TCPIP_DHCPNAME_SIZE +#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size +#endif + #ifndef MG_TCPIP_IP // e.g. MG_IPV4(192, 168, 0, 223) #define MG_TCPIP_IP MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP) #endif @@ -1492,10 +1500,6 @@ struct timeval { #define MG_SET_MAC_ADDRESS(mac) #endif -#ifndef MG_TCPIP_DHCPNAME_SIZE -#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size -#endif - #ifndef MG_SET_WIFI_CONFIG #define MG_SET_WIFI_CONFIG(ifp, driver_data) #endif diff --git a/src/config.h b/src/config.h index 49250e9c..3681f524 100644 --- a/src/config.h +++ b/src/config.h @@ -175,6 +175,14 @@ #define MG_ENABLE_TCPIP_DRIVER_INIT 1 // enabled built-in driver for #endif // Mongoose built-in network stack +#ifndef MG_ENABLE_TCPIP_TCPRTX +#define MG_ENABLE_TCPIP_TCPRTX 0 // TCP retransmission queue +#endif + +#ifndef MG_TCPIP_DHCPNAME_SIZE +#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size +#endif + #ifndef MG_TCPIP_IP // e.g. MG_IPV4(192, 168, 0, 223) #define MG_TCPIP_IP MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP) #endif @@ -211,10 +219,6 @@ #define MG_SET_MAC_ADDRESS(mac) #endif -#ifndef MG_TCPIP_DHCPNAME_SIZE -#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size -#endif - #ifndef MG_SET_WIFI_CONFIG #define MG_SET_WIFI_CONFIG(ifp, driver_data) #endif diff --git a/src/net_builtin.c b/src/net_builtin.c index f37e4e09..beb29a38 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -22,6 +22,14 @@ #define MG_TCPIP_WIN 6000 // TCP window size #endif +#ifndef MG_TCPIP_MIN_MSS +#define MG_TCPIP_MIN_MSS 64 // Minimum peer MSS +#endif + +#ifndef MG_TCPIP_TXQ_ALIGN +#define MG_TCPIP_TXQ_ALIGN 1024 // Retransmit queue allocation quantum +#endif + struct connstate { uint32_t seq, ack; // TCP seq/ack counters uint64_t timer; // TCP timer (see 'ttype' below) @@ -1323,7 +1331,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, } s = (struct connstate *) (c + 1); s->retransmit = lsn->mgr->ifp->enable_tcp_retransmit; - s->txq.align = MG_IO_SIZE; + s->txq.align = MG_TCPIP_TXQ_ALIGN; s->dmss = mss; // from options in client SYN s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); s->win = mg_ntohs(pkt->tcp->win), s->maxseq = (uint32_t) (s->seq + s->win); @@ -1425,6 +1433,7 @@ static size_t txq_next(struct connstate *s, uint8_t **buf) { } static bool txq_add(struct connstate *s, const void *buf, size_t len) { + assert(len > 0); uint32_t n = (uint32_t) len; size_t off = s->txq.len, total = sizeof(n) + len; if (mg_iobuf_add(&s->txq, off, NULL, total) != total) return false; @@ -1702,8 +1711,11 @@ static bool handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) { if (kind == 0) break; // End of Option List if (len < 2 || opts[1] == 0 || opts[1] > len) return false; // Malformed optlen = opts[1]; - if (kind == 2 && optlen == 4) // set received MSS - s->dmss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); + if (kind == 2 && optlen == 4) { // set received MSS + uint16_t mss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); + if (mss == 0 || mss < MG_TCPIP_MIN_MSS) return false; + s->dmss = mss; + } } MG_VERBOSE(("kind: %u, optlen: %u, len: %d\n", kind, optlen, len)); opts += optlen; @@ -2206,6 +2218,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { // If L2 address is not set, make a random one; fill MTU mg_l2_init(ifp); ifp->mtu = ifp->l2mtu; + if (MG_ENABLE_TCPIP_TCPRTX) ifp->enable_tcp_retransmit = true; if (ifp->dhcp_name[0] == '\0') // If DHCP name is not set, use "mip" memcpy(ifp->dhcp_name, "mip", 4); @@ -2261,7 +2274,7 @@ void mg_connect_resolved(struct mg_connection *c) { uint8_t *l2addr; struct connstate *s = (struct connstate *) (c + 1); s->retransmit = ifp->enable_tcp_retransmit; - s->txq.align = MG_IO_SIZE; + s->txq.align = MG_TCPIP_TXQ_ALIGN; c->is_resolving = 0; if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE; c->loc.port = mg_htons(ifp->eport++);