Correct and error in recv() and recvfrom() return value

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4402 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2012-02-18 18:13:30 +00:00
parent f60d578a46
commit f04310d559
24 changed files with 189 additions and 128 deletions

View File

@ -188,7 +188,15 @@ int ftpd_daemon(int s_argc, char **s_argv)
*/ */
ret = ftpd_session(handle, 5000); ret = ftpd_session(handle, 5000);
printf("FTP daemon [%d] ftpd_session returned %d\n", g_ftpdglob.pid, ret);
/* If any interesting happened (i.e., any thing other than a timeout),
* then report the interesting event.
*/
if (ret != -ETIMEDOUT)
{
printf("FTP daemon [%d] ftpd_session returned %d\n", g_ftpdglob.pid, ret);
}
} }
/* Close the FTPD server and exit (we can get here only if /* Close the FTPD server and exit (we can get here only if

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* examples/nettest/nettest-client.c * examples/nettest/nettest-client.c
* *
* Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -169,6 +169,11 @@ void send_client(void)
message("client: recv failed: %d\n", errno); message("client: recv failed: %d\n", errno);
goto errout_with_socket; goto errout_with_socket;
} }
else if (nbytesrecvd == 0)
{
message("client: The server closed the connection\n");
goto errout_with_socket;
}
totalbytesrecvd += nbytesrecvd; totalbytesrecvd += nbytesrecvd;
message("client: Received %d of %d bytes\n", totalbytesrecvd, SENDSIZE); message("client: Received %d of %d bytes\n", totalbytesrecvd, SENDSIZE);
} }

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* examples/nettest/nettest-server.c * examples/nettest/nettest-server.c
* *
* Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -149,11 +149,16 @@ void recv_server(void)
for (;;) for (;;)
{ {
nbytesread = recv(acceptsd, buffer, 2*SENDSIZE, 0); nbytesread = recv(acceptsd, buffer, 2*SENDSIZE, 0);
if (nbytesread <= 0) if (nbytesread < 0)
{ {
message("server: recv failed: %d\n", errno); message("server: recv failed: %d\n", errno);
goto errout_with_acceptsd; goto errout_with_acceptsd;
} }
else if (nbytesread == 0)
{
message("server: The client broke the connection\n");
goto errout_with_acceptsd;
}
message("Received %d bytes\n", nbytesread); message("Received %d bytes\n", nbytesread);
} }
#else #else
@ -164,11 +169,16 @@ void recv_server(void)
{ {
message("server: Reading...\n"); message("server: Reading...\n");
nbytesread = recv(acceptsd, &buffer[totalbytesread], 2*SENDSIZE - totalbytesread, 0); nbytesread = recv(acceptsd, &buffer[totalbytesread], 2*SENDSIZE - totalbytesread, 0);
if (nbytesread <= 0) if (nbytesread < 0)
{ {
message("server: recv failed: %d\n", errno); message("server: recv failed: %d\n", errno);
goto errout_with_acceptsd; goto errout_with_acceptsd;
} }
else if (nbytesread == 0)
{
message("server: The client broke the connection\n");
goto errout_with_acceptsd;
}
totalbytesread += nbytesread; totalbytesread += nbytesread;
message("server: Received %d of %d bytes\n", totalbytesread, SENDSIZE); message("server: Received %d of %d bytes\n", totalbytesread, SENDSIZE);

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* examples/poll/host.c * examples/poll/host.c
* *
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. * Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -137,6 +137,11 @@ int main(int argc, char **argv, char **envp)
message("client: recv failed: %d\n", errno); message("client: recv failed: %d\n", errno);
goto errout_with_socket; goto errout_with_socket;
} }
else if (nbytesrecvd == 0)
{
message("client: The server broke the connections\n");
goto errout_with_socket;
}
inbuf[nbytesrecvd] = '\0'; inbuf[nbytesrecvd] = '\0';
message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd); message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd);

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* examples/poll/net_listener.c * examples/poll/net_listener.c
* *
* Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* examples/poll/net_reader.c * examples/poll/net_reader.c
* *
* Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* examples/udp/udp-server.c * examples/udp/udp-server.c
* *
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* netutils/dhcpc/dhcpc.c * netutils/dhcpc/dhcpc.c
* *
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Based heavily on portions of uIP: * Based heavily on portions of uIP:
* *

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* netutils/dhcpd/dhcpd.c * netutils/dhcpd/dhcpd.c
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View File

@ -796,7 +796,7 @@ static int ftpd_rxpoll(int sd, int timeout)
if (ret == 0) if (ret == 0)
{ {
nvdbg("poll() timed out\n"); //nvdbg("poll() timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
else if (ret < 0) else if (ret < 0)
@ -870,7 +870,14 @@ static int ftpd_accept(int sd, FAR void *addr, FAR socklen_t *addrlen,
ret = ftpd_rxpoll(sd, timeout); ret = ftpd_rxpoll(sd, timeout);
if (ret < 0) if (ret < 0)
{ {
nvdbg("ftpd_rxpoll() failed: %d\n", ret); /* Only report interesting, infrequent errors (not the common timeout) */
#ifdef CONFIG_DEBUG_NET
if (ret != -ETIMEDOUT)
{
ndbg("ftpd_rxpoll() failed: %d\n", ret);
}
#endif
return ret; return ret;
} }
} }
@ -909,34 +916,18 @@ static ssize_t ftpd_recv(int sd, FAR void *data, size_t size, int timeout)
} }
} }
/* Receive the data... waiting if necessary */ /* Receive the data... waiting if necessary. The client side will break the
* connection after the file has been sent. Zero (end-of-file) should be
* received in this case.
*/
ret = recv(sd, data, size, 0); ret = recv(sd, data, size, 0);
if (ret < 0) if (ret < 0)
{ {
int errval = errno; int errval = errno;
/* Special case some TCP read errors. The client side will break the ndbg("recv() failed: %d\n", errval);
* connection after the file has been sent. return -errval;
*/
#warning FIXME
/* When the client breaks the connection, the NuttX socket layer will
* return an error with errno == ENOTCONN. This is wrong! It should
* return 0 (end-of-file) in that case! We work around the bug and
* report end-of-file for that case here. This needs to be fixed
* someday.
*/
if (errval == ENOTCONN)
{
nvdbg("Connection lost, returning end-of-file\n");
ret = 0;
}
else
{
ndbg("recv() failed: %d\n", errval);
return -errval;
}
} }
return ret; return ret;
@ -4342,7 +4333,14 @@ int ftpd_session(FTPD_SESSION handle, int timeout)
&session->cmd.addrlen, timeout); &session->cmd.addrlen, timeout);
if (session->cmd.sd < 0) if (session->cmd.sd < 0)
{ {
ndbg("ftpd_accept() failed: %d\n", session->cmd.sd); /* Only report interesting, infrequent errors (not the common timeout) */
#ifdef CONFIG_DEBUG_NET
if (session->cmd.sd != -ETIMEDOUT)
{
ndbg("ftpd_accept() failed: %d\n", session->cmd.sd);
}
#endif
ret = session->cmd.sd; ret = session->cmd.sd;
goto errout_with_session; goto errout_with_session;
} }

View File

@ -12,8 +12,8 @@
* the resolver code calls a callback function called resolv_found() * the resolver code calls a callback function called resolv_found()
* that must be implemented by the module that uses the resolver. * that must be implemented by the module that uses the resolver.
* *
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Based heavily on portions of uIP: * Based heavily on portions of uIP:
* *

View File

@ -234,7 +234,7 @@ int tftpget(const char *remote, const char *local, in_addr_t addr, bool binary)
/* Check if anything valid was received */ /* Check if anything valid was received */
if (nbytesrecvd >= 0) if (nbytesrecvd > 0)
{ {
/* Verify the sender address and port number */ /* Verify the sender address and port number */

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* netuils/tftp/tftpc_packets.c * netuils/tftp/tftpc_packets.c
* *
* Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions

View File

@ -217,9 +217,17 @@ static int tftp_rcvack(int sd, uint8_t *packet, struct sockaddr_in *server,
{ {
/* Failed to receive a good packet */ /* Failed to receive a good packet */
if (nbytes >= 0) if (nbytes == 0)
{ {
ndbg("tftp_recvfrom short packet: %d bytes\n", nbytes); ndbg("Connection lost: %d bytes\n", nbytes);
}
else if (nbytes > 0)
{
ndbg("Short packet: %d bytes\n", nbytes);
}
else
{
ndbg("Recveid failure\n");
} }
/* Break out to bump up the retry count */ /* Break out to bump up the retry count */

View File

@ -2,8 +2,8 @@
* netutils/webclient/webclient.c * netutils/webclient/webclient.c
* Implementation of the HTTP client. * Implementation of the HTTP client.
* *
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Based on uIP which also has a BSD style license: * Based on uIP which also has a BSD style license:
* *
@ -526,6 +526,7 @@ int wget(FAR const char *url, FAR char *buffer, int buflen,
} }
else if (ret == 0) else if (ret == 0)
{ {
nvdbg("Connection lost\n");
close(sockfd); close(sockfd);
break; break;
} }

View File

@ -2,8 +2,8 @@
* netutils/webserver/httpd.c * netutils/webserver/httpd.c
* httpd Web server * httpd Web server
* *
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* This is a leverage of similar logic from uIP: * This is a leverage of similar logic from uIP:
* *
@ -380,6 +380,11 @@ static inline int httpd_cmd(struct httpd_state *pstate)
ndbg("[%d] recv failed: %d\n", pstate->ht_sockfd, errno); ndbg("[%d] recv failed: %d\n", pstate->ht_sockfd, errno);
return ERROR; return ERROR;
} }
lese if (recvlen == 0)
{
ndbg("[%d] connection lost\n", pstate->ht_sockfd);
return ERROR;
}
httpd_dumpbuffer("Incoming buffer", pstate->ht_buffer, recvlen); httpd_dumpbuffer("Incoming buffer", pstate->ht_buffer, recvlen);
/* We will handle only GET */ /* We will handle only GET */

View File

@ -2467,3 +2467,5 @@
a lower-half quadrature encoder driver for the STM32. On initial check-in, a lower-half quadrature encoder driver for the STM32. On initial check-in,
this is little more than a "skeleton" file. this is little more than a "skeleton" file.
* Various files: CAN ISO-11783 support contributed by Gary Teravskis. * Various files: CAN ISO-11783 support contributed by Gary Teravskis.
* net/recv.c and net/recvfrom.c: Correct a bug in return value: The the peer
gracefully closes the connections, needs to return zero and not ENOTCONN

View File

@ -13,7 +13,7 @@
<h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1> <h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1>
<p><small>by</small></p> <p><small>by</small></p>
<p>Gregory Nutt<p> <p>Gregory Nutt<p>
<p>Last Updated: December 5, 2011</p> <p>Last Updated: February 18, 2011</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -7391,8 +7391,7 @@ Those socket APIs are discussed in the following paragraphs.</p>
</ul> </ul>
<p> <p>
<b>Returned Values:</b> <b>Returned Values:</b>
see <a href="#recvfrom"><code>recvfrom()</code></a>. See <a href="#recvfrom"><code>recvfrom()</code></a>.
Zero on success.
</p> </p>
<h3><a name="recvfrom">2.12.9 <code>recvfrom</code></a></h3> <h3><a name="recvfrom">2.12.9 <code>recvfrom</code></a></h3>
@ -7429,7 +7428,8 @@ Those socket APIs are discussed in the following paragraphs.</p>
<p> <p>
<b>Returned Values:</b> <b>Returned Values:</b>
On success, returns the number of characters sent. On success, returns the number of characters sent.
On error, -1 is returned, and <a href="#ErrnoAccess"><code>errno</code></a> is set appropriately: If no data is available to be received and the peer has performed an orderly shutdown, recv() will return 0.
Othwerwise, on errors, -1 is returned, and <a href="#ErrnoAccess"><code>errno</code></a> is set appropriately:
</p> </p>
<ul> <ul>
<li><code>EAGAIN</code>. <li><code>EAGAIN</code>.

View File

@ -13,7 +13,7 @@ nuttx/
(1) pthreads (sched/) (1) pthreads (sched/)
(2) C++ Support (2) C++ Support
(5) Binary loaders (binfmt/) (5) Binary loaders (binfmt/)
(18) Network (net/, drivers/net) (17) Network (net/, drivers/net)
(2) USB (drivers/usbdev, drivers/usbhost) (2) USB (drivers/usbdev, drivers/usbhost)
(8) Libraries (lib/) (8) Libraries (lib/)
(10) File system/Generic drivers (fs/, drivers/) (10) File system/Generic drivers (fs/, drivers/)
@ -437,20 +437,8 @@ o Network (net/, drivers/net)
Status: Open Status: Open
Priority: Low unless you need it. Priority: Low unless you need it.
Title: RECV/RECVFROM RETURN VALUE
Description: If the peer performs an orderly shutdown, then recvfrom currently returns
an error with errno set to ENOTCONN. This is wrong. There is a fine
distinction. The ENOTCONN errno is intended for the case where the socket
was never connected. In the case were the socket was connected then the
peer performs an order shutdown: "...If no messages are available to be
received and the peer has performed an orderly shutdown, recv() shall
return 0. ..."
Status: Open and there is a kludge in apps/netutils/ftpd/ftpdc.c work around this
bad return value.
Priority: Medium
o USB (drivers/usbdev, drivers/usbhost) o USB (drivers/usbdev, drivers/usbhost)
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Title: USB STORAGE DRIVER DELAYS Title: USB STORAGE DRIVER DELAYS
Description: There is a workaround for a bug in drivers/usbdev/usbdev_storage.c. Description: There is a workaround for a bug in drivers/usbdev/usbdev_storage.c.

View File

@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* net/accept.c * net/accept.c
* *
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -441,6 +441,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
pnewsock->s_type = SOCK_STREAM; pnewsock->s_type = SOCK_STREAM;
pnewsock->s_conn = state.acpt_newconn; pnewsock->s_conn = state.acpt_newconn;
pnewsock->s_flags |= _SF_CONNECTED; pnewsock->s_flags |= _SF_CONNECTED;
pnewsock->s_flags &= ~_SF_CLOSED;
return newfd; return newfd;
errout_with_lock: errout_with_lock:

View File

@ -116,15 +116,37 @@ static void connection_event(struct uip_conn *conn, uint16_t flags)
{ {
nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags); nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
/* UIP_CLOSE: The remote host has closed the connection /* These loss-of-connection events may be reported:
* UIP_ABORT: The remote host has aborted the connection *
* UIP_TIMEDOUT: Connection aborted due to too many retransmissions. * UIP_CLOSE: The remote host has closed the connection
* UIP_ABORT: The remote host has aborted the connection
* UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
*
* And we need to set these two socket status bits appropriately:
*
* _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
* _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
* _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
*/ */
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
if ((flags & UIP_CLOSE) != 0)
{ {
/* Indicate that the socket is no longer connected */ /* The peer gracefully closed the connection. Marking the
* connection as disconnected will suppress some subsequent
* ENOTCONN errors from receive. A graceful disconnection is
* not handle as an error but as an "end-of-file"
*/
psock->s_flags &= ~_SF_CONNECTED; psock->s_flags &= ~_SF_CONNECTED;
psock->s_flags |= _SF_CLOSED;
}
else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
/* The loss of connection was less than graceful. This will (eventually)
* be reported as an ENOTCONN error.
*/
psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
} }
/* UIP_CONNECTED: The socket is successfully connected */ /* UIP_CONNECTED: The socket is successfully connected */
@ -134,6 +156,7 @@ static void connection_event(struct uip_conn *conn, uint16_t flags)
/* Indicate that the socket is now connected */ /* Indicate that the socket is now connected */
psock->s_flags |= _SF_CONNECTED; psock->s_flags |= _SF_CONNECTED;
psock->s_flags &= ~_SF_CLOSED;
} }
} }
} }

View File

@ -57,16 +57,25 @@
/* Definitions of 8-bit socket flags */ /* Definitions of 8-bit socket flags */
/* Bits 0-2: Socket state */ /* Bits 0-2: Socket state */
#define _SF_IDLE 0x00 /* There is no socket activity */ #define _SF_IDLE 0x00 /* - There is no socket activity */
#define _SF_ACCEPT 0x01 /* Socket is waiting to accept a connection */ #define _SF_ACCEPT 0x01 /* - Socket is waiting to accept a connection */
#define _SF_RECV 0x02 /* Waiting for recv action to complete */ #define _SF_RECV 0x02 /* - Waiting for recv action to complete */
#define _SF_SEND 0x03 /* Waiting for send action to complete */ #define _SF_SEND 0x03 /* - Waiting for send action to complete */
#define _SF_MASK 0x03 /* Mask to isolate the above actions */ #define _SF_MASK 0x03 /* - Mask to isolate the above actions */
/* Bit 3: unused */
#define _SF_NONBLOCK 0x10 /* Bit 4: Don't block if no data (TCP/READ only) */ #define _SF_NONBLOCK 0x08 /* Bit 3: Don't block if no data (TCP/READ only) */
#define _SF_LISTENING 0x20 /* Bit 5: SOCK_STREAM is listening */ #define _SF_LISTENING 0x10 /* Bit 4: SOCK_STREAM is listening */
#define _SF_BOUND 0x40 /* Bit 6: SOCK_STREAM is bound to an address */ #define _SF_BOUND 0x20 /* Bit 5: SOCK_STREAM is bound to an address */
#define _SF_CONNECTED 0x80 /* Bit 7: SOCK_STREAM is connected */ /* Bits 6-7: Connection state */
#define _SF_CONNECTED 0x40 /* Bit 6: SOCK_STREAM is connected */
#define _SF_CLOSED 0x80 /* Bit 7: SOCK_STREAM was gracefully disconnected */
/* Connection state encoding:
*
* _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
* _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
* _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
*/
/* Macro to manage the socket state and flags */ /* Macro to manage the socket state and flags */
@ -78,6 +87,7 @@
#define _SS_ISLISTENING(s) (((s) & _SF_LISTENING) != 0) #define _SS_ISLISTENING(s) (((s) & _SF_LISTENING) != 0)
#define _SS_ISBOUND(s) (((s) & _SF_CONNECTED) != 0) #define _SS_ISBOUND(s) (((s) & _SF_CONNECTED) != 0)
#define _SS_ISCONNECTED(s) (((s) & _SF_CONNECTED) != 0) #define _SS_ISCONNECTED(s) (((s) & _SF_CONNECTED) != 0)
#define _SS_ISCLOSED(s) (((s) & _SF_CLOSED) != 0)
/* This macro converts a socket option value into a bit setting */ /* This macro converts a socket option value into a bit setting */

View File

@ -419,7 +419,12 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
#endif #endif
} }
/* Check for a loss of connection */ /* Check for a loss of connection.
*
* UIP_CLOSE: The remote host has closed the connection
* UIP_ABORT: The remote host has aborted the connection
* UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
*/
else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{ {
@ -431,9 +436,18 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
pstate->rf_cb->priv = NULL; pstate->rf_cb->priv = NULL;
pstate->rf_cb->event = NULL; pstate->rf_cb->event = NULL;
/* Report not connected */ /* If the peer gracefully closed the connection, then return zero
* (end-of-file). Otherwise, report a not-connected error
*/
pstate->rf_result = -ENOTCONN; if ((flags & UIP_CLOSE) != 0)
{
pstate->rf_result = 0;
}
else
{
pstate->rf_result = -ENOTCONN;
}
/* Wake up the waiting thread */ /* Wake up the waiting thread */
@ -585,27 +599,6 @@ static uint16_t recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn,
sem_post(&pstate->rf_sem); sem_post(&pstate->rf_sem);
} }
/* Check for a loss of connection */
else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
nllvdbg("error\n");
/* Stop further callbacks */
pstate->rf_cb->flags = 0;
pstate->rf_cb->priv = NULL;
pstate->rf_cb->event = NULL;
/* Report not connected */
pstate->rf_result = -ENOTCONN;
/* Wake up the waiting thread */
sem_post(&pstate->rf_sem);
}
/* No data has been received -- this is some other event... probably a /* No data has been received -- this is some other event... probably a
* poll -- check for a timeout. * poll -- check for a timeout.
*/ */
@ -719,7 +712,9 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
if (pstate->rf_result < 0) if (pstate->rf_result < 0)
{ {
/* Return EGAIN on a timeout or ENOTCONN on loss of connection */ /* This might return EGAIN on a timeout or ENOTCONN on loss of
* connection (TCP only)
*/
return pstate->rf_result; return pstate->rf_result;
} }
@ -796,7 +791,7 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
{ {
/* Set up the callback in the connection */ /* Set up the callback in the connection */
state.rf_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; state.rf_cb->flags = UIP_NEWDATA|UIP_POLL;
state.rf_cb->priv = (void*)&state; state.rf_cb->priv = (void*)&state;
state.rf_cb->event = recvfrom_udpinterrupt; state.rf_cb->event = recvfrom_udpinterrupt;
@ -900,11 +895,20 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
if (!_SS_ISCONNECTED(psock->s_flags)) if (!_SS_ISCONNECTED(psock->s_flags))
{ {
/* Was any data transferred from the readahead buffer after we were /* Was any data transferred from the readahead buffer after we were
* disconnected? * disconnected? If so, then return the number of bytes received. We
* will wait to return end disconnection indications the next time that
* recvfrom() is called.
*
* If no data was received (i.e., ret == 0 -- it will not be negative)
* and the connection was gracefully closed by the remote peer, then return
* success. If rf_recvlen is zero, the caller of recvfrom() will get an
* end-of-file indication.
*/ */
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0 #if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
if (ret <= 0) if (ret <= 0 && !_SS_ISCLOSED(psock->s_flags))
#else
if (!_SS_ISCLOSED(psock->s_flags))
#endif #endif
{ {
/* Nothing was previously received from the readahead buffers. /* Nothing was previously received from the readahead buffers.
@ -1008,8 +1012,10 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* fromlen The length of the address structure * fromlen The length of the address structure
* *
* Returned Value: * Returned Value:
* On success, returns the number of characters sent. On error, * On success, returns the number of characters sent. If no data is
* -1 is returned, and errno is set appropriately: * available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Othwerwise, on errors, -1 is returned, and errno
* is set appropriately:
* *
* EAGAIN * EAGAIN
* The socket is marked non-blocking and the receive operation would block, * The socket is marked non-blocking and the receive operation would block,

View File

@ -103,22 +103,13 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
nllvdbg("flags: %04x\n", flags); nllvdbg("flags: %04x\n", flags);
if (pstate) if (pstate)
{ {
/* Check if the connection was rejected */
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
/* Yes.. then terminate with an error */
pstate->st_sndlen = -ENOTCONN;
}
/* Check if the outgoing packet is available (it may have been claimed /* Check if the outgoing packet is available (it may have been claimed
* by a sendto interrupt serving a different thread -OR- if the output * by a sendto interrupt serving a different thread -OR- if the output
* buffer currently contains unprocessed incoming data. In these cases * buffer currently contains unprocessed incoming data. In these cases
* we will just have to wait for the next polling cycle. * we will just have to wait for the next polling cycle.
*/ */
else if (dev->d_sndlen > 0 || (flags & UIP_NEWDATA) != 0) if (dev->d_sndlen > 0 || (flags & UIP_NEWDATA) != 0)
{ {
/* Another thread has beat us sending data or the buffer is busy, /* Another thread has beat us sending data or the buffer is busy,
* wait for the next polling cycle * wait for the next polling cycle
@ -314,7 +305,7 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
state.st_cb = uip_udpcallbackalloc(conn); state.st_cb = uip_udpcallbackalloc(conn);
if (state.st_cb) if (state.st_cb)
{ {
state.st_cb->flags = UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; state.st_cb->flags = UIP_POLL;
state.st_cb->priv = (void*)&state; state.st_cb->priv = (void*)&state;
state.st_cb->event = sendto_interrupt; state.st_cb->event = sendto_interrupt;