summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog7
-rw-r--r--nuttx/Documentation/NuttX.html7
-rw-r--r--nuttx/net/accept.c12
-rw-r--r--nuttx/net/recvfrom.c4
-rw-r--r--nuttx/netutils/thttpd/config.h10
-rw-r--r--nuttx/netutils/thttpd/libhttpd.c101
-rw-r--r--nuttx/netutils/thttpd/thttpd.c110
7 files changed, 146 insertions, 105 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 72c1f89e7..f26fecc8c 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -828,9 +828,10 @@
* configs/ntosd-dm320/thttpd: A build configuration for THTTPD on the Neuros
DM320 platform.
* lib/: Added strstr() and strpbrk().
- * net/recvfrom.c: Sockets now support some non-blocking operations --
- specifically only for TCP/IP read operations when read-ahead buffering
- is enabled.
+ * net/recvfrom.c and net/accept(): Sockets now support some non-blocking
+ operations, specifically for (1) TCP/IP read operations when read-ahead
+ buffering is enabled, and (2) TCP/IP accept() operations when TCP/IP
+ connection backlog is enabled.
* fs/fs_fcntl.c and net/net_vfcntl.c: Minimal support provided for fcntl().
It can, at least, be used to mark sockets as blocking or non-blocking.
* net/net_close.c: Fix bug in close(). If reference count not set to zero
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 53b35cbfa..fb2ec5067 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -1501,9 +1501,10 @@ nuttx-0.4.10 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* configs/ntosd-dm320/thttpd: A build configuration for THTTPD on the Neuros
DM320 platform.
* lib/: Added strstr() and strpbrk().
- * net/recvfrom.c: Sockets now support some non-blocking operations --
- specifically only for TCP/IP read operations when read-ahead buffering
- is enabled.
+ * net/recvfrom.c and net/accept(): Sockets now support some non-blocking
+ operations, specifically for (1) TCP/IP read operations when read-ahead
+ buffering is enabled, and (2) TCP/IP accept() operations when TCP/IP
+ connection backlog is enabled.
* fs/fs_fcntl.c and net/net_vfcntl.c: Minimal support provided for fcntl().
It can, at least, be used to mark sockets as blocking or non-blocking.
* net/net_close.c: Fix bug in close(). If reference count not set to zero
diff --git a/nuttx/net/accept.c b/nuttx/net/accept.c
index 81ac8dbff..28ea7e237 100644
--- a/nuttx/net/accept.c
+++ b/nuttx/net/accept.c
@@ -356,6 +356,18 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
nvdbg("Pending conn=%p\n", state.acpt_newconn);
accept_tcpsender(state.acpt_newconn, inaddr);
}
+
+ /* In general, this uIP-based implementation will not support non-blocking
+ * socket operations... except in a few cases: Here for TCP accept with backlog
+ * enabled. If this socket is configured as non-blocking then return EAGAIN
+ * if there is no pending connection in the backlog.
+ */
+
+ else if (_SS_ISNONBLOCK(psock->s_flags))
+ {
+ err = EAGAIN;
+ goto errout_with_irq;
+ }
else
#endif
{
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index 345ec380a..e5fc27ac6 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -882,8 +882,8 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
recvfrom_readahead(&state);
- /* In general, this uI-based implementation will not support non-blocking
- * socket operations... except in this one case: TCP receive with read-ahead
+ /* 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
* enabled. If this socket is configured as non-blocking then return EAGAIN
* if no data was obtained from the read-ahead buffers.
*/
diff --git a/nuttx/netutils/thttpd/config.h b/nuttx/netutils/thttpd/config.h
index 63b76a06d..2fe70539a 100644
--- a/nuttx/netutils/thttpd/config.h
+++ b/nuttx/netutils/thttpd/config.h
@@ -131,10 +131,20 @@
# define CONFIG_THTTPD_CHARSET "iso-8859-1"
# endif
+/* Initial buffer size, buffer reallocation increment, maximum buffer size */
+
# ifndef CONFIG_THTTPD_IOBUFFERSIZE
# define CONFIG_THTTPD_IOBUFFERSIZE 256
# endif
+# ifndef CONFIG_THTTPD_REALLOCINCR
+# define CONFIG_THTTPD_REALLOCINCR 128
+# endif
+
+# ifndef CONFIG_THTTPD_MAXREALLOC
+# define CONFIG_THTTPD_MAXREALLOC 4096
+# endif
+
# if CONFIG_THTTPD_IOBUFFERSIZE > 65535
# error "Can't use uint16 for buffer"
# endif
diff --git a/nuttx/netutils/thttpd/libhttpd.c b/nuttx/netutils/thttpd/libhttpd.c
index fa294f392..68e1e5c48 100644
--- a/nuttx/netutils/thttpd/libhttpd.c
+++ b/nuttx/netutils/thttpd/libhttpd.c
@@ -3469,7 +3469,7 @@ void httpd_realloc_str(char **strP, size_t * maxsizeP, size_t size)
{
if (*maxsizeP == 0)
{
- *maxsizeP = MAX(200, size + 100);
+ *maxsizeP = MAX(CONFIG_THTTPD_IOBUFFERSIZE, size + CONFIG_THTTPD_REALLOCINCR);
*strP = NEW(char, *maxsizeP + 1);
++str_alloc_count;
str_alloc_size += *maxsizeP;
@@ -3559,7 +3559,7 @@ int httpd_get_conn(httpd_server *hs, int listen_fd, httpd_conn *hc)
if (!hc->initialized)
{
hc->read_size = 0;
- httpd_realloc_str(&hc->read_buf, &hc->read_size, 500);
+ httpd_realloc_str(&hc->read_buf, &hc->read_size, CONFIG_THTTPD_IOBUFFERSIZE);
hc->maxdecodedurl =
hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings =
hc->maxpathinfo = hc->maxquery = hc->maxaccept =
@@ -3567,7 +3567,7 @@ int httpd_get_conn(httpd_server *hs, int listen_fd, httpd_conn *hc)
hc->maxremoteuser = 0;
#ifdef CONFIG_THTTPD_TILDE_MAP2
hc->maxaltdir = 0;
-#endif /*CONFIG_THTTPD_TILDE_MAP2 */
+#endif
httpd_realloc_str(&hc->decodedurl, &hc->maxdecodedurl, 1);
httpd_realloc_str(&hc->origfilename, &hc->maxorigfilename, 1);
httpd_realloc_str(&hc->expnfilename, &hc->maxexpnfilename, 0);
@@ -3587,6 +3587,7 @@ int httpd_get_conn(httpd_server *hs, int listen_fd, httpd_conn *hc)
/* Accept the new connection. */
+ nvdbg("accept() new connection on listen_fd %d\n", listen_fd);
sz = sizeof(sa);
hc->conn_fd = accept(listen_fd, (struct sockaddr*)&sa, &sz);
if (hc->conn_fd < 0)
@@ -3613,54 +3614,56 @@ int httpd_get_conn(httpd_server *hs, int listen_fd, httpd_conn *hc)
hc->hs = hs;
(void)memset(&hc->client_addr, 0, sizeof(hc->client_addr));
(void)memmove(&hc->client_addr, &sa, sockaddr_len(&sa));
- hc->read_idx = 0;
- hc->checked_idx = 0;
- hc->checked_state = CHST_FIRSTWORD;
- hc->method = METHOD_UNKNOWN;
- hc->status = 0;
- hc->bytes_to_send = 0;
- hc->bytes_sent = 0;
- hc->encodedurl = "";
- hc->decodedurl[0] = '\0';
- hc->protocol = "UNKNOWN";
- hc->origfilename[0] = '\0';
- hc->expnfilename[0] = '\0';
- hc->encodings[0] = '\0';
- hc->pathinfo[0] = '\0';
- hc->query[0] = '\0';
- hc->referer = "";
- hc->useragent = "";
- hc->accept[0] = '\0';
- hc->accepte[0] = '\0';
- hc->acceptl = "";
- hc->cookie = "";
- hc->contenttype = "";
- hc->reqhost[0] = '\0';
- hc->hdrhost = "";
- hc->hostdir[0] = '\0';
- hc->authorization = "";
- hc->remoteuser[0] = '\0';
- hc->buffer[0] = '\0';
+ hc->read_idx = 0;
+ hc->checked_idx = 0;
+ hc->checked_state = CHST_FIRSTWORD;
+ hc->method = METHOD_UNKNOWN;
+ hc->status = 0;
+ hc->bytes_to_send = 0;
+ hc->bytes_sent = 0;
+ hc->encodedurl = "";
+ hc->decodedurl[0] = '\0';
+ hc->protocol = "UNKNOWN";
+ hc->origfilename[0] = '\0';
+ hc->expnfilename[0] = '\0';
+ hc->encodings[0] = '\0';
+ hc->pathinfo[0] = '\0';
+ hc->query[0] = '\0';
+ hc->referer = "";
+ hc->useragent = "";
+ hc->accept[0] = '\0';
+ hc->accepte[0] = '\0';
+ hc->acceptl = "";
+ hc->cookie = "";
+ hc->contenttype = "";
+ hc->reqhost[0] = '\0';
+ hc->hdrhost = "";
+ hc->hostdir[0] = '\0';
+ hc->authorization = "";
+ hc->remoteuser[0] = '\0';
+ hc->buffer[0] = '\0';
#ifdef CONFIG_THTTPD_TILDE_MAP2
- hc->altdir[0] = '\0';
+ hc->altdir[0] = '\0';
#endif
hc->buflen = 0;
hc->if_modified_since = (time_t) - 1;
- hc->range_if = (time_t) - 1;
- hc->contentlength = -1;
+ hc->range_if = (time_t)-1;
+ hc->contentlength = -1;
hc->type = "";
#ifdef CONFIG_THTTPD_VHOST
- hc->vhostname = NULL;
+ hc->vhostname = NULL;
#endif
- hc->mime_flag = TRUE;
- hc->one_one = FALSE;
- hc->got_range = FALSE;
- hc->tildemapped = FALSE;
- hc->range_start = 0;
- hc->range_end = -1;
- hc->keep_alive = FALSE;
- hc->should_linger = FALSE;
- hc->file_fd = -1;
+ hc->mime_flag = TRUE;
+ hc->one_one = FALSE;
+ hc->got_range = FALSE;
+ hc->tildemapped = FALSE;
+ hc->range_start = 0;
+ hc->range_end = -1;
+ hc->keep_alive = FALSE;
+ hc->should_linger = FALSE;
+ hc->file_fd = -1;
+
+ nvdbg("New connection accepted on %d\n", hc->conn_fd);
return GC_OK;
}
@@ -4067,14 +4070,13 @@ int httpd_parse_request(httpd_conn *hc)
cp += strspn(cp, " \t");
if (hc->accept[0] != '\0')
{
- if (strlen(hc->accept) > 5000)
+ if (strlen(hc->accept) > CONFIG_THTTPD_MAXREALLOC)
{
ndbg("%s way too much Accept: data\n",
httpd_ntoa(&hc->client_addr));
continue;
}
- httpd_realloc_str(&hc->accept, &hc->maxaccept,
- strlen(hc->accept) + 2 + strlen(cp));
+ httpd_realloc_str(&hc->accept, &hc->maxaccept, strlen(hc->accept) + 2 + strlen(cp));
(void)strcat(hc->accept, ", ");
}
else
@@ -4089,14 +4091,13 @@ int httpd_parse_request(httpd_conn *hc)
cp += strspn(cp, " \t");
if (hc->accepte[0] != '\0')
{
- if (strlen(hc->accepte) > 5000)
+ if (strlen(hc->accepte) > CONFIG_THTTPD_MAXREALLOC)
{
ndbg("%s way too much Accept-Encoding: data\n",
httpd_ntoa(&hc->client_addr));
continue;
}
- httpd_realloc_str(&hc->accepte, &hc->maxaccepte,
- strlen(hc->accepte) + 2 + strlen(cp));
+ httpd_realloc_str(&hc->accepte, &hc->maxaccepte, strlen(hc->accepte) + 2 + strlen(cp));
(void)strcat(hc->accepte, ", ");
}
else
diff --git a/nuttx/netutils/thttpd/thttpd.c b/nuttx/netutils/thttpd/thttpd.c
index 259f88e1b..d89d6dd06 100644
--- a/nuttx/netutils/thttpd/thttpd.c
+++ b/nuttx/netutils/thttpd/thttpd.c
@@ -195,37 +195,42 @@ static int handle_newconnect(struct timeval *tv, int listen_fd)
struct connect_s *conn;
ClientData client_data;
- /* This loops until the accept() fails, trying to start new connections as
- * fast as possible so we don't overrun the listen queue.
+ /* This loops until the accept() fails, trying to start new connections as
+ * fast as possible so we don't overrun the listen queue.
*/
+ nvdbg("New connection(s) on listen_fd %d\n", listen_fd);
for (;;)
{
/* Is there room in the connection table? */
+
if (num_connects >= AVAILABLE_FDS)
{
/* Out of connection slots. Run the timers, then the existing
* connections, and maybe we'll free up a slot by the time we get
- * back here. */
+ * back here.
+ */
+
ndbg("too many connections!\n");
tmr_run(tv);
- return 0;
+ return -1;
}
/* Get the first free connection entry off the free list */
+#ifdef CONFIG_DEBUG
if (first_free_connect == -1 ||
connects[first_free_connect].conn_state != CNST_FREE)
{
ndbg("the connects free list is messed up\n");
exit(1);
}
-
+#endif
conn = &connects[first_free_connect];
/* Make the httpd_conn if necessary */
- if (conn->hc == (httpd_conn *) 0)
+ if (!conn->hc)
{
conn->hc = NEW(httpd_conn, 1);
if (conn->hc == (httpd_conn *) 0)
@@ -233,8 +238,9 @@ static int handle_newconnect(struct timeval *tv, int listen_fd)
ndbg("out of memory allocating an httpd_conn\n");
exit(1);
}
+
conn->hc->initialized = 0;
- ++httpd_conn_count;
+ httpd_conn_count++;
}
/* Get the connection */
@@ -247,37 +253,43 @@ static int handle_newconnect(struct timeval *tv, int listen_fd)
case GC_FAIL:
tmr_run(tv);
- return 0;
+ return -1;
/* No more connections to accept for now */
case GC_NO_MORE:
- return 1;
+ return 0;
+
+ default:
+ break;
}
+ nvdbg("New connection fd %d\n", conn->hc->conn_fd);
+
conn->conn_state = CNST_READING;
/* Pop it off the free list */
- first_free_connect = conn->next_free_connect;
+ first_free_connect = conn->next_free_connect;
conn->next_free_connect = -1;
- ++num_connects;
- client_data.p = conn;
- conn->active_at = tv->tv_sec;
- conn->wakeup_timer = (Timer *) 0;
- conn->linger_timer = (Timer *) 0;
- conn->offset = 0;
+ num_connects++;
+ client_data.p = conn;
+ conn->active_at = tv->tv_sec;
+ conn->wakeup_timer = NULL;
+ conn->linger_timer = NULL;
+ conn->offset = 0;
/* Set the connection file descriptor to no-delay mode */
httpd_set_ndelay(conn->hc->conn_fd);
-
fdwatch_add_fd(fw, conn->hc->conn_fd, conn, FDW_READ);
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET)
++stats_connections;
if (num_connects > stats_simultaneous)
- stats_simultaneous = num_connects;
+ {
+ stats_simultaneous = num_connects;
+ }
#endif
}
}
@@ -293,11 +305,11 @@ static void handle_read(struct connect_s *conn, struct timeval *tv)
if (hc->read_idx >= hc->read_size)
{
- if (hc->read_size > 5000)
+ if (hc->read_size > CONFIG_THTTPD_MAXREALLOC)
{
goto errout_with_400;
}
- httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->read_size + 1000);
+ httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->read_size + CONFIG_THTTPD_REALLOCINCR);
}
/* Read some more bytes */
@@ -880,7 +892,12 @@ int thttpd_main(int argc, char **argv)
if (num_ready < 0)
{
if (errno == EINTR || errno == EAGAIN)
- continue; /* try again */
+ {
+ /* Not errors... try again */
+
+ continue;
+ }
+
ndbg("fdwatch: %d\n", errno);
exit(1);
}
@@ -897,10 +914,9 @@ int thttpd_main(int argc, char **argv)
/* Is it a new connection? */
- if (hs != (httpd_server *) 0 && hs->listen_fd != -1 &&
- fdwatch_check_fd(fw, hs->listen_fd))
+ if (fdwatch_check_fd(fw, hs->listen_fd))
{
- if (handle_newconnect(&tv, hs->listen_fd))
+ if (!handle_newconnect(&tv, hs->listen_fd))
{
/* Go around the loop and do another fdwatch, rather than
* dropping through and processing existing connections. New
@@ -913,33 +929,33 @@ int thttpd_main(int argc, char **argv)
/* Find the connections that need servicing */
- while ((conn =
- (struct connect_s*)fdwatch_get_next_client_data(fw)) !=
- (struct connect_s*)- 1)
+ while ((conn = (struct connect_s*)fdwatch_get_next_client_data(fw)) != (struct connect_s*)-1)
{
- if (conn == (struct connect_s *) 0)
- continue;
-
- hc = conn->hc;
- if (!fdwatch_check_fd(fw, hc->conn_fd))
+ if (conn)
{
- /* Something went wrong */
+ hc = conn->hc;
+ if (!fdwatch_check_fd(fw, hc->conn_fd))
+ {
+ /* Something went wrong */
- clear_connection(conn, &tv);
- }
- else
- {
- switch (conn->conn_state)
+ nvdbg("Clearing connection\n");
+ clear_connection(conn, &tv);
+ }
+ else
{
- case CNST_READING:
- handle_read(conn, &tv);
- break;
- case CNST_SENDING:
- handle_send(conn, &tv);
- break;
- case CNST_LINGERING:
- handle_linger(conn, &tv);
- break;
+ nvdbg("Handle conn_state %d\n", conn->conn_state);
+ switch (conn->conn_state)
+ {
+ case CNST_READING:
+ handle_read(conn, &tv);
+ break;
+ case CNST_SENDING:
+ handle_send(conn, &tv);
+ break;
+ case CNST_LINGERING:
+ handle_linger(conn, &tv);
+ break;
+ }
}
}
}