Implemented timeout on send (TCP only, bug #33820)

This commit is contained in:
Simon Goldschmidt 2011-09-21 19:36:09 +02:00
parent 8d5514603e
commit a2aa43a426
7 changed files with 135 additions and 62 deletions

View File

@ -6,6 +6,10 @@ HISTORY
++ New features: ++ New features:
2011-09-21: Simon Goldschmidt
* opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on
send (TCP only, bug #33820)
2011-09-21: Simon Goldschmidt 2011-09-21: Simon Goldschmidt
* init.c: Converted runtime-sanity-checks into compile-time checks that can * init.c: Converted runtime-sanity-checks into compile-time checks that can
be disabled (since runtime checks can often not be seen on embedded targets) be disabled (since runtime checks can often not be seen on embedded targets)

View File

@ -611,12 +611,26 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
msg.msg.msg.w.dataptr = dataptr; msg.msg.msg.w.dataptr = dataptr;
msg.msg.msg.w.apiflags = apiflags; msg.msg.msg.w.apiflags = apiflags;
msg.msg.msg.w.len = size; msg.msg.msg.w.len = size;
#if LWIP_SO_SNDTIMEO
if (conn->send_timeout != 0) {
/* get the time we started, which is later compared to
sys_now() + conn->send_timeout */
msg.msg.msg.w.time_started = sys_now();
} else {
msg.msg.msg.w.time_started = 0;
}
#endif /* LWIP_SO_SNDTIMEO */
/* For locking the core: this _can_ be delayed on low memory/low send buffer, /* For locking the core: this _can_ be delayed on low memory/low send buffer,
but if it is, this is done inside api_msg.c:do_write(), so we can use the but if it is, this is done inside api_msg.c:do_write(), so we can use the
non-blocking version here. */ non-blocking version here. */
err = TCPIP_APIMSG(&msg); err = TCPIP_APIMSG(&msg);
if ((err == ERR_OK) && (bytes_written != NULL)) { if ((err == ERR_OK) && (bytes_written != NULL)) {
if (dontblock) { if (dontblock
#if LWIP_SO_SNDTIMEO
|| (conn->send_timeout != 0)
#endif /* LWIP_SO_SNDTIMEO */
) {
/* nonblocking write: maybe the data has been sent partly */ /* nonblocking write: maybe the data has been sent partly */
*bytes_written = msg.msg.msg.w.len; *bytes_written = msg.msg.msg.w.len;
} else { } else {

View File

@ -626,6 +626,9 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
conn->current_msg = NULL; conn->current_msg = NULL;
conn->write_offset = 0; conn->write_offset = 0;
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
#if LWIP_SO_SNDTIMEO
conn->send_timeout = 0;
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
conn->recv_timeout = 0; conn->recv_timeout = 0;
#endif /* LWIP_SO_RCVTIMEO */ #endif /* LWIP_SO_RCVTIMEO */
@ -1217,6 +1220,22 @@ do_writemore(struct netconn *conn)
LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
conn->write_offset < conn->current_msg->msg.w.len); conn->write_offset < conn->current_msg->msg.w.len);
#if LWIP_SO_SNDTIMEO
if ((conn->send_timeout != 0) &&
((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) {
write_finished = 1;
if (conn->write_offset == 0) {
/* nothing has been written */
err = ERR_WOULDBLOCK;
conn->current_msg->msg.w.len = 0;
} else {
/* partial write */
err = ERR_OK;
conn->current_msg->msg.w.len = conn->write_offset;
}
} else
#endif /* LWIP_SO_SNDTIMEO */
{
dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; dataptr = (u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
diff = conn->current_msg->msg.w.len - conn->write_offset; diff = conn->current_msg->msg.w.len - conn->write_offset;
if (diff > 0xffffUL) { /* max_u16_t */ if (diff > 0xffffUL) { /* max_u16_t */
@ -1289,7 +1308,7 @@ err_mem:
write_finished = 1; write_finished = 1;
conn->current_msg->msg.w.len = 0; conn->current_msg->msg.w.len = 0;
} }
}
if (write_finished) { if (write_finished) {
/* everything was written: set back connection state /* everything was written: set back connection state
and back to application task */ and back to application task */

View File

@ -1535,7 +1535,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
case SO_ERROR: case SO_ERROR:
case SO_KEEPALIVE: case SO_KEEPALIVE:
/* UNIMPL case SO_CONTIMEO: */ /* UNIMPL case SO_CONTIMEO: */
/* UNIMPL case SO_SNDTIMEO: */ #if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */ #endif /* LWIP_SO_RCVTIMEO */
@ -1780,6 +1782,11 @@ lwip_getsockopt_internal(void *arg)
s, *(int *)optval)); s, *(int *)optval));
break; break;
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
*(int *)optval = netconn_get_sendtimeout(sock->conn);
break;
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
*(int *)optval = netconn_get_recvtimeout(sock->conn); *(int *)optval = netconn_get_recvtimeout(sock->conn);
@ -1934,7 +1941,9 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
/* UNIMPL case SO_DONTROUTE: */ /* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE: case SO_KEEPALIVE:
/* UNIMPL case case SO_CONTIMEO: */ /* UNIMPL case case SO_CONTIMEO: */
/* UNIMPL case case SO_SNDTIMEO: */ #if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */ #endif /* LWIP_SO_RCVTIMEO */
@ -2160,6 +2169,11 @@ lwip_setsockopt_internal(void *arg)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
s, optname, (*(int*)optval?"on":"off"))); s, optname, (*(int*)optval?"on":"off")));
break; break;
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval);
break;
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
netconn_set_recvtimeout(sock->conn, *(int*)optval); netconn_set_recvtimeout(sock->conn, *(int*)optval);

View File

@ -180,6 +180,11 @@ struct netconn {
#if LWIP_SOCKET #if LWIP_SOCKET
int socket; int socket;
#endif /* LWIP_SOCKET */ #endif /* LWIP_SOCKET */
#if LWIP_SO_SNDTIMEO
/** timeout to wait for sending data (which means enqueueing data for sending
in internal buffers) */
s32_t send_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
/** timeout to wait for new data to be received /** timeout to wait for new data to be received
(or connections to arrive for listening netconns) */ (or connections to arrive for listening netconns) */
@ -299,6 +304,12 @@ err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ /** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) #define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0)
#if LWIP_SO_SNDTIMEO
/** Set the send timeout in milliseconds */
#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout))
/** Get the send timeout in milliseconds */
#define netconn_get_sendtimeout(conn) ((conn)->send_timeout)
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
/** Set the receive timeout in milliseconds */ /** Set the receive timeout in milliseconds */
#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) #define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))

View File

@ -89,6 +89,9 @@ struct api_msg_msg {
const void *dataptr; const void *dataptr;
size_t len; size_t len;
u8_t apiflags; u8_t apiflags;
#if LWIP_SO_SNDTIMEO
u32_t time_started;
#endif /* LWIP_SO_SNDTIMEO */
} w; } w;
/** used for do_recv */ /** used for do_recv */
struct { struct {

View File

@ -1434,6 +1434,14 @@
#define LWIP_TCP_KEEPALIVE 0 #define LWIP_TCP_KEEPALIVE 0
#endif #endif
/**
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
* SO_SNDTIMEO processing.
*/
#ifndef LWIP_SO_SNDTIMEO
#define LWIP_SO_SNDTIMEO 0
#endif
/** /**
* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
* SO_RCVTIMEO processing. * SO_RCVTIMEO processing.