summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/ChangeLog.txt2
-rw-r--r--apps/netutils/telnetd/telnetd_driver.c18
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/net/recvfrom.c43
4 files changed, 46 insertions, 20 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index a445c2024..bcc0ac172 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -490,3 +490,5 @@
* apps/builtin/: Extensions from Mike Smith.
* apps/examples/ftpd/Makefile: Name ftpd_start is not the name of
the entrypoint. Should be ftpd_main (from Yan T.)
+ * apps/netutils/telnetd/telnetd_driver: Was stuck in a loop if
+ recv[from]() ever returned a value <= 0.
diff --git a/apps/netutils/telnetd/telnetd_driver.c b/apps/netutils/telnetd/telnetd_driver.c
index 1183a2f70..274fde370 100644
--- a/apps/netutils/telnetd/telnetd_driver.c
+++ b/apps/netutils/telnetd/telnetd_driver.c
@@ -558,6 +558,8 @@ static ssize_t telnetd_read(FAR struct file *filep, FAR char *buffer, size_t len
{
if (priv->td_pending > 0)
{
+ /* Process the buffered telnet data */
+
FAR const char *src = &priv->td_rxbuffer[priv->td_offset];
ret = telnetd_receive(priv, src, priv->td_pending, buffer, len);
}
@@ -568,13 +570,25 @@ static ssize_t telnetd_read(FAR struct file *filep, FAR char *buffer, size_t len
{
ret = psock_recv(&priv->td_psock, priv->td_rxbuffer,
CONFIG_TELNETD_RXBUFFER_SIZE, 0);
+
+ /* Did we receive anything? */
+
if (ret > 0)
{
- /* Process the received telnet data */
+ /* Yes.. Process the newly received telnet data */
telnetd_dumpbuffer("Received buffer", priv->td_rxbuffer, ret);
ret = telnetd_receive(priv, priv->td_rxbuffer, ret, buffer, len);
}
+
+ /* Otherwise the peer closed the connection (ret == 0) or an error
+ * occurred (ret < 0).
+ */
+
+ else
+ {
+ break;
+ }
}
}
while (ret == 0);
@@ -746,7 +760,7 @@ FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon)
* instance resided in the daemon's socket array).
*/
- psock = sockfd_socket(sd);
+ psock = sockfd_socket(sd);
if (!psock)
{
nlldbg("Failed to convert sd=%d to a socket structure\n", sd);
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 80944db66..77441dd21 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3993,3 +3993,6 @@
(gracefully). recv[from]() returned success and the closure
was never detected. Hmmm.. I don't know why the network monitor
did not catch this event. This is an important bug fix.
+ * net/recvfrom(): Fix a introduced with the last bugfix. If
+ the peer does an orderly closure of the socket, report 0 not
+ -ENOTCONN
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index ac8065f81..a1a6742c5 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -571,40 +571,47 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
* gracefully disconnected
* _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was
* rudely disconnected
- *
- * These flag settings are probably not necessary if
- * CONFIG_NET_TCP_RECVDELAY == 0; in that case we know that
- * pstate->rf_recvlen == 0 and we will always return -ENOTCONN.
*/
psock = pstate->rf_sock;
if ((flags & UIP_CLOSE) != 0)
{
+ /* Report that the connection was gracefully closed */
+
psock->s_flags &= ~_SF_CONNECTED;
psock->s_flags |= _SF_CLOSED;
+
+ /* This case should always return success (zero)! The value of
+ * rf_recvlen, if zero, will indicate that the connection was
+ * gracefully closed.
+ */
+
+ pstate->rf_result = 0;
}
else
{
+ /* Report that the connection was rudely lost */
+
psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
- }
- /* If no data has been received, then return ENOTCONN.
- * Otherwise, let this return success. The failure will
- * be reported the next time that recv[from]() is called.
- */
+ /* If no data has been received, then return ENOTCONN.
+ * Otherwise, let this return success. The failure will
+ * be reported the next time that recv[from]() is called.
+ */
#if CONFIG_NET_TCP_RECVDELAY > 0
- if (pstate->rf_recvlen > 0)
- {
- pstate->rf_result = 0;
- }
- else
- {
- pstate->rf_result = -ENOTCONN;
- }
+ if (pstate->rf_recvlen > 0)
+ {
+ pstate->rf_result = 0;
+ }
+ else
+ {
+ pstate->rf_result = -ENOTCONN;
+ }
#else
- pstate->rf_result = -ENOTCONN;
+ pstate->rf_result = -ENOTCONN;
#endif
+ }
/* Wake up the waiting thread */