summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-09 17:20:56 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-09-09 17:20:56 +0000
commit7a65f932826220c741ffbf5698b48692a787d915 (patch)
tree825e048f8fc18b7e69cb155ad96b7254566a3ffe /nuttx
parentd12e00bdd6ffbb39ab5d45d5d5a484d293108021 (diff)
downloadpx4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.tar.gz
px4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.tar.bz2
px4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.zip
Implement TCP send; remove uIP proto-sockets
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@339 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/examples/uip/main.c1
-rw-r--r--nuttx/include/net/uip/httpd.h49
-rw-r--r--nuttx/include/net/uip/psock.h257
-rw-r--r--nuttx/include/nuttx/net.h2
-rw-r--r--nuttx/include/sys/socket.h20
-rw-r--r--nuttx/net/bind.c1
-rw-r--r--nuttx/net/connect.c20
-rw-r--r--nuttx/net/net-internal.h20
-rw-r--r--nuttx/net/recv.c2
-rw-r--r--nuttx/net/recvfrom.c286
-rw-r--r--nuttx/net/send.c200
-rw-r--r--nuttx/net/sendto.c10
-rw-r--r--nuttx/net/uip/Make.defs2
-rw-r--r--nuttx/net/uip/psock.c385
-rw-r--r--nuttx/net/uip/uip-tcpconn.c109
-rw-r--r--nuttx/netutils/smtp/smtp.c212
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.c83
-rw-r--r--nuttx/netutils/webserver/httpd-cgi.h3
-rw-r--r--nuttx/netutils/webserver/httpd-fs.c1
-rw-r--r--nuttx/netutils/webserver/httpd.c271
-rw-r--r--nuttx/netutils/webserver/httpd.h74
21 files changed, 878 insertions, 1130 deletions
diff --git a/nuttx/examples/uip/main.c b/nuttx/examples/uip/main.c
index 9771f4a9e..773d430ea 100644
--- a/nuttx/examples/uip/main.c
+++ b/nuttx/examples/uip/main.c
@@ -89,6 +89,7 @@ int user_start(int argc, char *argv[])
#if defined(CONFIG_EXAMPLE_UIP_WEBSERVER)
httpd_init();
+ httpd_listen();
#elif defined(CONFIG_EXAMPLE_UIP_TELNETD)
telnetd_init();
#elif defined(CONFIG_EXAMPLE_UIP_DHCPC)
diff --git a/nuttx/include/net/uip/httpd.h b/nuttx/include/net/uip/httpd.h
index 1c9420448..ff99ddb36 100644
--- a/nuttx/include/net/uip/httpd.h
+++ b/nuttx/include/net/uip/httpd.h
@@ -28,51 +28,12 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __HTTPD_H__
-#define __HTTPD_H__
+#ifndef _NET_UIP_HTTPD_H
+#define _NET_UIP_HTTPD_H
#include <sys/types.h>
-#include <net/uip/psock.h>
-#define HTTPD_FS_STATISTICS 1
+extern void httpd_init(void);
+extern void httpd_listen(void);
-struct httpd_fs_file
-{
- char *data;
- int len;
-};
-
-struct httpd_state
-{
- unsigned char timer;
- struct psock sin, sout;
- char inputbuf[50];
- char filename[20];
- char state;
- struct httpd_fs_file file;
- int len;
- char *scriptptr;
- int scriptlen;
-
- unsigned short count;
-};
-
-#ifdef HTTPD_FS_STATISTICS
-#if HTTPD_FS_STATISTICS == 1
-extern uint16 httpd_fs_count(char *name);
-#endif /* HTTPD_FS_STATISTICS */
-#endif /* HTTPD_FS_STATISTICS */
-
-void httpd_init(void);
-void httpd_log(char *msg);
-void httpd_log_file(uint16 *requester, char *file);
-
-/* file must be allocated by caller and will be filled in
- * by the function.
- */
-
-int httpd_fs_open(const char *name, struct httpd_fs_file *file);
-void httpd_fs_init(void);
-
-
-#endif /* __HTTPD_H__ */
+#endif /* _NET_UIP_HTTPD_H */
diff --git a/nuttx/include/net/uip/psock.h b/nuttx/include/net/uip/psock.h
deleted file mode 100644
index 3ecc7abdc..000000000
--- a/nuttx/include/net/uip/psock.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/****************************************************************************
- * psock.h
- * Protosocket library header file
- *
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * This logic was leveraged from uIP which also has a BSD-style license:
- *
- * Author: Adam Dunkels <adam@sics.se>
- * Copyright (c) 2004, Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- ****************************************************************************/
-
-#ifndef __NET_UIP_PSOCK_H
-#define __NET_UIP_PSOCK_H
-
-/* psock Protosockets library
- *
- * The protosocket library provides an interface to the uIP stack that is
- * similar to the traditional BSD socket interface. Unlike programs
- * written for the ordinary uIP event-driven interface, programs
- * written with the protosocket library are executed in a sequential
- * fashion and does not have to be implemented as explicit state
- * machines.
- *
- * Protosockets only work with TCP connections.
- *
- * The protosocket library uses \ref pt protothreads to provide
- * sequential control flow. This makes the protosockets lightweight in
- * terms of memory, but also means that protosockets inherits the
- * functional limitations of protothreads. Each protosocket lives only
- * within a single function. Automatic variables (stack variables) are
- * not retained across a protosocket library function call.
- *
- * \note Because the protosocket library uses protothreads, local
- * variables will not always be saved across a call to a protosocket
- * library function. It is therefore advised that local variables are
- * used with extreme care.
- *
- * The protosocket library provides functions for sending data without
- * having to deal with retransmissions and acknowledgements, as well
- * as functions for reading data without having to deal with data
- * being split across more than one TCP segment.
- *
- * Because each protosocket runs as a protothread, the protosocket has to be
- * started with a call to PSOCK_BEGIN() at the start of the function
- * in which the protosocket is used. Similarly, the protosocket protothread can
- * be terminated by a call to PSOCK_EXIT().
- *
- */
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-#ifdef CONFIG_NET
-
-#include <sys/types.h>
-#include <net/uip/uipopt.h>
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-/* The structure that holds the state of a buffer.
- *
- * This structure holds the state of a uIP buffer. The structure has
- * no user-visible elements, but is used through the functions
- * provided by the library.
- *
- */
-
-struct psock_buf
-{
- uint8 *ptr;
- unsigned short left;
-};
-
-/* The representation of a protosocket.
- *
- * The protosocket structrure is an opaque structure with no user-visible
- * elements.
- */
-
-struct psock
-{
- const uint8 *sendptr; /* Pointer to the next data to be sent. */
- uint8 *readptr; /* Pointer to the next data to be read. */
- uint8 *bufptr; /* Pointer to the buffer used for buffering incoming data. */
- uint16 sendlen; /* The number of bytes left to be sent. */
- uint16 readlen; /* The number of bytes left to be read. */
- struct psock_buf buf; /* The structure holding the state of the input buffer. */
- unsigned int bufsize; /* The size of the input buffer. */
- unsigned char state; /* The state of the protosocket. */
-};
-
-/****************************************************************************
- * Public FunctionPrototypes
- ****************************************************************************/
-
-/* Initialize a protosocket.
- *
- * Initializes a protosocket and must be called before the
- * protosocket is used. The initialization also specifies the input buffer
- * for the protosocket.
- *
- * psock (struct psock *) A pointer to the protosocket to be
- * initialized
- *
- * buffer (char *) A pointer to the input buffer for the
- * protosocket.
- *
- * buffersize (unsigned int) The size of the input buffer.
- */
-
-extern void psock_init(struct psock *psock, char *buffer, unsigned int buffersize);
-
-/* Send data.
- *
- * This macro sends data over a protosocket. The protosocket protothread blocks
- * until all data has been sent and is known to have been received by
- * the remote end of the TCP connection.
- *
- * psock (struct psock *) A pointer to the protosocket over which
- * data is to be sent.
- *
- * data (char *) A pointer to the data that is to be sent.
- *
- * datalen (unsigned int) The length of the data that is to be
- * sent.
- */
-
-extern void psock_send(struct psock *psock, const char *buf, unsigned int len);
-
-/*Send a null-terminated string.
- *
- * psock Pointer to the protosocket.
- * str The string to be sent.
- *
- * This function sends a null-terminated string over the
- * protosocket.
- */
-
-#define PSOCK_SEND_STR(psock, str) psock_send(psock, str, strlen(str))
-
-/* Generate data with a function and send it
- *
- * psock Pointer to the protosocket.
- * generator Pointer to the generator function
- * arg Argument to the generator function
- *
- * This function generates data and sends it over the
- * protosocket. This can be used to dynamically generate
- * data for a transmission, instead of generating the data
- * in a buffer beforehand. This function reduces the need for
- * buffer memory. The generator function is implemented by
- * the application, and a pointer to the function is given
- * as an argument with the call to PSOCK_GENERATOR_SEND().
- *
- * The generator function should place the generated data
- * directly in the uip_appdata buffer, and return the
- * length of the generated data. The generator function is
- * called by the protosocket layer when the data first is
- * sent, and once for every retransmission that is needed.
- */
-
-extern void psock_generator_send(struct psock *psock, unsigned short (*f)(void *), void *arg);
-
-/* Close a protosocket.
- *
- * This macro closes a protosocket and can only be called from within the
- * protothread in which the protosocket lives.
- *
- * psock (struct psock *) A pointer to the protosocket that is to
- * be closed.
- */
-
-#define PSOCK_CLOSE(psock) uip_close()
-
-/* Read data until the buffer is full.
- *
- * This macro will block waiting for data and read the data into the
- * input buffer specified with the call to PSOCK_INIT(). Data is read
- * until the buffer is full..
- *
- * psock (struct psock *) A pointer to the protosocket from which
- * data should be read.
- */
-
-extern void psock_readbuf(struct psock *psock);
-
-/* Read data up to a specified character.
- *
- * This macro will block waiting for data and read the data into the
- * input buffer specified with the call to PSOCK_INIT(). Data is only
- * read until the specifieed character appears in the data stream.
- *
- * psock (struct psock *) A pointer to the protosocket from which
- * data should be read.
- *
- * c (char) The character at which to stop reading.
- */
-
-extern void psock_readto(struct psock *psock, unsigned char c);
-
-/* The length of the data that was previously read.
- *
- * Returns the length of the data that was previously read
- * using PSOCK_READTO() or PSOCK_READ().
- *
- * psock (struct psock *) A pointer to the protosocket holding the data.
- */
-
-extern uint16 psock_datalen(struct psock *psock);
-
-/* Check if there is new data has arrived on a protosocket without blocking
- *
- * psock (struct psock *) A pointer to the protosocket.
- */
-
-extern boolean psock_checknewdata(struct psock *s);
-
-/* Block until new data has arrived on a protosocket.
- *
- * psock (struct psock *) A pointer to the protosocket.
- */
-
-extern void psock_waitnewdata(struct psock *s);
-
-#endif /* CONFIG_NET */
-#endif /* __NET_UIP_PSOCK_H */
diff --git a/nuttx/include/nuttx/net.h b/nuttx/include/nuttx/net.h
index 2f700a985..5247fe3fd 100644
--- a/nuttx/include/nuttx/net.h
+++ b/nuttx/include/nuttx/net.h
@@ -46,7 +46,6 @@
#include <semaphore.h>
#include <net/uip/uip.h>
-#include <net/uip/psock.h>
/****************************************************************************
* Definitions
@@ -87,6 +86,7 @@ struct socket
{
int s_crefs; /* Reference count on the socket */
uint8 s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
+ uint8 s_flags; /* See _SF_* definitions */
#ifdef CONFIG_NET_SOCKOPTS
sockopt_t s_options; /* Selected socket options */
#ifndef CONFIG_DISABLE_CLOCK
diff --git a/nuttx/include/sys/socket.h b/nuttx/include/sys/socket.h
index 52c20e272..865b1f69e 100644
--- a/nuttx/include/sys/socket.h
+++ b/nuttx/include/sys/socket.h
@@ -177,21 +177,21 @@ extern "C" {
#endif
EXTERN int socket(int domain, int type, int protocol);
-EXTERN int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-EXTERN int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+EXTERN int bind(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen);
+EXTERN int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen);
-EXTERN ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-EXTERN ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
- const struct sockaddr *to, socklen_t tolen);
+EXTERN ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags);
+EXTERN ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
+ FAR const struct sockaddr *to, socklen_t tolen);
-EXTERN ssize_t recv(int sockfd, void *buf, size_t len, int flags);
-EXTERN ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen);
+EXTERN ssize_t recv(int sockfd, FAR void *buf, size_t len, int flags);
+EXTERN ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
+ FAR struct sockaddr *from, FAR socklen_t *fromlen);
EXTERN int setsockopt(int sockfd, int level, int option,
- const void *value, socklen_t value_len);
+ FAR const void *value, socklen_t value_len);
EXTERN int getsockopt(int sockfd, int level, int option,
- void *value, socklen_t *value_len);
+ FAR void *value, FAR socklen_t *value_len);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c
index edc9776d4..f1d5dbbd9 100644
--- a/nuttx/net/bind.c
+++ b/nuttx/net/bind.c
@@ -119,6 +119,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
case SOCK_STREAM:
ret = uip_tcpbind(psock->s_conn, inaddr);
+ psock->s_flags |= _SF_BOUND;
break;
#ifdef CONFIG_NET_UDP
diff --git a/nuttx/net/connect.c b/nuttx/net/connect.c
index aaa267227..5bc978fe9 100644
--- a/nuttx/net/connect.c
+++ b/nuttx/net/connect.c
@@ -90,7 +90,7 @@
* sa_family field.
* EAGAIN
* No more free local ports or insufficient entries in the routing
- * cache. For PF_INET.
+ * cache.
* EALREADY
* The socket is non-blocking and a previous connection attempt has
* not yet been completed.
@@ -155,12 +155,28 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
case SOCK_STREAM:
{
- int ret = uip_tcpconnect(psock->s_conn, inaddr);
+ int ret;
+
+ /* Verify that the socket is not already connected */
+
+ if (_SS_ISCONNECTED(psock->s_flags))
+ {
+ err = -EISCONN;
+ goto errout;
+ }
+
+ /* Perform the uIP connection operation */
+
+ ret = uip_tcpconnect(psock->s_conn, inaddr);
if (ret < 0)
{
err = -ret;
goto errout;
}
+
+ /* Mark the connection bound and connected */
+
+ psock->s_flags |= (_SF_BOUND|_SF_CONNECTED);
}
break;
diff --git a/nuttx/net/net-internal.h b/nuttx/net/net-internal.h
index b62099a16..f517f863d 100644
--- a/nuttx/net/net-internal.h
+++ b/nuttx/net/net-internal.h
@@ -52,6 +52,26 @@
* Definitions
****************************************************************************/
+/* Definitions of 8-bit socket flags */
+
+ /* Bits 0:2 : Socket state */
+#define _SF_IDLE 0x00 /* There is no socket activity */
+#define _SF_LISTEN 0x01 /* Socket is listening */
+#define _SF_RECV 0x02 /* Waiting for recv action to complete */
+#define _SF_SEND 0x03 /* Waiting for send action to complete */
+#define _SF_MASK 0x03 /* Mask to isolate the above actions */
+ /* Bits 3:5 : unused */
+#define _SF_BOUND 0x40 /* Bit 6: SOCK_STREAM is bound to an address */
+#define _SF_CONNECTED 0x80 /* Bit 7: SOCK_STREAM is connected */
+
+/* Macro to manage the socket state and flags */
+
+#define _SS_SETSTATE(s,f) (((s) & ~_SF_MASK) | (f))
+#define _SS_GETSTATE(s) ((s) & _SF_MASK)
+#define _SS_ISBUSY(s) (_SS_GETSTATE(s) != _SF_IDLE)
+#define _SS_ISCONNECTED(s) (((s) & _SF_CONNECTED) != 0)
+#define _SS_ISBOUND(s) (((s) & _SF_CONNECTED) != 0)
+
/* This macro converts a socket option value into a bit setting */
#define _SO_BIT(o) (1 << (o))
diff --git a/nuttx/net/recv.c b/nuttx/net/recv.c
index e03fbd495..135b6f319 100644
--- a/nuttx/net/recv.c
+++ b/nuttx/net/recv.c
@@ -69,7 +69,7 @@
*
****************************************************************************/
-ssize_t recv(int sockfd, void *buf, size_t len, int flags)
+ssize_t recv(int sockfd, FAR void *buf, size_t len, int flags)
{
return recvfrom(sockfd, buf, len, flags, NULL, 0);
}
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index 318f0d1bf..a8bc59505 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -77,6 +77,7 @@ struct recvfrom_s
void recvfrom_interrupt(void *private)
{
struct recvfrom_s *pstate = (struct recvfrom_s *)private;
+ struct uip_udp_conn *udp_conn;
size_t recvlen;
/* 'private' might be null in some race conditions (?) */
@@ -88,9 +89,9 @@ void recvfrom_interrupt(void *private)
if (uip_newdata())
{
/* Get the length of the data to return */
- if (uip_len > pstate-> rf_buflen)
+ if (uip_len > pstate->rf_buflen)
{
- recvlen = pstate-> rf_buflen;
+ recvlen = pstate->rf_buflen;
}
else
{
@@ -103,15 +104,16 @@ void recvfrom_interrupt(void *private)
/* Don't allow any further call backs. */
- uip_conn->private = NULL;
- uip_conn->callback = NULL;
+ udp_conn = (struct uip_udp_conn *)pstate->rf_sock->s_conn;
+ udp_conn->private = NULL;
+ udp_conn->callback = NULL;
/* Wake up the waiting thread, returning the number of bytes
* actually read.
*/
pstate->rf_buflen = recvlen;
- sem_post(&pstate-> rf_sem);
+ sem_post(&pstate->rf_sem);
}
/* No data has been received -- this is some other event... probably a
@@ -131,15 +133,16 @@ void recvfrom_interrupt(void *private)
{
/* Don't allow any further call backs. */
- uip_conn->private = NULL;
- uip_conn->callback = NULL;
+ udp_conn = (struct uip_udp_conn *)pstate->rf_sock->s_conn;
+ udp_conn->private = NULL;
+ udp_conn->callback = NULL;
/* Wake up the waiting thread, returning the error -EAGAIN
* that signals the timeout event
*/
pstate->rf_buflen = -EAGAIN;
- sem_post(&pstate-> rf_sem);
+ sem_post(&pstate->rf_sem);
}
}
}
@@ -148,6 +151,157 @@ void recvfrom_interrupt(void *private)
}
/****************************************************************************
+ * Function: udp_recvfrom
+ *
+ * Description:
+ * Perform the recvfrom operation for a UDP SOCK_DGRAM
+ *
+ * Parameters:
+ * psock Pointer to the socket structure for the SOCK_DRAM socket
+ * buf Buffer to receive data
+ * len Length of buffer
+ * infrom INET ddress of source
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -errno is returned (see recvfrom for list of errnos).
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_IPv6
+static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ FAR const struct sockaddr_in6 *infrom )
+#else
+static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ FAR const struct sockaddr_in *infrom )
+#endif
+{
+ struct uip_udp_conn *udp_conn;
+ struct recvfrom_s state;
+ irqstate_t save;
+ int err;
+ int ret;
+
+ /* Perform the UDP recvfrom() operation */
+
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
+
+ save = irqsave();
+ memset(&state, 0, sizeof(struct recvfrom_s));
+ (void)sem_init(&state. rf_sem, 0, 0); /* Doesn't really fail */
+ state.rf_sock = psock;
+ state.rf_buflen = len;
+ state.rf_buffer = buf;
+
+#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+ /* Set up the start time for the timeout */
+
+ state.rf_starttime = g_system_timer;
+#endif
+
+ /* Setup the UDP socket */
+
+ err = uip_udpconnect(psock->s_conn, NULL);
+ if (err < 0)
+ {
+ irqrestore(save);
+ return err;
+ }
+
+ /* Set up the callback in the connection */
+
+ udp_conn = (struct uip_udp_conn *)psock->s_conn;
+ udp_conn->private = (void*)&state;
+ udp_conn->callback = recvfrom_interrupt;
+
+ /* Wait for either the receive to complete or for an error/timeout to occur.
+ * NOTES: (1) sem_wait will also terminate if a signal is received, (2)
+ * interrupts are disabled! They will be re-enabled while the task sleeps
+ * and automatically re-enabled when the task restarts.
+ */
+
+ ret = sem_wait(&state. rf_sem);
+
+ /* Make sure that no further interrupts are processed */
+
+ udp_conn->private = NULL;
+ udp_conn->callback = NULL;
+ sem_destroy(&state. rf_sem);
+ irqrestore(save);
+
+ /* Check for a error/timeout detected by the interrupt handler. Errors are
+ * signaled by negative errno values for the rcv length
+ */
+
+ if (state.rf_buflen < 0)
+ {
+ /* Return EGAIN on a timeout */
+
+ return state.rf_buflen;
+ }
+
+ /* If sem_wait failed, then we were probably reawakened by a signal. In
+ * this case, sem_wait will have set errno appropriately.
+ */
+
+ if (ret < 0)
+ {
+ return -*get_errno_ptr();
+ }
+
+#warning "Needs to return server address"
+ return state.rf_buflen;
+}
+#endif /* CONFIG_NET_UDP */
+
+/****************************************************************************
+ * Function: tcp_recvfrom
+ *
+ * Description:
+ * Perform the recvfrom operation for a TCP/IP SOCK_STREAM
+ *
+ * Parameters:
+ * psock Pointer to the socket structure for the SOCK_DRAM socket
+ * buf Buffer to receive data
+ * len Length of buffer
+ * infrom INET ddress of source
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -errno is returned (see recvfrom for list of errnos).
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_IPv6
+static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ FAR const struct sockaddr_in6 *infrom )
+#else
+static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ FAR const struct sockaddr_in *infrom )
+#endif
+{
+ /* Verify that the SOCK_STREAM has been connected */
+
+ if (_SS_ISCONNECTED(psock->s_flags))
+ {
+ /* The SOCK_STREAM must be connect in order to recive */
+
+ return -ENOTCONN;
+ }
+
+#warning "TCP/IP recv not implemented"
+ return -ENOSYS;
+}
+
+/****************************************************************************
* Global Functions
****************************************************************************/
@@ -203,8 +357,8 @@ void recvfrom_interrupt(void *private)
*
****************************************************************************/
-ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *from,
- socklen_t *fromlen)
+ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
{
FAR struct socket *psock;
#ifdef CONFIG_NET_IPv6
@@ -212,13 +366,16 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
#else
FAR const struct sockaddr_in *infrom = (const struct sockaddr_in *)from;
#endif
-#ifdef CONFIG_NET_UDP
- struct uip_udp_conn *udp_conn;
- struct recvfrom_s state;
- irqstate_t save;
-#endif
+ ssize_t ret;
int err;
- int ret;
+
+ /* Verify that non-NULL pointers were passed */
+
+ if (!buf || !from || !fromlen)
+ {
+ err = EINVAL;
+ goto errout;
+ }
/* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
@@ -230,95 +387,52 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
goto errout;
}
- /* Perform the TCP/IP recv() operation */
+ /* Verify that a valid address has been provided */
- if (psock->s_type == SOCK_STREAM)
- {
-#warning "TCP/IP recv not implemented"
- err = ENOSYS;
+#ifdef CONFIG_NET_IPv6
+ if (from->sa_family != AF_INET6 || *fromlen < sizeof(struct sockaddr_in6))
+#else
+ if (from->sa_family != AF_INET || *fromlen < sizeof(struct sockaddr_in))
+#endif
+ {
+ err = EBADF;
goto errout;
- }
+ }
- /* Perform the UDP recvfrom() operation */
+ /* Set the socket state to receiving */
-#ifdef CONFIG_NET_UDP
- /* Initialize the state structure. This is done with interrupts
- * disabled because we don't want anything to happen until we
- * are ready.
- */
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
- save = irqsave();
- memset(&state, 0, sizeof(struct recvfrom_s));
- (void)sem_init(&state. rf_sem, 0, 0); /* Doesn't really fail */
- state. rf_buflen = len;
- state. rf_buffer = buf;
+ /* Perform the TCP/IP or UDP recv() operation */
-#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
- /* Set up the start time for the timeout */
-
- state.rf_starttime = g_system_timer;
+#ifdef CONFIG_NET_UDP
+ if (psock->s_type == SOCK_STREAM)
#endif
-
- /* Setup the UDP socket */
-
- ret = uip_udpconnect(psock->s_conn, NULL);
- if (ret < 0)
{
- irqrestore(save);
- err = -ret;
- goto errout;
+ ret = tcp_recvfrom(psock, buf, len, infrom);
}
-
- /* Set up the callback in the connection */
-
- udp_conn = (struct uip_udp_conn *)psock->s_conn;
- udp_conn->private = (void*)&state;
- udp_conn->callback = recvfrom_interrupt;
-
- /* Wait for either the read to complete: NOTES: (1) sem_wait will also
- * terminate if a signal is received, (2) interrupts are disabled! They
- * will be re-enabled while the task sleeps and automatically re-enabled
- * when the task restarts.
- */
-
- ret = sem_wait(&state. rf_sem);
-
- /* Make sure that no further interrupts are processed */
-
- uip_conn->private = NULL;
- uip_conn->callback = NULL;
- sem_destroy(&state. rf_sem);
- irqrestore(save);
-
- /* Check for a timeout. Errors are signaled by negative errno values
- * for the rcv length
- */
-
-#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
- if (state.rf_buflen < 0)
+#ifdef CONFIG_NET_UDP
+ else
{
- /* Return EGAIN on a timeout */
-
- err = -state.rf_buflen;
- goto errout;
+ ret = udp_recvfrom(psock, buf, len, infrom);
}
#endif
- /* If sem_wait failed, then we were probably reawakened by a signal. In
- * this case, sem_wait will have set errno appropriately.
- */
+ /* Set the socket state to idle */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+
+ /* Handle returned errors */
if (ret < 0)
{
- return ERROR;
+ err = -ret;
+ goto errout;
}
-#warning "Needs to return server address"
- return state.rf_buflen;
+ /* Success return */
-#else
- err = ENOSYS;
-#endif
+ return ret;
errout:
*get_errno_ptr() = err;
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index cc2b154a2..037455faf 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -42,12 +42,125 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <string.h>
#include <errno.h>
+#include <arch/irq.h>
#include "net-internal.h"
/****************************************************************************
- * Global Functions
+ * Definitions
+ ****************************************************************************/
+
+#define STATE_POLLWAIT 1
+#define STATE_DATA_SENT 2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure holds the state of the send operation until it can be
+ * operated upon from the interrupt level.
+ */
+
+struct send_s
+{
+ FAR struct socket *snd_sock; /* Points to the parent socket structure */
+ sem_t snd_sem; /* Used to wake up the waiting thread */
+ FAR const uint8 *snd_buffer; /* Points to the buffer of data to send */
+ size_t snd_buflen; /* Number of bytes in the buffer to send */
+ ssize_t snd_sent; /* The number of bytes sent */
+ uint8 snd_state; /* The state of the send operation. */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: send_Interrupt
+ *
+ * Description:
+ * This function is called from the interrupt level to perform the actual
+ * send operation when polled by the uIP layer.
+ *
+ * Parameters:
+ * private An instance of struct send_s cast to void*
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+static void send_interrupt(void *private)
+{
+ struct send_s *pstate = (struct send_s *)private;
+ struct uip_conn *conn;
+
+ /* If the data has not been sent OR if it needs to be retransmitted,
+ * then send it now.
+ */
+
+ if (pstate->snd_state != STATE_DATA_SENT || uip_rexmit())
+ {
+ if (pstate->snd_buflen > uip_mss())
+ {
+ uip_send(pstate->snd_buffer, uip_mss());
+ }
+ else
+ {
+ uip_send(pstate->snd_buffer, pstate->snd_buflen);
+ }
+
+ pstate->snd_state = STATE_DATA_SENT;
+ }
+
+ /* Check if all data has been sent and acknowledged */
+
+ else if (pstate->snd_state == STATE_DATA_SENT && uip_acked())
+ {
+ /* Yes.. the data has been sent AND acknowledge */
+
+ if (pstate->snd_buflen > uip_mss())
+ {
+ /* Not all data has been sent */
+
+ pstate->snd_sent += uip_mss();
+ pstate->snd_buflen -= uip_mss();
+ pstate->snd_buffer += uip_mss();
+
+ /* Send again on the next poll */
+
+ pstate->snd_state = STATE_POLLWAIT;
+ }
+ else
+ {
+ /* All data has been sent */
+
+ pstate->snd_sent += pstate->snd_buflen;
+ pstate->snd_buffer += pstate->snd_buflen;
+ pstate->snd_buflen = 0;
+
+ /* Don't allow any further call backs. */
+
+ conn = (struct uip_conn *)pstate->snd_sock->s_conn;
+ conn->private = NULL;
+ conn->callback = NULL;
+
+ /* Wake up the waiting thread, returning the number of bytes
+ * actually sent.
+ */
+
+ sem_post(&pstate->snd_sem);
+ }
+ }
+}
+
+/****************************************************************************
+ * Public Functions
****************************************************************************/
/****************************************************************************
@@ -57,8 +170,8 @@
* The send() call may be used only when the socket is in a connected state
* (so that the intended recipient is known). The only difference between
* send() and write() is the presence of flags. With zero flags parameter,
- * send() is equivalent to write(). Also, send(s,buf,len,flags) is
- * equivalent to sendto(s,buf,len,flags,NULL,0).
+ * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
+ * equivalent to sendto(sockfd,buf,len,flags,NULL,0).
*
* Parameters:
* sockfd Socket descriptor of socket
@@ -117,7 +230,11 @@
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
{
FAR struct socket *psock = sockfd_socket(sockfd);
+ struct uip_conn *conn;
+ struct send_s state;
+ irqstate_t save;
int err;
+ int ret;
/* Verify that the sockfd corresponds to valid, allocated socket */
@@ -129,21 +246,86 @@ ssize_t send(int sockfd, const void *buf, size_t len, int flags)
/* If this is a connected socket, then return ENOTCONN */
- if (psock->s_type != SOCK_STREAM)
+ if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
{
err = ENOTCONN;
goto errout;
}
+ /* Set the socket state to sending */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
+
/* Perform the TCP send operation */
-#warning "send() not implemented"
- err = ENOSYS;
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
+
+ save = irqsave();
+ memset(&state, 0, sizeof(struct send_s));
+ (void)sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */
+ state.snd_sock = psock;
+ state.snd_buflen = len;
+ state.snd_buffer = buf;
+ state.snd_state = STATE_POLLWAIT;
+
+ if (len > 0)
+ {
+ /* Set up the callback in the connection */
+
+ conn = (struct uip_conn *)psock->s_conn;
+ conn->private = (void*)&state;
+ conn->callback = send_interrupt;
+
+ /* Wait for the send to complete or an error to occur: NOTES: (1)
+ * sem_wait will also terminate if a signal is received, (2) interrupts
+ * are disabled! They will be re-enabled while the task sleeps and
+ * automatically re-enabled when the task restarts.
+ */
+
+ ret = sem_wait(&state. snd_sem);
+
+ /* Make sure that no further interrupts are processed */
+
+ conn->private = NULL;
+ conn->callback = NULL;
+ }
+
+ sem_destroy(&state. snd_sem);
+ irqrestore(save);
+
+ /* Set the socket state to idle */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+
+ /* Check for a errors. Errors are signaled by negative errno values
+ * for the send length
+ */
+
+ if (state.snd_sent < 0)
+ {
+ err = state.snd_sent;
+ goto errout;
+ }
+
+ /* If sem_wait failed, then we were probably reawakened by a signal. In
+ * this case, sem_wait will have set errno appropriately.
+ */
+
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout;
+ }
+
+ /* Return the number of bytes actually sent */
+
+ return state.snd_sent;
errout:
- *get_errno_ptr() = ENOSYS;
- return ERROR;
- *get_errno_ptr() = ENOSYS;
+ *get_errno_ptr() = err;
return ERROR;
}
diff --git a/nuttx/net/sendto.c b/nuttx/net/sendto.c
index eef1a31b4..bba9c5b47 100644
--- a/nuttx/net/sendto.c
+++ b/nuttx/net/sendto.c
@@ -97,7 +97,7 @@ void sendto_interrupt(void *private)
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
- * socket, the parameters to and tolen are ignored (and the error EISCONN
+ * socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
@@ -214,6 +214,10 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
/* Perform the UDP sendto operation */
#ifdef CONFIG_NET_UDP
+ /* Set the socket state to sending */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
+
/* Initialize the state structure. This is done with interrupts
* disabled because we don't want anything to happen until we
* are ready.
@@ -244,6 +248,10 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
sem_wait(&state.st_sem);
sem_destroy(&state.st_sem);
+
+ /* Set the socket state to idle */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
return len;
#else
err = ENOSYS;
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs
index 96691792d..4ad51f9bc 100644
--- a/nuttx/net/uip/Make.defs
+++ b/nuttx/net/uip/Make.defs
@@ -34,6 +34,6 @@
############################################################################
UIP_ASRCS =
-UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c \
+UIP_CSRCS = uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c \
uip-tcpconn.c uip-udpconn.c uip-wait.c
diff --git a/nuttx/net/uip/psock.c b/nuttx/net/uip/psock.c
deleted file mode 100644
index 55676c3c2..000000000
--- a/nuttx/net/uip/psock.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/****************************************************************************
- * net/uip/psock.c
- *
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * Based on uIP which also has a BSD style license:
- *
- * Copyright (c) 2004, Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <pthread.h>
-#include <debug.h>
-
-#include <net/uip/uip.h>
-#include <net/uip/uipopt.h>
-#include <net/uip/psock.h>
-
-#define STATE_NONE 0
-#define STATE_ACKED 1
-#define STATE_READ 2
-#define STATE_BLOCKED_NEWDATA 3
-#define STATE_BLOCKED_CLOSE 4
-#define STATE_BLOCKED_SEND 5
-#define STATE_DATA_SENT 6
-
-/*
- * Return value of the buffering functions that indicates that a
- * buffer was not filled by incoming data.
- *
- */
-#define BUF_NOT_FULL 0
-#define BUF_NOT_FOUND 0
-
-/*
- * Return value of the buffering functions that indicates that a
- * buffer was completely filled by incoming data.
- *
- */
-#define BUF_FULL 1
-
-/*
- * Return value of the buffering functions that indicates that an
- * end-marker byte was found.
- *
- */
-#define BUF_FOUND 2
-
-static void buf_setup(struct psock_buf *buf, uint8 *bufptr, uint16 bufsize)
-{
- buf->ptr = bufptr;
- buf->left = bufsize;
-}
-
-static uint8 buf_bufdata(struct psock_buf *buf, uint16 len, uint8 **dataptr, uint16 *datalen)
-{
- if (*datalen < buf->left)
- {
- memcpy(buf->ptr, *dataptr, *datalen);
- buf->ptr += *datalen;
- buf->left -= *datalen;
- *dataptr += *datalen;
- *datalen = 0;
- return BUF_NOT_FULL;
- }
- else if (*datalen == buf->left)
- {
- memcpy(buf->ptr, *dataptr, *datalen);
- buf->ptr += *datalen;
- buf->left = 0;
- *dataptr += *datalen;
- *datalen = 0;
- return BUF_FULL;
- }
- else
- {
- memcpy(buf->ptr, *dataptr, buf->left);
- buf->ptr += buf->left;
- *datalen -= buf->left;
- *dataptr += buf->left;
- buf->left = 0;
- return BUF_FULL;
- }
-}
-
-static uint8 buf_bufto(struct psock_buf *buf, uint8 endmarker, uint8 **dataptr, uint16 *datalen)
-{
- uint8 c;
- while(buf->left > 0 && *datalen > 0)
- {
- c = *buf->ptr = **dataptr;
- ++*dataptr;
- ++buf->ptr;
- --*datalen;
- --buf->left;
-
- if (c == endmarker)
- {
- return BUF_FOUND;
- }
- }
-
- if (*datalen == 0)
- {
- return BUF_NOT_FOUND;
- }
-
- while(*datalen > 0)
- {
- c = **dataptr;
- --*datalen;
- ++*dataptr;
-
- if (c == endmarker)
- {
- return BUF_FOUND | BUF_FULL;
- }
- }
-
- return BUF_FULL;
-}
-
-static boolean send_data(register struct psock *s)
-{
- /* Inidicate that we are blocked waiting for the send to complete */
-
- s->state = STATE_BLOCKED_SEND;
-
- /* Loop until we successfully send the data */
-
- for (;;)
- {
- /* If the data has not been sent OR if it needs to be retransmitted,
- * then send it now.
- */
-
- if (s->state != STATE_DATA_SENT || uip_rexmit())
- {
- if (s->sendlen > uip_mss())
- {
- uip_send(s->sendptr, uip_mss());
- }
- else
- {
- uip_send(s->sendptr, s->sendlen);
- }
-
- s->state = STATE_DATA_SENT;
- }
-
- /* Check if all data has been sent and acknowledged */
-
- if (s->state == STATE_DATA_SENT && uip_acked())
- {
- /* Yes.. the data has been sent AND acknowledge */
-
- if (s->sendlen > uip_mss())
- {
- s->sendlen -= uip_mss();
- s->sendptr += uip_mss();
- }
- else
- {
- s->sendptr += s->sendlen;
- s->sendlen = 0;
- }
-
- s->state = STATE_ACKED;
- return TRUE;
- }
-
- /* No.. then wait on the retransmit or acked events */
-
- (void)uip_event_wait(UIP_ACKDATA|UIP_REXMIT);
- }
-
- return FALSE; /* We never get here */
-}
-
-void psock_send(struct psock *s, const char *buf, unsigned int len)
-{
- /* If there is no data to send, we exit immediately. */
-
- if (len > 0)
- {
- /* Save the length of and a pointer to the data that is to be sent. */
-
- s->sendptr = (const uint8*)buf;
- s->sendlen = len;
- s->state = STATE_NONE;
-
- /* Loop here until all data is sent. The s->sendlen variable is updated
- * by the data_sent() function.
- */
-
- while(s->sendlen > 0) {
-
- /* Wait until the data has been sent and acknowledged */
-
- send_data(s);
- }
-
- /* Done */
-
- s->state = STATE_NONE;
- }
-}
-
-void psock_generator_send(register struct psock *s, unsigned short (*generate)(void *), void *arg)
-{
- /* Ensure that there is a generator function to call. */
-
- if (generate != NULL)
- {
- /* Call the generator function to generate the data in the uip_appdata
- * buffer.
- */
-
- s->sendlen = generate(arg);
- s->sendptr = uip_appdata;
- s->state = STATE_NONE;
-
- do
- {
- /* Call the generator function again if we are called to perform a
- * retransmission.
- */
-
- if (uip_rexmit())
- {
- generate(arg);
- }
-
- /* Wait until all data is sent and acknowledged. */
-
- send_data(s);
- }
- while(s->sendlen > 0);
-
- /* Done */
-
- s->state = STATE_NONE;
- }
-}
-
-uint16 psock_datalen(struct psock *psock)
-{
- return psock->bufsize - psock->buf.left;
-}
-
-boolean psock_checknewdata(struct psock *s)
-{
- if (s->readlen > 0)
- {
- /* There is data in the uip_appdata buffer that has not yet been read
- * with the PSOCK_READ functions.
- */
- return TRUE;
- }
- else if (s->state == STATE_READ)
- {
- /* All data in uip_appdata buffer already consumed. */
-
- s->state = STATE_BLOCKED_NEWDATA;
- return FALSE;
- }
- else if (uip_newdata())
- {
- /* There is new data that has not been consumed. */
-
- return TRUE;
- }
- else
- {
- /* There is no new data. */
-
- return FALSE;
- }
-}
-
-void psock_waitnewdata(struct psock *s)
-{
- while (!psock_checknewdata(s))
- {
- uip_event_wait(UIP_NEWDATA);
- }
-}
-
-void psock_readto(register struct psock *psock, unsigned char c)
-{
-restart:
- buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
-
- /* XXX: Should add buf_checkmarker() before do{} loop, if
- incoming data has been handled while waiting for a write. */
-
- do
- {
- if (psock->readlen == 0)
- {
- psock_waitnewdata(psock);
- psock->state = STATE_READ;
- psock->readptr = (uint8 *)uip_appdata;
- psock->readlen = uip_datalen();
- }
- }
- while((buf_bufto(&psock->buf, c, &psock->readptr, &psock->readlen) & BUF_FOUND) == 0);
-
- if (psock_datalen(psock) == 0)
- {
- psock->state = STATE_NONE;
- goto restart;
- }
-}
-
-void psock_readbuf(register struct psock *psock)
-{
-restart:
- buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
-
- /* XXX: Should add buf_checkmarker() before do{} loop, if
- incoming data has been handled while waiting for a write. */
-
- do
- {
- if (psock->readlen == 0)
- {
- psock_waitnewdata(psock);
- dbg("Waited for newdata\n");
- psock->state = STATE_READ;
- psock->readptr = (uint8 *)uip_appdata;
- psock->readlen = uip_datalen();
- }
- }
- while(buf_bufdata(&psock->buf, psock->bufsize, &psock->readptr, &psock->readlen) != BUF_FULL);
-
- if (psock_datalen(psock) == 0)
- {
- psock->state = STATE_NONE;
- goto restart;
- }
-}
-
-void psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
-{
- psock->state = STATE_NONE;
- psock->readlen = 0;
- psock->bufptr = (uint8*)buffer;
- psock->bufsize = buffersize;
- buf_setup(&psock->buf, (uint8*)buffer, buffersize);
-}
-
diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c
index 9d1380f6b..8f14dc24b 100644
--- a/nuttx/net/uip/uip-tcpconn.c
+++ b/nuttx/net/uip/uip-tcpconn.c
@@ -123,6 +123,69 @@ static struct uip_conn *uip_find_conn(uint16 portno)
}
/****************************************************************************
+ * Name: uip_selectport()
+ *
+ * Description:
+ * If the portnumber is zero; select an unused port for the connection.
+ * If the portnumber is non-zero, verify that no other connection has
+ * been created with this port number.
+ *
+ * Input Parameters:
+ * portno -- the selected port number in host order. Zero means no port
+ * selected.
+ *
+ * Return:
+ * 0 on success, -ERRNO on failure
+ *
+ * Assumptions:
+ * Interrupts are disabled
+ *
+ ****************************************************************************/
+
+static int uip_selectport(uint16 portno)
+{
+ if (portno == 0)
+ {
+ /* No local port assigned. Loop until we find a valid listen port number
+ * that is not being used by any other connection.
+ */
+
+ do
+ {
+ /* Guess that the next available port number will be the one after
+ * the last port number assigned.
+ */
+ portno = ++g_last_tcp_port;
+
+ /* Make sure that the port number is within range */
+
+ if (g_last_tcp_port >= 32000)
+ {
+ g_last_tcp_port = 4096;
+ }
+ }
+ while (uip_find_conn(g_last_tcp_port));
+ }
+ else
+ {
+ /* A port number has been supplied. Verify that no other TCP/IP
+ * connection is using this local port.
+ */
+
+ if (uip_find_conn(portno))
+ {
+ /* It is in use... return EADDRINUSE */
+
+ return -EADDRINUSE;
+ }
+ }
+
+ /* Return the selecte or verified port number */
+
+ return portno;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -422,6 +485,20 @@ int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr)
int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr)
#endif
{
+ irqstate_t flags;
+ int port;
+
+ /* Verify or select a local port */
+
+ flags = irqsave();
+ port = uip_selectport(ntohs(conn->lport));
+ irqrestore(flags);
+
+ if (port < 0)
+ {
+ return port;
+ }
+
#warning "Need to implement bind logic"
return -ENOSYS;
}
@@ -453,7 +530,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
#endif
{
irqstate_t flags;
- uint16 port;
+ int port;
/* The connection is expected to be in the UIP_ALLOCATED state.. i.e.,
* allocated via up_tcpalloc(), but not yet put into the active connections
@@ -469,29 +546,13 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
* one now.
*/
- port = ntohs(conn->lport);
- if (port == 0)
- {
- /* No local port assigned. Loop until we find a valid listen port number\
- * that is not being used by any other connection.
- */
-
- do
- {
- /* Guess that the next available port number will be the one after
- * the last port number assigned.
- */
-#warning "This need protection from other threads and from interrupts"
- port = ++g_last_tcp_port;
-
- /* Make sure that the port number is within range */
+ flags = irqsave();
+ port = uip_selectport(ntohs(conn->lport));
+ irqrestore(flags);
- if (g_last_tcp_port >= 32000)
- {
- g_last_tcp_port = 4096;
- }
- }
- while (uip_find_conn(g_last_tcp_port));
+ if (port < 0)
+ {
+ return port;
}
/* Initialize and return the connection structure, bind it to the port number */
@@ -511,7 +572,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
conn->rto = UIP_RTO;
conn->sa = 0;
conn->sv = 16; /* Initial value of the RTT variance. */
- conn->lport = htons(port);
+ conn->lport = htons((uint16)port);
/* The sockaddr port is 16 bits and already in network order */
diff --git a/nuttx/netutils/smtp/smtp.c b/nuttx/netutils/smtp/smtp.c
index 5d7a61aa6..be224590a 100644
--- a/nuttx/netutils/smtp/smtp.c
+++ b/nuttx/netutils/smtp/smtp.c
@@ -47,13 +47,14 @@
****************************************************************************/
#include <sys/types.h>
-#include <string.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <net/uip/uip.h>
-#include <net/uip/psock.h>
#include <net/uip/smtp.h>
#include "smtp-strings.h"
@@ -77,7 +78,6 @@ struct smtp_state
uint8 state;
boolean connected;
sem_t sem;
- struct psock psock;
uip_ipaddr_t smtpserver;
char *localhostname;
char *to;
@@ -89,146 +89,155 @@ struct smtp_state
int sentlen;
int textlen;
int sendptr;
- int result;
char buffer[SMTP_INPUT_BUFFER_SIZE];
};
-static volatile struct smtp_state *gpsmtp = 0;
-
-static void smtp_send_message(struct smtp_state *psmtp)
+static inline int smtp_send_message(int sockfd, struct smtp_state *psmtp)
{
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (strncmp(psmtp->buffer, smtp_220, 3) != 0)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 2;
- return;
+ return ERROR;
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_helo);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->localhostname);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_helo, psmtp->localhostname);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->buffer[0] != ISO_2)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 3;
- return;
+ return ERROR;
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_mail_from);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->from);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_mail_from, psmtp->from);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->buffer[0] != ISO_2)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 3;
- return;
+ return ERROR;
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_rcpt_to);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->to);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_rcpt_to, psmtp->to);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->buffer[0] != ISO_2)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 5;
- return;
+ return ERROR;
}
if (psmtp->cc != 0)
{
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_rcpt_to);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->cc);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_rcpt_to, psmtp->cc);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->buffer[0] != ISO_2)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 6;
- return;
+ return ERROR;
}
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_data);
+ if (send(sockfd, smtp_data, strlen(smtp_data), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->buffer[0] != ISO_3)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 7;
- return;
+ return ERROR;
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_to);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->to);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_to, psmtp->to);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
if (psmtp->cc != 0)
{
- PSOCK_SEND_STR(&psmtp->psock, (char *)psmtp->cc);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->cc);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_to, psmtp->cc);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_from);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->from);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
-
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_subject);
- PSOCK_SEND_STR(&psmtp->psock, psmtp->subject);
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
-
- psock_send(&psmtp->psock, psmtp->msg, psmtp->msglen);
-
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnlperiodcrnl);
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_from, psmtp->from);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
- psock_readto(&psmtp->psock, ISO_nl);
- if (psmtp->buffer[0] != ISO_2)
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", smtp_subject, psmtp->subject);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
{
- PSOCK_CLOSE(&psmtp->psock);
- psmtp->result = 8;
- return;
+ return ERROR;
}
- PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_quit);
- psmtp->result = 0;
-}
+ if (send(sockfd, psmtp->msg, psmtp->msglen, 0) < 0)
+ {
+ return ERROR;
+ }
-/* This function is called by the UIP interrupt handling logic whenevent an
- * event of interest occurs.
- */
+ if (send(sockfd, smtp_crnlperiodcrnl, strlen(smtp_crnlperiodcrnl), 0) < 0)
+ {
+ return ERROR;
+ }
-void uip_interrupt_event(void)
-{
-#warning OBSOLETE -- needs to be redesigned
- if (gpsmtp)
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
{
- if (uip_closed())
- {
- gpsmtp->connected = FALSE;
- return;
- }
+ return ERROR;
+ }
- if (uip_aborted() || uip_timedout())
- {
- gpsmtp->connected = FALSE;
- }
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
- sem_post((sem_t*)&gpsmtp->sem);
+ if (send(sockfd, smtp_quit, strlen(smtp_quit), 0) < 0)
+ {
+ return ERROR;
}
+ return OK;
}
/* Specificy an SMTP server and hostname.
@@ -264,6 +273,7 @@ int smtp_send(void *handle, char *to, char *cc, char *from, char *subject, char
struct smtp_state *psmtp = (struct smtp_state *)handle;
struct sockaddr_in server;
int sockfd;
+ int ret;
/* Setup */
@@ -274,7 +284,6 @@ int smtp_send(void *handle, char *to, char *cc, char *from, char *subject, char
psmtp->subject = subject;
psmtp->msg = msg;
psmtp->msglen = msglen;
- psmtp->result = OK;
/* Create a socket */
@@ -284,12 +293,6 @@ int smtp_send(void *handle, char *to, char *cc, char *from, char *subject, char
return ERROR;
}
- /* Make this instance globally visible (we will get interrupts as
- * soon as we connect
- */
-
- gpsmtp = psmtp;
-
/* Connect to server. First we have to set some fields in the
* 'server' structure. The system will assign me an arbitrary
* local port that is not in use.
@@ -301,27 +304,16 @@ int smtp_send(void *handle, char *to, char *cc, char *from, char *subject, char
if (connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0)
{
+ close(sockfd);
return ERROR;
- }
-
- /* Initialize the psock structure inside the smtp state structure */
-
- psock_init(&psmtp->psock, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE);
-
- /* And wait for the the socket to be connected */
-
- sem_wait(&psmtp->sem);
- gpsmtp = 0;
+ }
- /* Was an error reported by interrupt handler? */
+ /* Send the message */
- if (psmtp->result == OK )
- {
- /* No... Send the message */
- smtp_send_message(psmtp);
- }
+ ret = smtp_send_message(sockfd, psmtp);
- return psmtp->result;
+ close(sockfd);
+ return ret;
}
void *smtp_open(void)
diff --git a/nuttx/netutils/webserver/httpd-cgi.c b/nuttx/netutils/webserver/httpd-cgi.c
index 2b68040a2..9870961e6 100644
--- a/nuttx/netutils/webserver/httpd-cgi.c
+++ b/nuttx/netutils/webserver/httpd-cgi.c
@@ -30,15 +30,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+
#include <net/uip/uip.h>
-#include <net/uip/psock.h>
#include <net/uip/httpd.h>
#include "httpd-cgi.h"
-#include <stdio.h>
-#include <string.h>
-
#define CONFIG_HTTPDCGI_FILESTATS 1
#undef CONFIG_HTTPDCGI_DCPSTATS
#define CONFIG_HTTPDCGI_NETSTATS 1
@@ -101,7 +101,7 @@ static const char *states[] =
};
#endif
-static void nullfunction(struct httpd_state *s, char *ptr)
+static void nullfunction(struct httpd_state *pstate, char *ptr)
{
}
@@ -120,66 +120,57 @@ httpd_cgifunction httpd_cgi(char *name)
}
#ifdef CONFIG_HTTPDCGI_FILESTATS
-static unsigned short generate_file_stats(void *arg)
+static void file_stats(struct httpd_state *pstate, char *ptr)
{
- char *f = (char *)arg;
- return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f));
-}
-
-static void file_stats(struct httpd_state *s, char *ptr)
-{
- psock_generator_send(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1);
+ char buffer[16];
+ char *pcount = strchr(ptr, ' ') + 1;
+ snprintf(buffer, 16, "%5u", httpd_fs_count(pcount));
+ (void)send(pstate->sockout, buffer, strlen(buffer), 0);
}
#endif
#if CONFIG_HTTPDCGI_TCPSTATS
-static unsigned short generate_tcp_stats(void *arg)
+static void tcp_stats(struct httpd_state *pstate, char *ptr)
{
struct uip_conn *conn;
- struct httpd_state *s = (struct httpd_state *)arg;
-
- conn = &uip_conns[s->count];
- return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
- "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n",
- htons(conn->lport),
- htons(conn->ripaddr[0]) >> 8,
- htons(conn->ripaddr[0]) & 0xff,
- htons(conn->ripaddr[1]) >> 8,
- htons(conn->ripaddr[1]) & 0xff,
- htons(conn->rport),
- states[conn->tcpstateflags & UIP_TS_MASK],
- conn->nrtx,
- conn->timer,
- (uip_outstanding(conn))? '*':' ',
- (uip_stopped(conn))? '!':' ');
-}
+ struct httpd_state *pstate = (struct httpd_state *)arg;
+ char buffer[256];
-static void tcp_stats(struct httpd_state *s, char *ptr)
-{
- for(s->count = 0; s->count < UIP_CONNS; ++s->count)
+ for(pstate->count = 0; pstate->count < UIP_CONNS; ++pstate->count)
{
- if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
+ conn = &uip_conns[pstate->count];
+ if((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
{
- psock_generator_send(&s->sout, generate_tcp_stats, s);
+ snprintf(buffer, 25t,
+ "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n",
+ htons(conn->lport),
+ htons(conn->ripaddr[0]) >> 8,
+ htons(conn->ripaddr[0]) & 0xff,
+ htons(conn->ripaddr[1]) >> 8,
+ htons(conn->ripaddr[1]) & 0xff,
+ htons(conn->rport),
+ states[conn->tcpstateflags & UIP_TS_MASK],
+ conn->nrtx,
+ conn->timer,
+ (uip_outstanding(conn))? '*':' ',
+ (uip_stopped(conn))? '!':' ');
+
+ (void)send(pstate->sockout, buffer, strlen(buffer), 0);
}
}
}
#endif
#ifdef CONFIG_HTTPDCGI_NETSTATS
-static unsigned short generate_net_stats(void *arg)
-{
- struct httpd_state *s = (struct httpd_state *)arg;
- return snprintf((char*)uip_appdata, UIP_APPDATA_SIZE,
- "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]);
-}
-
-static void net_stats(struct httpd_state *s, char *ptr)
+static void net_stats(struct httpd_state *pstate, char *ptr)
{
#if UIP_STATISTICS
- for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); ++s->count)
+ char buffer[16];
+
+ for(pstate->count = 0; pstate->count < sizeof(uip_stat) / sizeof(uip_stats_t); ++pstate->count)
{
- psock_generator_send(&s->sout, generate_net_stats, s);
+ snprintf(buffer, 16, "%5u\n", ((uip_stats_t *)&uip_stat)[pstate->count]);
+ send(pstate->sockout, buffer, strlen(buffer), 0);
}
#endif /* UIP_STATISTICS */
}
diff --git a/nuttx/netutils/webserver/httpd-cgi.h b/nuttx/netutils/webserver/httpd-cgi.h
index bd22feb85..7243b19f2 100644
--- a/nuttx/netutils/webserver/httpd-cgi.h
+++ b/nuttx/netutils/webserver/httpd-cgi.h
@@ -33,9 +33,10 @@
#ifndef __HTTPD_CGI_H__
#define __HTTPD_CGI_H__
-#include <net/uip/psock.h>
#include <net/uip/httpd.h>
+#include "httpd.h"
+
typedef void (* httpd_cgifunction)(struct httpd_state *, char *);
httpd_cgifunction httpd_cgi(char *name);
diff --git a/nuttx/netutils/webserver/httpd-fs.c b/nuttx/netutils/webserver/httpd-fs.c
index 3b446ac43..d3fe35171 100644
--- a/nuttx/netutils/webserver/httpd-fs.c
+++ b/nuttx/netutils/webserver/httpd-fs.c
@@ -45,6 +45,7 @@
#include <net/uip/httpd.h>
+#include "httpd.h"
#include "httpd-fsdata.h"
#ifndef NULL
diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c
index 6cf50962f..4f18a72df 100644
--- a/nuttx/netutils/webserver/httpd.c
+++ b/nuttx/netutils/webserver/httpd.c
@@ -35,9 +35,12 @@
*/
#include <stdlib.h>
+#include <sys/socket.h>
+
#include <net/uip/uip.h>
#include <net/uip/httpd.h>
+#include "httpd.h"
#include "httpd-cgi.h"
#include "http-strings.h"
@@ -54,244 +57,208 @@
#define ISO_slash 0x2f
#define ISO_colon 0x3a
-static unsigned short generate_part_of_file(void *state)
-{
- struct httpd_state *s = (struct httpd_state *)state;
-
- if (s->file.len > uip_mss()) {
- s->len = uip_mss();
- } else {
- s->len = s->file.len;
- }
- memcpy(uip_appdata, s->file.data, s->len);
-
- return s->len;
-}
+#define SEND_STR(psock, str) psock_send(psock, str, strlen(str))
-static void send_file(struct httpd_state *s)
+static inline int send_file(struct httpd_state *pstate)
{
- do {
- psock_generator_send(&s->sout, generate_part_of_file, s);
- s->file.len -= s->len;
- s->file.data += s->len;
- } while(s->file.len > 0);
-#warning REVISIT must not return until file sent
+ return send(pstate->sockout, pstate->file.data, pstate->file.len, 0);
}
-static void send_part_of_file(struct httpd_state *s)
+static inline int send_part_of_file(struct httpd_state *pstate)
{
- psock_send(&s->sout, s->file.data, s->len);
-#warning REVISIT must not return until file sent
+ return send(pstate->sockout, pstate->file.data, pstate->len, 0);
}
-static void next_scriptstate(struct httpd_state *s)
+static void next_scriptstate(struct httpd_state *pstate)
{
char *p;
- p = strchr(s->scriptptr, ISO_nl) + 1;
- s->scriptlen -= (unsigned short)(p - s->scriptptr);
- s->scriptptr = p;
+ p = strchr(pstate->scriptptr, ISO_nl) + 1;
+ pstate->scriptlen -= (unsigned short)(p - pstate->scriptptr);
+ pstate->scriptptr = p;
}
-static void handle_script(struct httpd_state *s)
+static void handle_script(struct httpd_state *pstate)
{
char *ptr;
-
- while(s->file.len > 0) {
+
+ while(pstate->file.len > 0) {
/* Check if we should start executing a script. */
- if (*s->file.data == ISO_percent &&
- *(s->file.data + 1) == ISO_bang) {
- s->scriptptr = s->file.data + 3;
- s->scriptlen = s->file.len - 3;
- if (*(s->scriptptr - 1) == ISO_colon) {
- httpd_fs_open(s->scriptptr + 1, &s->file);
- send_file(s);
+ if (*pstate->file.data == ISO_percent &&
+ *(pstate->file.data + 1) == ISO_bang) {
+ pstate->scriptptr = pstate->file.data + 3;
+ pstate->scriptlen = pstate->file.len - 3;
+ if (*(pstate->scriptptr - 1) == ISO_colon) {
+ httpd_fs_open(pstate->scriptptr + 1, &pstate->file);
+ send_file(pstate);
} else {
- httpd_cgi(s->scriptptr)(s, s->scriptptr);
+ httpd_cgi(pstate->scriptptr)(pstate, pstate->scriptptr);
}
- next_scriptstate(s);
+ next_scriptstate(pstate);
/* The script is over, so we reset the pointers and continue
sending the rest of the file. */
- s->file.data = s->scriptptr;
- s->file.len = s->scriptlen;
+ pstate->file.data = pstate->scriptptr;
+ pstate->file.len = pstate->scriptlen;
} else {
/* See if we find the start of script marker in the block of HTML
to be sent. */
- if (s->file.len > uip_mss()) {
- s->len = uip_mss();
+ if (pstate->file.len > uip_mss()) {
+ pstate->len = uip_mss();
} else {
- s->len = s->file.len;
+ pstate->len = pstate->file.len;
}
- if (*s->file.data == ISO_percent) {
- ptr = strchr(s->file.data + 1, ISO_percent);
+ if (*pstate->file.data == ISO_percent) {
+ ptr = strchr(pstate->file.data + 1, ISO_percent);
} else {
- ptr = strchr(s->file.data, ISO_percent);
+ ptr = strchr(pstate->file.data, ISO_percent);
}
if (ptr != NULL &&
- ptr != s->file.data) {
- s->len = (int)(ptr - s->file.data);
- if (s->len >= uip_mss()) {
- s->len = uip_mss();
+ ptr != pstate->file.data) {
+ pstate->len = (int)(ptr - pstate->file.data);
+ if (pstate->len >= uip_mss()) {
+ pstate->len = uip_mss();
}
}
- send_part_of_file(s);
- s->file.data += s->len;
- s->file.len -= s->len;
+ send_part_of_file(pstate);
+ pstate->file.data += pstate->len;
+ pstate->file.len -= pstate->len;
}
}
-#warning REVISIT must not return until sent
}
-static void send_headers(struct httpd_state *s, const char *statushdr)
+static int send_headers(struct httpd_state *pstate, const char *statushdr)
{
char *ptr;
+ int ret;
- PSOCK_SEND_STR(&s->sout, statushdr);
-
- ptr = strrchr(s->filename, ISO_period);
- if (ptr == NULL) {
- PSOCK_SEND_STR(&s->sout, http_content_type_binary);
- } else if (strncmp(http_html, ptr, 5) == 0 ||
- strncmp(http_shtml, ptr, 6) == 0) {
- PSOCK_SEND_STR(&s->sout, http_content_type_html);
- } else if (strncmp(http_css, ptr, 4) == 0) {
- PSOCK_SEND_STR(&s->sout, http_content_type_css);
- } else if (strncmp(http_png, ptr, 4) == 0) {
- PSOCK_SEND_STR(&s->sout, http_content_type_png);
- } else if (strncmp(http_gif, ptr, 4) == 0) {
- PSOCK_SEND_STR(&s->sout, http_content_type_gif);
- } else if (strncmp(http_jpg, ptr, 4) == 0) {
- PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
- } else {
- PSOCK_SEND_STR(&s->sout, http_content_type_plain);
- }
-#warning REVISIT must not return until sent
+ ret = send(pstate->sockout, statushdr, strlen(statushdr), 0);
+
+ ptr = strrchr(pstate->filename, ISO_period);
+ if (ptr == NULL)
+ {
+ ret = send(pstate->sockout, http_content_type_binary, strlen(http_content_type_binary), 0);
+ }
+ else if (strncmp(http_html, ptr, 5) == 0 || strncmp(http_shtml, ptr, 6) == 0)
+ {
+ ret = send(pstate->sockout, http_content_type_html, strlen(http_content_type_html), 0);
+ }
+ else if (strncmp(http_css, ptr, 4) == 0)
+ {
+ ret = send(pstate->sockout, http_content_type_css, strlen(http_content_type_css), 0);
+ }
+ else if (strncmp(http_png, ptr, 4) == 0)
+ {
+ ret = send(pstate->sockout, http_content_type_png, strlen(http_content_type_png), 0);
+ }
+ else if (strncmp(http_gif, ptr, 4) == 0)
+ {
+ ret = send(pstate->sockout, http_content_type_gif, strlen(http_content_type_gif), 0);
+ }
+ else if (strncmp(http_jpg, ptr, 4) == 0)
+ {
+ ret = send(pstate->sockout, http_content_type_jpg, strlen(http_content_type_jpg), 0);
+ }
+ else
+ {
+ ret = send(pstate->sockout, http_content_type_plain, strlen(http_content_type_plain), 0);
+ }
+ return ret;
}
-static void handle_output(struct httpd_state *s)
+static void handle_output(struct httpd_state *pstate)
{
char *ptr;
- if (!httpd_fs_open(s->filename, &s->file))
+ if (!httpd_fs_open(pstate->filename, &pstate->file))
{
- httpd_fs_open(http_404_html, &s->file);
- strcpy(s->filename, http_404_html);
- send_headers(s, http_header_404);
- send_file(s);
+ httpd_fs_open(http_404_html, &pstate->file);
+ strcpy(pstate->filename, http_404_html);
+ send_headers(pstate, http_header_404);
+ send_file(pstate);
}
else
{
- send_headers(s, http_header_200);
- ptr = strchr(s->filename, ISO_period);
+ send_headers(pstate, http_header_200);
+ ptr = strchr(pstate->filename, ISO_period);
if (ptr != NULL && strncmp(ptr, http_shtml, 6) == 0)
{
- handle_script(s);
+ handle_script(pstate);
}
else
{
- send_file(s);
+ send_file(pstate);
}
}
- PSOCK_CLOSE(&s->sout);
}
-static void handle_input(struct httpd_state *s)
+static int handle_input(struct httpd_state *pstate)
{
- psock_readto(&s->sin, ISO_space);
+ ssize_t recvlen;
+
+ if (recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
- if (strncmp(s->inputbuf, http_get, 4) != 0)
+ if (strncmp(pstate->inputbuf, http_get, 4) != 0)
{
- PSOCK_CLOSE(&s->sin);
- return;
+ return ERROR;
}
- psock_readto(&s->sin, ISO_space);
+ recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
+ if (recvlen < 0)
+ {
+ return ERROR;
+ }
- if (s->inputbuf[0] != ISO_slash)
+ if (pstate->inputbuf[0] != ISO_slash)
{
- PSOCK_CLOSE(&s->sin);
- return;
+ return ERROR;
}
- if (s->inputbuf[1] == ISO_space)
+ if (pstate->inputbuf[1] == ISO_space)
{
- strncpy(s->filename, http_index_html, sizeof(s->filename));
+ strncpy(pstate->filename, http_index_html, sizeof(pstate->filename));
}
else
{
- s->inputbuf[psock_datalen(&s->sin) - 1] = 0;
- strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
+ pstate->inputbuf[recvlen - 1] = 0;
+ strncpy(pstate->filename, &pstate->inputbuf[0], sizeof(pstate->filename));
}
- s->state = STATE_OUTPUT;
+ pstate->state = STATE_OUTPUT;
while(1)
{
- psock_readto(&s->sin, ISO_nl);
+ recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
+ if (recvlen < 0)
+ {
+ return ERROR;
+ }
- if (strncmp(s->inputbuf, http_referer, 8) == 0)
+ if (strncmp(pstate->inputbuf, http_referer, 8) == 0)
{
- s->inputbuf[psock_datalen(&s->sin) - 2] = 0;
+ pstate->inputbuf[recvlen - 2] = 0;
}
}
+
+ return OK;
}
-static void handle_connection(struct httpd_state *s)
+static void handle_connection(struct httpd_state *pstate)
{
- handle_input(s);
- if (s->state == STATE_OUTPUT) {
- handle_output(s);
+ handle_input(pstate);
+ if (pstate->state == STATE_OUTPUT) {
+ handle_output(pstate);
}
}
-/* This function is called by the UIP interrupt handling logic whenevent an
- * event of interest occurs.
- */
-
-void uip_interrupt_event(void)
+void httpd_listen(void)
{
-#warning OBSOLETE -- needs to be redesigned
- /* Get the private application specific data */
- struct httpd_state *s = (struct httpd_state *)(uip_conn->private);
-
- /* Has application specific data been allocate yet? */
-
- if (!s)
- {
- /* No.. allocate it now */
- s = (struct httpd_state *)malloc(sizeof(struct httpd_state));
- if (!s)
- {
- return;
- }
-
- /* And assign the private instance to the connection */
- uip_conn->private = s;
- }
-
- if (uip_closed() || uip_aborted() || uip_timedout()) {
- } else if (uip_connected()) {
- psock_init(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
- psock_init(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
- s->state = STATE_WAITING;
- s->timer = 0;
- handle_connection(s);
- } else if (s != NULL) {
- if (uip_poll()) {
- ++s->timer;
- if (s->timer >= 20) {
- uip_abort();
- }
- } else {
- s->timer = 0;
- }
- handle_connection(s);
- } else {
- uip_abort();
- }
+#warning "this is all very broken at the moment"
}
/* Initialize the web server
diff --git a/nuttx/netutils/webserver/httpd.h b/nuttx/netutils/webserver/httpd.h
new file mode 100644
index 000000000..b256c1dd1
--- /dev/null
+++ b/nuttx/netutils/webserver/httpd.h
@@ -0,0 +1,74 @@
+/* httpd.h
+ *
+ * Copyright (c) 2001-2005, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NETUTILS_WEBSERVER_HTTPD_H
+#define _NETUTILS_WEBSERVER_HTTPD_H
+
+#include <sys/types.h>
+
+#define HTTPD_FS_STATISTICS 1
+#define HTTPD_INBUFFER_SIZE 50
+
+struct httpd_fs_file
+{
+ char *data;
+ int len;
+};
+
+struct httpd_state
+{
+ unsigned char timer;
+ int sockin;
+ int sockout;
+ char inputbuf[HTTPD_INBUFFER_SIZE];
+ char filename[20];
+ char state;
+ struct httpd_fs_file file;
+ int len;
+ char *scriptptr;
+ int scriptlen;
+
+ unsigned short count;
+};
+
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+extern uint16 httpd_fs_count(char *name);
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+
+/* file must be allocated by caller and will be filled in
+ * by the function.
+ */
+
+int httpd_fs_open(const char *name, struct httpd_fs_file *file);
+void httpd_fs_init(void);
+
+#endif /* _NETUTILS_WEBSERVER_HTTPD_H */