Fixed bug #28651 (tcp_connect: no callbacks called if tcp_enqueue fails) both in raw- and netconn-API

This commit is contained in:
goldsimon 2010-01-21 18:43:37 +00:00
parent 60696a8485
commit 82318c0ef1
3 changed files with 29 additions and 19 deletions

View File

@ -50,6 +50,10 @@ HISTORY
++ Bugfixes: ++ 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 2010-01-19: Simon Goldschmidt
* api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp

View File

@ -882,13 +882,18 @@ do_connect(struct api_msg_msg *msg)
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
#if LWIP_TCP #if LWIP_TCP
case NETCONN_TCP: case NETCONN_TCP:
msg->conn->state = NETCONN_CONNECT;
msg->conn->current_msg = msg;
setup_tcp(msg->conn); setup_tcp(msg->conn);
msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
do_connected); do_connected);
/* sys_sem_signal() is called from do_connected (or err_tcp()), /* sys_sem_signal() is called from do_connected (or err_tcp()),
* when the connection is established! */ * 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; break;
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
default: default:

View File

@ -78,12 +78,12 @@ const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
/* The TCP PCB lists. */ /* The TCP PCB lists. */
/** List of all TCP PCBs bound but not yet (connected || listening) */ /** 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 */ /** List of all TCP PCBs in LISTEN state */
union tcp_listen_pcbs_t tcp_listen_pcbs; union tcp_listen_pcbs_t tcp_listen_pcbs;
/** List of all TCP PCBs that are in a state in which /** List of all TCP PCBs that are in a state in which
* they accept or send data. */ * 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 */ /** List of all TCP PCBs in TIME-WAIT state */
struct tcp_pcb *tcp_tw_pcbs; 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 */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1; pcb->cwnd = 1;
pcb->ssthresh = pcb->mss * 10; pcb->ssthresh = pcb->mss * 10;
pcb->state = SYN_SENT; #if LWIP_CALLBACK_API
#if LWIP_CALLBACK_API
pcb->connected = connected; pcb->connected = connected;
#endif /* LWIP_CALLBACK_API */ #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 ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS
#if LWIP_TCP_TIMESTAMPS #if LWIP_TCP_TIMESTAMPS
| TF_SEG_OPTS_TS | TF_SEG_OPTS_TS
#endif #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); tcp_output(pcb);
} }
return ret; return ret;
} }
/** /**
* Called every 500 ms and implements the retransmission timer and the timer that * 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 */ /* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && if((pcb->so_options & SOF_KEEPALIVE) &&
((pcb->state == ESTABLISHED) || ((pcb->state == ESTABLISHED) ||
(pcb->state == CLOSE_WAIT))) { (pcb->state == CLOSE_WAIT))) {
#if LWIP_TCP_KEEPALIVE #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)) (pcb->keep_idle + (pcb->keep_cnt*pcb->keep_intvl))
/ TCP_SLOW_INTERVAL) / TCP_SLOW_INTERVAL)
#else #else
if((u32_t)(tcp_ticks - pcb->tmr) > if((u32_t)(tcp_ticks - pcb->tmr) >
(pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) (pcb->keep_idle + TCP_MAXIDLE) / TCP_SLOW_INTERVAL)
#endif /* LWIP_TCP_KEEPALIVE */ #endif /* LWIP_TCP_KEEPALIVE */
{ {
@ -708,7 +709,7 @@ tcp_slowtmr(void)
/* If this PCB has queued out of sequence data, but has been /* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually inactive for too long, will drop the data (it will eventually
be retransmitted). */ be retransmitted). */
#if TCP_QUEUE_OOSEQ #if TCP_QUEUE_OOSEQ
if (pcb->ooseq != NULL && if (pcb->ooseq != NULL &&
(u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) {
tcp_segs_free(pcb->ooseq); tcp_segs_free(pcb->ooseq);
@ -736,7 +737,7 @@ tcp_slowtmr(void)
/* If the PCB should be removed, do it. */ /* If the PCB should be removed, do it. */
if (pcb_remove) { if (pcb_remove) {
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */ /* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) { if (prev != NULL) {
LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); 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 the PCB should be removed, do it. */
if (pcb_remove) { if (pcb_remove) {
tcp_pcb_purge(pcb); tcp_pcb_purge(pcb);
/* Remove PCB from tcp_tw_pcbs list. */ /* Remove PCB from tcp_tw_pcbs list. */
if (prev != NULL) { if (prev != NULL) {
LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);