Implement SO_RCVTIMEO on UDP sockets/netconn.
This commit is contained in:
@@ -73,18 +73,21 @@ static sys_sem_t selectsem = 0;
|
||||
static void
|
||||
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
|
||||
|
||||
static int err_to_errno_table[11] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
ECONNABORTED, /* ERR_ABRT -3 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -4 Connection reset. */
|
||||
ESHUTDOWN, /* ERR_CLSD -5 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -6 Not connected. */
|
||||
EINVAL, /* ERR_VAL -7 Illegal value. */
|
||||
EIO, /* ERR_ARG -8 Illegal argument. */
|
||||
EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */
|
||||
EADDRINUSE /* ERR_USE -10 Address in use. */
|
||||
static int err_to_errno_table[] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
ECONNABORTED, /* ERR_ABRT -3 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -4 Connection reset. */
|
||||
ESHUTDOWN, /* ERR_CLSD -5 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -6 Not connected. */
|
||||
EINVAL, /* ERR_VAL -7 Illegal value. */
|
||||
EIO, /* ERR_ARG -8 Illegal argument. */
|
||||
EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */
|
||||
EADDRINUSE, /* ERR_USE -10 Address in use. */
|
||||
-1, /* ERR_IF -11 Low-level netif error */
|
||||
-1, /* ERR_ISCONN -12 Already connected. */
|
||||
ETIMEDOUT /* ERR_TIMEOUT -13 Timeout */
|
||||
};
|
||||
|
||||
#define ERR_TO_ERRNO_TABLE_SIZE \
|
||||
@@ -146,13 +149,13 @@ alloc_socket(struct netconn *newconn)
|
||||
/* allocate a new socket identifier */
|
||||
for(i = 0; i < NUM_SOCKETS; ++i) {
|
||||
if (!sockets[i].conn) {
|
||||
sockets[i].conn = newconn;
|
||||
sockets[i].lastdata = NULL;
|
||||
sockets[i].conn = newconn;
|
||||
sockets[i].lastdata = NULL;
|
||||
sockets[i].lastoffset = 0;
|
||||
sockets[i].rcvevent = 0;
|
||||
sockets[i].sendevent = 1; /* TCP send buf is empty */
|
||||
sockets[i].flags = 0;
|
||||
sockets[i].err = 0;
|
||||
sockets[i].rcvevent = 0;
|
||||
sockets[i].sendevent = 1; /* TCP send buf is empty */
|
||||
sockets[i].flags = 0;
|
||||
sockets[i].err = 0;
|
||||
sys_sem_signal(socksem);
|
||||
return i;
|
||||
}
|
||||
@@ -349,10 +352,10 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen)
|
||||
{
|
||||
struct lwip_socket *sock;
|
||||
struct netbuf *buf;
|
||||
u16_t buflen, copylen;
|
||||
struct ip_addr *addr;
|
||||
u16_t port;
|
||||
struct netbuf *buf;
|
||||
u16_t buflen, copylen;
|
||||
struct ip_addr *addr;
|
||||
u16_t port;
|
||||
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
|
||||
@@ -364,44 +367,43 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
|
||||
/* Check if there is data left from the last recv operation. */
|
||||
if (sock->lastdata) {
|
||||
buf = sock->lastdata;
|
||||
} else {
|
||||
/* If this is non-blocking call, then check first */
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK))
|
||||
&& !sock->rcvevent)
|
||||
{
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No data was left from the previous operation, so we try to get
|
||||
some from the network. */
|
||||
buf = netconn_recv(sock->conn);
|
||||
|
||||
if (!buf) {
|
||||
/* We should really do some error checking here. */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
|
||||
sock_set_errno(sock, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
buf = sock->lastdata;
|
||||
} else {
|
||||
/* If this is non-blocking call, then check first */
|
||||
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent)
|
||||
{
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
|
||||
sock_set_errno(sock, EWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No data was left from the previous operation, so we try to get
|
||||
some from the network. */
|
||||
buf = netconn_recv(sock->conn);
|
||||
|
||||
if (!buf) {
|
||||
/* We should really do some error checking here. */
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
|
||||
sock_set_errno(sock, (sock->conn->type==NETCONN_UDP)?ETIMEDOUT:0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
buflen = netbuf_len(buf);
|
||||
|
||||
buflen -= sock->lastoffset;
|
||||
|
||||
|
||||
if (len > buflen) {
|
||||
copylen = buflen;
|
||||
} else {
|
||||
copylen = len;
|
||||
}
|
||||
|
||||
copylen = buflen;
|
||||
} else {
|
||||
copylen = len;
|
||||
}
|
||||
|
||||
/* copy the contents of the received buffer into
|
||||
the supplied memory pointer mem */
|
||||
the supplied memory pointer mem */
|
||||
netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
|
||||
|
||||
/* Check to see from where the data was. */
|
||||
/* Check to see from where the data was.*/
|
||||
if (from && fromlen) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
@@ -527,7 +529,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
|
||||
struct lwip_socket *sock;
|
||||
struct ip_addr remote_addr, addr;
|
||||
u16_t remote_port, port;
|
||||
int ret,connected;
|
||||
int err,connected;
|
||||
|
||||
sock = get_socket(s);
|
||||
if (!sock) {
|
||||
@@ -547,7 +549,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
|
||||
|
||||
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
|
||||
|
||||
ret = lwip_send(s, data, size, flags);
|
||||
err = lwip_send(s, data, size, flags);
|
||||
|
||||
/* reset the remote address and port number
|
||||
of the connection */
|
||||
@@ -555,7 +557,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
|
||||
netconn_connect(sock->conn, &addr, port);
|
||||
else
|
||||
netconn_disconnect(sock->conn);
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -632,7 +634,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
if (p_sock && (p_sock->lastdata || p_sock->rcvevent))
|
||||
{
|
||||
FD_SET(i, &lreadset);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
|
||||
nready++;
|
||||
}
|
||||
}
|
||||
@@ -643,7 +645,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
|
||||
if (p_sock && p_sock->sendevent)
|
||||
{
|
||||
FD_SET(i, &lwriteset);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
|
||||
nready++;
|
||||
}
|
||||
}
|
||||
@@ -709,8 +711,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
if (exceptset)
|
||||
FD_ZERO(exceptset);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
|
||||
set_errno(0);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
|
||||
set_errno(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -765,8 +767,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
if (exceptset)
|
||||
FD_ZERO(exceptset);
|
||||
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
|
||||
set_errno(0);
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
|
||||
set_errno(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -972,7 +974,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -994,6 +996,8 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
/* UNIMPL case SO_DONTROUTE: */
|
||||
case SO_ERROR:
|
||||
case SO_KEEPALIVE:
|
||||
/* UNIMPL case SO_SNDTIMEO: */
|
||||
case SO_RCVTIMEO:
|
||||
/* UNIMPL case SO_OOBINLINE: */
|
||||
/* UNIMPL case SO_RCVBUF: */
|
||||
/* UNIMPL case SO_SNDBUF: */
|
||||
@@ -1119,6 +1123,10 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
|
||||
sock->err = 0;
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
|
||||
break;
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
*(int *)optval = sock->conn->recv_timeout;
|
||||
break;
|
||||
} /* switch */
|
||||
break;
|
||||
|
||||
@@ -1162,7 +1170,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
int err = 0;
|
||||
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1183,6 +1191,8 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
/* UNIMPL case SO_DEBUG: */
|
||||
/* UNIMPL case SO_DONTROUTE: */
|
||||
case SO_KEEPALIVE:
|
||||
/* UNIMPL case case SO_SNDTIMEO: */
|
||||
case SO_RCVTIMEO:
|
||||
/* UNIMPL case SO_OOBINLINE: */
|
||||
/* UNIMPL case SO_RCVBUF: */
|
||||
/* UNIMPL case SO_SNDBUF: */
|
||||
@@ -1282,6 +1292,9 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
|
||||
}
|
||||
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
|
||||
break;
|
||||
case SO_RCVTIMEO:
|
||||
sock->conn->recv_timeout = ( *(int*)optval );
|
||||
break;
|
||||
} /* switch */
|
||||
break;
|
||||
|
||||
@@ -1327,7 +1340,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
|
||||
struct lwip_socket *sock = get_socket(s);
|
||||
|
||||
if(!sock) {
|
||||
set_errno(EBADF);
|
||||
set_errno(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user