summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/netutils/ftpc/ftpc_getfile.c44
-rw-r--r--apps/netutils/ftpc/ftpc_putfile.c42
-rw-r--r--apps/netutils/ftpc/ftpc_socket.c2
-rw-r--r--apps/netutils/ftpc/ftpc_transfer.c35
-rw-r--r--nuttx/ChangeLog7
-rw-r--r--nuttx/net/recvfrom.c69
6 files changed, 62 insertions, 137 deletions
diff --git a/apps/netutils/ftpc/ftpc_getfile.c b/apps/netutils/ftpc/ftpc_getfile.c
index 8a60c514b..366351636 100644
--- a/apps/netutils/ftpc/ftpc_getfile.c
+++ b/apps/netutils/ftpc/ftpc_getfile.c
@@ -167,31 +167,6 @@ static int ftpc_recvinit(struct ftpc_session_s *session, FAR const char *path,
}
/****************************************************************************
- * Name: ftpc_waitinput
- *
- * Description:
- * Wait to receive data.
- *
- ****************************************************************************/
-
-static int ftpc_waitinput(FAR struct ftpc_session_s *session)
-{
- int ret;
- do {
- ret = ftpc_waitdata(session, session->data.instream, true);
- if (ret == -1) {
- if (errno == EINTR)
- {
- FTPC_SET_INTERRUPT(session);
- }
- return ERROR;
- }
- } while(ret == 0);
-
- return OK;
-}
-
-/****************************************************************************
* Name: ftpc_recvbinary
*
* Description:
@@ -219,16 +194,6 @@ static int ftpc_recvbinary(FAR struct ftpc_session_s *session,
for (;;)
{
- /* Wait for input on the socket */
-
- ret = ftpc_waitinput(session);
- if (ret != OK)
- {
- nvdbg("ftpc_waitinput() failed\n");
- err = EIO;
- goto errout_with_buf;
- }
-
/* Read the data from the socket */
nread = fread(buf, sizeof(char), CONFIG_FTP_BUFSIZE, rinstream);
@@ -451,15 +416,6 @@ int ftpc_recvtext(FAR struct ftpc_session_s *session,
while ((ch = fgetc(rinstream)) != EOF)
{
- /* Wait for input on the socket */
-
- ret = ftpc_waitinput(session);
- if (ret != OK)
- {
- nvdbg("ftpc_waitinput() failed\n");
- break;
- }
-
/* Is it a carriage return? Compress \r\n to \n */
if (ch == '\r')
diff --git a/apps/netutils/ftpc/ftpc_putfile.c b/apps/netutils/ftpc/ftpc_putfile.c
index e008da3b1..bc20853d7 100644
--- a/apps/netutils/ftpc/ftpc_putfile.c
+++ b/apps/netutils/ftpc/ftpc_putfile.c
@@ -72,30 +72,6 @@
****************************************************************************/
/****************************************************************************
- * Name: ftpc_waitoutput
- *
- * Description:
- * Wait to send data.
- *
- ****************************************************************************/
-
-static int ftpc_waitoutput(FAR struct ftpc_session_s *session)
-{
- int ret;
-
- do
- {
- ret = ftpc_waitdata(session, session->data.outstream, false);
- if (ret < 0)
- {
- return ERROR;
- }
- }
- while(ret == 0);
- return OK;
-}
-
-/****************************************************************************
* Name: ftpc_sendbinary
*
* Description:
@@ -129,15 +105,6 @@ static int ftpc_sendbinary(FAR struct ftpc_session_s *session,
break;
}
- /* Wait to make sure that we send the data without blocking */
-
- ret = ftpc_waitoutput(session);
- if (ret != OK)
- {
- ret = ERROR;
- break;
- }
-
/* Send the data */
nwritten = fwrite(buf, sizeof(char), nread, routstream);
@@ -174,15 +141,8 @@ static int ftpc_sendtext(FAR struct ftpc_session_s *session,
/* Write characters one at a time. */
- while((c = fgetc(linstream)) != EOF)
+ while ((c = fgetc(linstream)) != EOF)
{
- /* Make sure that we can send the character without blocking */
-
- if (ftpc_waitoutput(session) != 0)
- {
- break;
- }
-
/* If it is a newline, send a carriage return too */
if (c == '\n')
diff --git a/apps/netutils/ftpc/ftpc_socket.c b/apps/netutils/ftpc/ftpc_socket.c
index d245c812d..4ec022bd0 100644
--- a/apps/netutils/ftpc/ftpc_socket.c
+++ b/apps/netutils/ftpc/ftpc_socket.c
@@ -185,8 +185,8 @@ int ftpc_sockconnect(struct ftpc_socket_s *sock, struct sockaddr_in *addr)
ndbg("ftpc_sockgetsockname() failed: %d\n", errno);
return ERROR;
}
- sock->connected = true;
+ sock->connected = true;
return OK;
}
diff --git a/apps/netutils/ftpc/ftpc_transfer.c b/apps/netutils/ftpc/ftpc_transfer.c
index 4dfa6d47b..f808e67fb 100644
--- a/apps/netutils/ftpc/ftpc_transfer.c
+++ b/apps/netutils/ftpc/ftpc_transfer.c
@@ -43,7 +43,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#include <poll.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
@@ -289,8 +288,8 @@ int ftpc_xfrinit(FAR struct ftpc_session_s *session)
/* Configure the data socket */
ftpc_sockgetsockname(&session->cmd, &addr);
- memcpy(&addr.sin_addr, addrport, (size_t)4);
- memcpy(&addr.sin_port, addrport+4, (size_t)2);
+ memcpy(&addr.sin_addr, addrport, 4);
+ memcpy(&addr.sin_port, addrport+4, 2);
/* Connect the data socket */
@@ -462,36 +461,6 @@ int ftpc_xfrabort(FAR struct ftpc_session_s *session, FAR FILE *stream)
}
/****************************************************************************
- * Name: ftpc_waitdata
- *
- * Description:
- * Wait for dta to be available on the provided stream.
- *
- ****************************************************************************/
-
-int ftpc_waitdata(FAR struct ftpc_session_s *session, FAR FILE *stream, bool rdwait)
-{
- FAR struct pollfd fds;
- int ret;
-
- /* Check the stream to see if it has input OR is ready for output */
-
- fds.fd = fileno(stream);
- fds.events = rdwait ? POLLIN : POLLOUT;
- ret = poll(&fds, 1, 10*1000);
- if (ret < 0)
- {
- if (errno == EINTR)
- {
- return OK;
- }
- return ERROR;
- }
-
- return ret;
-}
-
-/****************************************************************************
* Name: ftpc_timeout
*
* Description:
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 6bfbedeef..f0d87e379 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -1796,4 +1796,11 @@
testing of the FTP client shell.
* fd/fs_fdopen.c and net/net_checksd.c: Add support so that fdopen may
be used with socket descriptors.
+ * net/recvfrom.c: Fix an error found in receiving small files via FTP:
+ The small file is received a buffered in the readahead buffer, then the
+ socket is disconnected. When the app calls recvfrom, the socket is
+ already disconnected and the buffered data is stranded. Now, recvfrom
+ will continue to return success after the socket is disconnected until
+ the readahead buffer is drained.
+
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index 335e2b322..d974b85cf 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -682,6 +682,13 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf, size_t len,
pstate->rf_starttime = clock_systimer();
#endif
}
+
+/* The only uninitialization that has to be performed is destroying the
+ * semaphore.
+ */
+
+#define recvfrom_uninit(s) sem_destroy(&(s)->rf_sem)
+
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
/****************************************************************************
@@ -706,10 +713,6 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
{
int save_errno = errno; /* In case something we do changes it */
- /* Release semaphore in the state structure */
-
- sem_destroy(&pstate->rf_sem);
-
/* Check for a error/timeout detected by the interrupt handler. Errors are
* signaled by negative errno values for the rcv length
*/
@@ -783,8 +786,7 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
ret = uip_udpconnect(conn, NULL);
if (ret < 0)
{
- uip_unlock(save);
- return ret;
+ goto errout_with_state;
}
/* Set up the callback in the connection */
@@ -814,7 +816,6 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
uip_udpdisable(conn);
uip_udpcallbackfree(conn, state.rf_cb);
- uip_unlock(save);
ret = recvfrom_result(ret, &state);
}
else
@@ -822,6 +823,9 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
ret = -EBUSY;
}
+errout_with_state:
+ uip_unlock(save);
+ recvfrom_uninit(&state);
return ret;
}
#endif /* CONFIG_NET_UDP */
@@ -859,15 +863,6 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
uip_lock_t save;
int ret = OK;
- /* Verify that the SOCK_STREAM has been connected */
-
- if (!_SS_ISCONNECTED(psock->s_flags))
- {
- /* The SOCK_STREAM must be connected in order to receive */
-
- return -ENOTCONN;
- }
-
/* Initialize the state structure. This is done with interrupts
* disabled because we don't want anything to happen until we
* are ready.
@@ -876,11 +871,47 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
save = uip_lock();
recvfrom_init(psock, buf, len, infrom, &state);
+ /* Handle any any TCP data already buffered in a read-ahead buffer. NOTE
+ * that there may be read-ahead data to be retrieved even after the
+ * socket has been disconnected.
+ */
+
#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ recvfrom_readahead(&state);
+#endif
- /* Handle any any TCP data already buffered in a read-ahead buffer. */
+ /* Verify that the SOCK_STREAM has been or still is connected */
- recvfrom_readahead(&state);
+ if (!_SS_ISCONNECTED(psock->s_flags))
+ {
+ /* Was any data transferred from the readahead buffer after we were
+ * disconnected?
+ */
+
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+ if (state.rf_recvlen <= 0)
+ {
+ /* Nothing was received. The SOCK_STREAM must be re-connected in
+ * order to receive an additional data.
+ */
+
+ ret = -ENOTCONN;
+ }
+ else
+ {
+ /* The socket is disconnected, but there is data in the read-ahead
+ * buffer. The return value is the number of bytes read from the
+ * read-ahead buffer */
+
+ ret = state.rf_recvlen;
+ }
+#else
+ /* The SOCK_STREAM must be connected inorder to receive data. */
+
+ ret = -ENOTCONN;
+#endif
+ }
+ else
/* In general, this uIP-based implementation will not support non-blocking
* socket operations... except in a few cases: Here for TCP receive with read-ahead
@@ -888,6 +919,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* if no data was obtained from the read-ahead buffers.
*/
+#if CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
if (_SS_ISNONBLOCK(psock->s_flags))
{
/* Return OK if something was received; EGAIN if not */
@@ -944,6 +976,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
}
uip_unlock(save);
+ recvfrom_uninit(&state);
return ret;
}
#endif /* CONFIG_NET_TCP */