net: tcp: add timeout wait in net_context_connect

If the parameter "timeout" is set in net_context_connect(), the
assumption by the user is that the function would wait for SYNACK
to be received before returning to the caller.

Currently this is not the case.  The timeout parameter is handed
off to net_l2_offload_ip_connect() if CONFIG_NET_L2_OFFLOAD_IP is
defined but never handled in a normal call.

To implement the timeout, let's use a semaphore to wait for
tcp_synack_received() to get a SYNACK before returning from
net_context_connect().

Change-Id: I7565550ed5545e6410b2d99c429367c1fb539970
Signed-off-by: Michael Scott <michael.scott@linaro.org>
This commit is contained in:
Michael Scott 2017-01-17 21:49:33 -08:00 committed by Jukka Rissanen
commit 72e013a7ba
4 changed files with 18 additions and 1 deletions

View file

@ -477,6 +477,7 @@ typedef void (*net_context_connect_cb_t)(struct net_context *context,
* @return 0 on success.
* @return -EINVAL if an invalid parameter is passed as an argument.
* @return -ENOTSUP if the operation is not supported or implemented.
* @return -ETIMEDOUT if the connect operation times out.
*/
int net_context_connect(struct net_context *context,
const struct sockaddr *addr,

View file

@ -928,6 +928,8 @@ static enum net_verdict tcp_synack_received(struct net_conn *conn,
net_context_set_state(context, NET_CONTEXT_CONNECTED);
send_ack(context, raddr);
k_sem_give(&context->tcp->connect_wait);
}
return NET_DROP;
@ -950,6 +952,9 @@ int net_context_connect(struct net_context *context,
NET_ASSERT(addr);
NET_ASSERT(PART_OF_ARRAY(contexts, context));
#if defined(CONFIG_NET_TCP)
NET_ASSERT(context->tcp);
#endif
if (!net_context_is_used(context)) {
return -ENOENT;
@ -1104,12 +1109,16 @@ int net_context_connect(struct net_context *context,
net_context_set_state(context, NET_CONTEXT_CONNECTING);
/* FIXME - set timer to wait for SYN-ACK */
send_syn(context, addr);
if (cb) {
cb(context, user_data);
}
/* in tcp_synack_received() we give back this semaphore */
if (k_sem_take(&context->tcp->connect_wait, timeout)) {
return -ETIMEDOUT;
}
#endif
return 0;

View file

@ -152,6 +152,7 @@ struct net_tcp *net_tcp_alloc(struct net_context *context)
tcp_context[i].accept_cb = NULL;
k_timer_init(&tcp_context[i].retry_timer, tcp_retry_expired, NULL);
k_sem_init(&tcp_context[i].connect_wait, 0, UINT_MAX);
return &tcp_context[i];
}
@ -167,6 +168,7 @@ int net_tcp_release(struct net_tcp *tcp)
k_delayed_work_cancel(&tcp->fin_timer);
k_delayed_work_cancel(&tcp->ack_timer);
k_timer_stop(&tcp->retry_timer);
k_sem_reset(&tcp->connect_wait);
net_tcp_set_state(tcp, NET_TCP_CLOSED);
tcp->context = NULL;

View file

@ -138,6 +138,11 @@ struct net_tcp {
* established.
*/
net_tcp_accept_cb_t accept_cb;
/**
* Semaphore to signal TCP connection completion
*/
struct k_sem connect_wait;
};
static inline bool net_tcp_is_used(struct net_tcp *tcp)