From 82318c0ef1f1f66ad07210b6294a2f5b19a8aaea Mon Sep 17 00:00:00 2001 From: goldsimon Date: Thu, 21 Jan 2010 18:43:37 +0000 Subject: [PATCH] Fixed bug #28651 (tcp_connect: no callbacks called if tcp_enqueue fails) both in raw- and netconn-API --- CHANGELOG | 4 ++++ src/api/api_msg.c | 9 +++++++-- src/core/tcp.c | 35 ++++++++++++++++++----------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bee66bb7..4b17d173 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -50,6 +50,10 @@ HISTORY ++ Bugfixes: + 2010-01-21: Simon Goldschmidt + * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called + if tcp_enqueue fails) both in raw- and netconn-API + 2010-01-19: Simon Goldschmidt * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 8dfd34e6..0a0c9ea2 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -882,13 +882,18 @@ do_connect(struct api_msg_msg *msg) #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - msg->conn->state = NETCONN_CONNECT; - msg->conn->current_msg = msg; setup_tcp(msg->conn); msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, do_connected); /* sys_sem_signal() is called from do_connected (or err_tcp()), * when the connection is established! */ + if (msg->err == ERR_OK) { + msg->conn->state = NETCONN_CONNECT; + msg->conn->current_msg = msg; + } else { + /* tcp_connect failed, so do_connected will not be called: return now */ + sys_sem_signal(msg->conn->op_completed); + } break; #endif /* LWIP_TCP */ default: diff --git a/src/core/tcp.c b/src/core/tcp.c index e341af31..a39857cf 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -78,12 +78,12 @@ const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; /* The TCP PCB lists. */ /** List of all TCP PCBs bound but not yet (connected || listening) */ -struct tcp_pcb *tcp_bound_pcbs; +struct tcp_pcb *tcp_bound_pcbs; /** List of all TCP PCBs in LISTEN state */ union tcp_listen_pcbs_t tcp_listen_pcbs; /** List of all TCP PCBs that are in a state in which * they accept or send data. */ -struct tcp_pcb *tcp_active_pcbs; +struct tcp_pcb *tcp_active_pcbs; /** List of all TCP PCBs in TIME-WAIT state */ struct tcp_pcb *tcp_tw_pcbs; @@ -550,25 +550,26 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port, #endif /* TCP_CALCULATE_EFF_SEND_MSS */ pcb->cwnd = 1; pcb->ssthresh = pcb->mss * 10; - pcb->state = SYN_SENT; -#if LWIP_CALLBACK_API +#if LWIP_CALLBACK_API pcb->connected = connected; #endif /* LWIP_CALLBACK_API */ - TCP_RMV(&tcp_bound_pcbs, pcb); - TCP_REG(&tcp_active_pcbs, pcb); - snmp_inc_tcpactiveopens(); - ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS #if LWIP_TCP_TIMESTAMPS | TF_SEG_OPTS_TS #endif ); - if (ret == ERR_OK) { + if (ret == ERR_OK) { + /* SYN segment was enqueued, changed the pcbs state now */ + pcb->state = SYN_SENT; + TCP_RMV(&tcp_bound_pcbs, pcb); + TCP_REG(&tcp_active_pcbs, pcb); + snmp_inc_tcpactiveopens(); + tcp_output(pcb); } return ret; -} +} /** * Called every 500 ms and implements the retransmission timer and the timer that @@ -671,15 +672,15 @@ tcp_slowtmr(void) } /* Check if KEEPALIVE should be sent */ - if((pcb->so_options & SOF_KEEPALIVE) && - ((pcb->state == ESTABLISHED) || + if((pcb->so_options & SOF_KEEPALIVE) && + ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { #if LWIP_TCP_KEEPALIVE - if((u32_t)(tcp_ticks - pcb->tmr) > + if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl)) / TCP_SLOW_INTERVAL) #else - if((u32_t)(tcp_ticks - pcb->tmr) > + if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) #endif /* LWIP_TCP_KEEPALIVE */ { @@ -708,7 +709,7 @@ tcp_slowtmr(void) /* If this PCB has queued out of sequence data, but has been inactive for too long, will drop the data (it will eventually be retransmitted). */ -#if TCP_QUEUE_OOSEQ +#if TCP_QUEUE_OOSEQ if (pcb->ooseq != NULL && (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { tcp_segs_free(pcb->ooseq); @@ -736,7 +737,7 @@ tcp_slowtmr(void) /* If the PCB should be removed, do it. */ if (pcb_remove) { - tcp_pcb_purge(pcb); + tcp_pcb_purge(pcb); /* Remove PCB from tcp_active_pcbs list. */ if (prev != NULL) { LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); @@ -791,7 +792,7 @@ tcp_slowtmr(void) /* If the PCB should be removed, do it. */ if (pcb_remove) { - tcp_pcb_purge(pcb); + tcp_pcb_purge(pcb); /* Remove PCB from tcp_tw_pcbs list. */ if (prev != NULL) { LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);