diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 96a4023c..fe97c012 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -512,8 +512,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) sys_mbox_free(&newconn->recvmbox); sys_mbox_set_invalid(&newconn->recvmbox); netconn_free(newconn); - /* handle backlog counter */ - tcp_backlog_accepted(newpcb); return ERR_MEM; } else { /* Register event with callback */ @@ -774,9 +772,6 @@ netconn_drain(struct netconn *conn) struct netconn *newconn = (struct netconn *)mem; /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ /* pcb might be set to NULL already by err_tcp() */ - if (newconn->pcb.tcp != NULL) { - tcp_backlog_accepted(newconn->pcb.tcp); - } /* drain recvmbox */ netconn_drain(newconn); if (newconn->pcb.tcp != NULL) { diff --git a/src/core/tcp.c b/src/core/tcp.c index 145dbcd3..2285ecc6 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -194,9 +194,12 @@ void tcp_backlog_delayed(struct tcp_pcb* pcb) { LWIP_ASSERT("pcb != NULL", pcb != NULL); - if (pcb->listener != NULL) { - pcb->listener->accepts_pending++; - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + if ((pcb->flags & TF_BACKLOGPEND) == 0) { + if (pcb->listener != NULL) { + pcb->listener->accepts_pending++; + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->flags |= TF_BACKLOGPEND; + } } } @@ -212,9 +215,12 @@ void tcp_backlog_accepted(struct tcp_pcb* pcb) { LWIP_ASSERT("pcb != NULL", pcb != NULL); - if (pcb->listener != NULL) { - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); - pcb->listener->accepts_pending--; + if ((pcb->flags & TF_BACKLOGPEND) != 0) { + if (pcb->listener != NULL) { + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->listener->accepts_pending--; + pcb->flags &= ~TF_BACKLOGPEND; + } } } #endif /* TCP_LISTEN_BACKLOG */ @@ -470,6 +476,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset) tcp_segs_free(pcb->ooseq); } #endif /* TCP_QUEUE_OOSEQ */ + tcp_backlog_accepted(pcb); if (send_rst) { LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); @@ -1599,7 +1606,9 @@ tcp_arg(struct tcp_pcb *pcb, void *arg) { /* This function is allowed to be called for both listen pcbs and connection pcbs. */ - pcb->callback_arg = arg; + if (pcb != NULL) { + pcb->callback_arg = arg; + } } #if LWIP_CALLBACK_API @@ -1613,8 +1622,10 @@ tcp_arg(struct tcp_pcb *pcb, void *arg) void tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) { - LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); - pcb->recv = recv; + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); + pcb->recv = recv; + } } /** @@ -1627,8 +1638,10 @@ tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) void tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) { - LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); - pcb->sent = sent; + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); + pcb->sent = sent; + } } /** @@ -1642,8 +1655,10 @@ tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) void tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) { - LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); - pcb->errf = err; + if (pcb != NULL) { + LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); + pcb->errf = err; + } } /** @@ -1657,7 +1672,7 @@ tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) void tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) { - if (pcb->state == LISTEN) { + if ((pcb != NULL) && (pcb->state == LISTEN)) { struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)pcb; lpcb->accept = accept; } @@ -1698,14 +1713,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); -#if TCP_LISTEN_BACKLOG - if (pcb->state == SYN_RCVD) { - tcp_backlog_accepted(pcb); - /* prevent executing this again: */ - pcb->listener = NULL; - } -#endif /* TCP_LISTEN_BACKLOG */ - + tcp_backlog_accepted(pcb); if (pcb->refused_data != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 7c7775d5..8f56b9f6 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -571,6 +571,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) } #if TCP_LISTEN_BACKLOG pcb->accepts_pending++; + npcb->flags |= TF_BACKLOGPEND; #endif /* TCP_LISTEN_BACKLOG */ /* Set up the new PCB. */ ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index 9edcf169..7166485a 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -131,13 +131,17 @@ typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); #define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) #define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) typedef u32_t tcpwnd_size_t; -typedef u16_t tcpflags_t; #else #define RCV_WND_SCALE(pcb, wnd) (wnd) #define SND_WND_SCALE(pcb, wnd) (wnd) #define TCPWND16(x) (x) #define TCP_WND_MAX(pcb) TCP_WND typedef u16_t tcpwnd_size_t; +#endif + +#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG +typedef u16_t tcpflags_t; +#else typedef u8_t tcpflags_t; #endif @@ -207,6 +211,9 @@ struct tcp_pcb { #define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ #if LWIP_WND_SCALE #define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ +#endif +#if TCP_LISTEN_BACKLOG +#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ #endif /* the rest of the fields are in host byte order