diff --git a/include/net/uip/httpd.h b/include/net/uip/httpd.h index ff99ddb364..ef21cc6ba9 100644 --- a/include/net/uip/httpd.h +++ b/include/net/uip/httpd.h @@ -34,6 +34,6 @@ #include extern void httpd_init(void); -extern void httpd_listen(void); +extern int httpd_listen(void); #endif /* _NET_UIP_HTTPD_H */ diff --git a/include/net/uip/uip.h b/include/net/uip/uip.h index ed511f92ea..fae05836c3 100644 --- a/include/net/uip/uip.h +++ b/include/net/uip/uip.h @@ -159,32 +159,30 @@ typedef uip_ip4addr_t uip_ipaddr_t; * file pointers) for the connection. */ -struct uip_driver_s; /* Forward reference */ +struct uip_driver_s; /* Forward reference */ struct uip_conn { dq_entry_t node; /* Implements a doubly linked list */ uip_ipaddr_t ripaddr; /* The IP address of the remote host. */ uint16 lport; /* The local TCP port, in network byte order. */ - uint16 rport; /* The local remote TCP port, in network byte - order. */ + uint16 rport; /* The local remote TCP port, in network byte order. */ uint8 rcv_nxt[4]; /* The sequence number that we expect to - receive next. */ - uint8 snd_nxt[4]; /* The sequence number that was last sent by - us. */ + * receive next. */ + uint8 snd_nxt[4]; /* The sequence number that was last sent by us. */ uint16 len; /* Length of the data that was previously sent. */ uint16 mss; /* Current maximum segment size for the - connection. */ + * connection. */ uint16 initialmss; /* Initial maximum segment size for the - connection. */ + * connection. */ uint8 sa; /* Retransmission time-out calculation state - variable. */ + * variable. */ uint8 sv; /* Retransmission time-out calculation state - variable. */ + * variable. */ uint8 rto; /* Retransmission time-out. */ uint8 tcpstateflags; /* TCP state and flags. */ uint8 timer; /* The retransmission timer. */ uint8 nrtx; /* The number of retransmissions for the last - segment sent. */ + * segment sent. */ /* Higher level logic can retain application specific information * in the following: @@ -192,6 +190,8 @@ struct uip_conn void *data_private; void (*data_event)(struct uip_driver_s *dev, void *private); + void *accept_private; + int (*accept)(void *private, struct uip_conn *conn); void *connection_private; void (*connection_event)(void *private); }; @@ -564,7 +564,7 @@ extern int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr) * port A 16-bit port number in network byte order. */ -void uip_listen(uint16 port); +int uip_listen(uint16 port); /* Stop listening to the specified port. * @@ -574,7 +574,7 @@ void uip_listen(uint16 port); * port A 16-bit port number in network byte order. */ -void uip_unlisten(uint16 port); +int uip_unlisten(uint16 port); /* Check if a connection has outstanding (i.e., unacknowledged) data. * diff --git a/net/accept.c b/net/accept.c index c54b49d370..66c05e989a 100644 --- a/net/accept.c +++ b/net/accept.c @@ -42,12 +42,72 @@ #include #include +#include +#include #include +#include #include "net-internal.h" /**************************************************************************** - * Global Functions + * Private Types + ****************************************************************************/ + +struct accept_s +{ + sem_t acpt_sem; /* Wait for interrupt event */ +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *acpt_addr; /* Return connection adress */ +#else + FAR const struct sockaddr_in *acpt_addr; /* Return connection adress */ +#endif + FAR struct uip_conn *acpt_listenconn; /* The listener connection */ + FAR struct uip_conn *acpt_newconn; /* The accepted connection */ + int acpt_result; /* The result of the wait */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: accept_interrupt + * + * Description: + * Receive interrupt level callbacks when connections occur + * + ****************************************************************************/ + +static int accept_interrupt(void *private, struct uip_conn *conn) +{ + struct accept_s *pstate = (struct accept_s *)private; + int ret = -EINVAL; + if (pstate) + { + /* Get the connection address */ +#warning "need to return the address of the connection" + + /* Save the connection structure */ + + pstate->acpt_newconn = conn; + pstate->acpt_result = OK; + sem_post(&pstate->acpt_sem); + + /* Stop any further callbacks */ + + pstate->acpt_listenconn->accept_private = NULL; + pstate->acpt_listenconn->accept = NULL; + ret = OK; + } + return ret; +} + +/**************************************************************************** + * Public Functions ****************************************************************************/ /**************************************************************************** @@ -122,7 +182,160 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - *get_errno_ptr() = ENOSYS; + FAR struct socket *psock = sockfd_socket(sockfd); + FAR struct socket *pnewsock; + FAR struct uip_conn *conn; + struct accept_s state; +#ifdef CONFIG_NET_IPv6 + FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; +#else + FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; +#endif + irqstate_t save; + int newfd; + int err; + int ret; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + /* It is not a valid socket description. Distinguish between the cases + * where sockfd is a just valid and when it is a valid file descriptor used + * in the wrong context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + { + err = ENOTSOCK; + } + else +#endif + { + err = EBADF; + } + goto errout; + } + + /* We have a socket descriptor, but it is a stream? */ + + if (psock->s_type != SOCK_STREAM) + { + err = EOPNOTSUPP; + goto errout; + } + + /* Is the socket listening for a connection? */ + + if (!_SS_ISLISTENING(psock->s_flags)) + { + err = EINVAL; + goto errout; + } + + /* Verify that a valid memory block has been provided to receive the address address */ + +#ifdef CONFIG_NET_IPv6 + if (addr->sa_family != AF_INET6 || *addrlen < sizeof(struct sockaddr_in6)) +#else + if (addr->sa_family != AF_INET || *addrlen < sizeof(struct sockaddr_in)) +#endif + { + err = EBADF; + goto errout; + } + + /* Allocate a socket descriptor for the new connection now (so that it cannot fail later) */ + + newfd = sockfd_allocate(); + if (newfd < 0) + { + err = ENFILE; + goto errout; + } + + pnewsock = sockfd_socket(newfd); + if (newfd) + { + err = ENFILE; + goto errout_with_socket; + } + + /* Set the socket state to accepting */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); + + /* Perform the TCP accept 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(); + state.acpt_addr = inaddr; + state.acpt_listenconn = psock->s_conn; + state.acpt_newconn = NULL; + state.acpt_result = OK; + + /* Set up the callback in the connection */ + + conn = (struct uip_conn *)psock->s_conn; + conn->accept_private = (void*)&state; + conn->accept = accept_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. acpt_sem); + + /* Make sure that no further interrupts are processed */ + + conn->accept_private = NULL; + conn->accept = NULL; + + sem_destroy(&state. acpt_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.acpt_result != 0) + { + err = state.acpt_result; + goto errout_with_socket; + } + + /* 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_with_socket; + } + + /* Initialize the socket structure */ + + pnewsock->s_type = SOCK_STREAM; + pnewsock->s_conn = state.acpt_newconn; + return newfd; + +errout_with_socket: + sockfd_release(newfd); + +errout: + *get_errno_ptr() = err; return ERROR; } diff --git a/net/listen.c b/net/listen.c index 30dcb778b4..08f9d851a7 100644 --- a/net/listen.c +++ b/net/listen.c @@ -56,7 +56,7 @@ * Description: * To accept connections, a socket is first created with socket(), a * willingness to accept incoming connections and a queue limit for incoming - * connections are specified with listen, and then the connections are + * connections are specified with listen(), and then the connections are * accepted with accept(). The listen() call applies only to sockets of * type SOCK_STREAM or SOCK_SEQPACKET. * @@ -87,7 +87,51 @@ int listen(int sockfd, int backlog) { - *get_errno_ptr() = ENOSYS; + FAR struct socket *psock = sockfd_socket(sockfd); + struct uip_conn *conn; + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + /* It is not a valid socket description. Distinguish between the cases + * where sockfd is a just valid and when it is a valid file descriptor used + * in the wrong context. + */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + { + err = ENOTSOCK; + } + else +#endif + { + err = EBADF; + } + goto errout; + } + + /* Verify that the sockfd corresponds to a connected SOCK_STREAM */ + + conn = (struct uip_conn *)psock->s_conn; + if (psock->s_type != SOCK_STREAM || !psock->s_conn || conn->lport <= 0) + { + err = EOPNOTSUPP; + goto errout; + } + + /* Start listening to the bound port. This enables callbacks when accept() + * is called; and someday should enable post() or select() logic. + */ + + uip_listen(conn->lport); + psock->s_flags |= _SF_LISTENING; + return OK; + +errout: + *get_errno_ptr() = err; return ERROR; } diff --git a/net/net-internal.h b/net/net-internal.h index eca4ec5ccd..af587d970b 100644 --- a/net/net-internal.h +++ b/net/net-internal.h @@ -56,11 +56,12 @@ /* Bits 0:2 : Socket state */ #define _SF_IDLE 0x00 /* There is no socket activity */ -#define _SF_LISTEN 0x01 /* Socket is listening */ +#define _SF_ACCEPT 0x01 /* Socket is waiting to accept a connection */ #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 */ + /* Bits 3:4 : unused */ +#define _SF_LISTENING 0x20 /* Bit 5: SOCK_STREAM is listening */ #define _SF_BOUND 0x40 /* Bit 6: SOCK_STREAM is bound to an address */ #define _SF_CONNECTED 0x80 /* Bit 7: SOCK_STREAM is connected */ @@ -69,8 +70,9 @@ #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_ISLISTENING(s) (((s) & _SF_LISTENING) != 0) #define _SS_ISBOUND(s) (((s) & _SF_CONNECTED) != 0) +#define _SS_ISCONNECTED(s) (((s) & _SF_CONNECTED) != 0) /* This macro converts a socket option value into a bit setting */ diff --git a/net/uip/Make.defs b/net/uip/Make.defs index fd20143ff0..61f89cc7b0 100644 --- a/net/uip/Make.defs +++ b/net/uip/Make.defs @@ -35,5 +35,5 @@ UIP_ASRCS = UIP_CSRCS = uip-arp.c uip.c uip-send.c uip-fw.c uip-neighbor.c uip-split.c \ - uip-tcpconn.c uip-udpconn.c + uip-tcpconn.c uip-udpconn.c uip-listen.c diff --git a/net/uip/uip-internal.h b/net/uip/uip-internal.h index f8613c63a0..6c76f39cf1 100644 --- a/net/uip/uip-internal.h +++ b/net/uip/uip-internal.h @@ -44,6 +44,9 @@ ****************************************************************************/ #include +#include +#include +#include /**************************************************************************** * Public Macro Definitions @@ -75,7 +78,8 @@ extern "C" { EXTERN void uip_tcpinit(void); EXTERN struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf); -EXTERN struct uip_conn *uip_tcplistener(struct uip_tcpip_hdr *buf); +EXTERN struct uip_conn *uip_tcplistener(uint16 portno); +EXTERN struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf); EXTERN void uip_tcpnextsequence(void); /* Defined in uip_udpconn.c *************************************************/ @@ -83,6 +87,12 @@ EXTERN void uip_tcpnextsequence(void); EXTERN void uip_udpinit(void); EXTERN struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf); +/* Defined in uip_listen.c **************************************************/ + +EXTERN void uip_listeninit(void); +EXTERN boolean uip_islistener(uint16 port); +EXTERN int uip_accept(struct uip_conn *conn, uint16 portno); + #undef EXTERN #ifdef __cplusplus } diff --git a/net/uip/uip-listen.c b/net/uip/uip-listen.c new file mode 100644 index 0000000000..edbb9d469d --- /dev/null +++ b/net/uip/uip-listen.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * net/uip/uip-listen.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * A direct leverage of logic from uIP which also has b BSD style license + * + * Author: Adam Dunkels + * Copyright (c) 2001-2003, 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifdef CONFIG_NET + +#include +#include + +#include "uip-internal.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The uip_listenports list all currently listening ports. */ + +static uint16 uip_listenports[UIP_LISTENPORTS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: uip_listeninit + * + * Description: + * Setup the listening data structures + * + * Assumptions: + * Called early in the inialization phase while the system is still + * single-threaded. + * + ****************************************************************************/ + +void uip_listeninit(void) +{ + int ndx; + for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++) + { + uip_listenports[ndx] = 0; + } +} + +/**************************************************************************** + * Function: uip_unlisten + * + * Description: + * Stop listening on a port + * + * Assumptions: + * Called from normal user code. + * + ****************************************************************************/ + +int uip_unlisten(uint16 port) +{ + irqstate_t flags; + int ndx; + int ret = -EINVAL; + + flags = irqsave(); + for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++) + { + if (uip_listenports[ndx] == port) + { + uip_listenports[ndx] = 0; + ret = OK; + break; + } + } + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Function: uip_listen + * + * Description: + * Start listening on a port + * + * Assumptions: + * Called from normal user code. + * + ****************************************************************************/ + +int uip_listen(uint16 port) +{ + irqstate_t flags; + int ndx; + int ret = -ENOBUFS; + + flags = irqsave(); + for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++) + { + if (uip_listenports[ndx] == 0) + { + uip_listenports[ndx] = port; + ret = OK; + break; + } + } + irqrestore(flags); + return ret; +} + +/**************************************************************************** + * Function: uip_islistener + * + * Description: + * Return TRUE is there is a listener for the specified port + * + * Assumptions: + * Called at interrupt level + * + ****************************************************************************/ + +boolean uip_islistener(uint16 portno) +{ + int ndx; + for (ndx = 0; ndx < UIP_LISTENPORTS; ndx++) + { + if (uip_listenports[ndx] == portno) + { + return TRUE; + } + } + return FALSE; +} + +/**************************************************************************** + * Function: uip_accept + * + * Description: + * Accept the new connection for the specified listening port. + * + * Assumptions: + * Called at interrupt level + * + ****************************************************************************/ + +int uip_accept(struct uip_conn *conn, uint16 portno) +{ + struct uip_conn *listener; + int ret = ERROR; + + /* The interrupt logic has already allocated and initialized a TCP + * connection -- now check if is an application in place to accept the + * connection. + */ + + listener = uip_tcplistener(portno); + if (listener && listener->accept) + { + /* Yes.. accept the connection */ + + ret = listener->accept(listener->accept_private, conn); + } + return ret; +} + +#endif /* CONFIG_NET */ diff --git a/net/uip/uip-tcpconn.c b/net/uip/uip-tcpconn.c index f604c26c78..b8bcdb3ceb 100644 --- a/net/uip/uip-tcpconn.c +++ b/net/uip/uip-tcpconn.c @@ -90,38 +90,6 @@ static uint8 g_tcp_sequence[4]; * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: uip_find_conn() - * - * Description: - * Given a port number, find the socket bound to the port number. - * Primary use: to determine if a port number is available. - * - ****************************************************************************/ - -static struct uip_conn *uip_find_conn(uint16 portno) -{ - struct uip_conn *conn; - int i; - - /* Check if this port number is already in use, and if so try to find - * another one. - */ - - for (i = 0; i < UIP_CONNS; i++) - { - conn = &g_tcp_connections[i]; - if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(g_last_tcp_port)) - { - /* The portnumber is in use */ - - return conn; - } - } - - return NULL; -} - /**************************************************************************** * Name: uip_selectport() * @@ -164,7 +132,7 @@ static int uip_selectport(uint16 portno) g_last_tcp_port = 4096; } } - while (uip_find_conn(g_last_tcp_port)); + while (uip_tcplistener(g_last_tcp_port)); } else { @@ -172,7 +140,7 @@ static int uip_selectport(uint16 portno) * connection is using this local port. */ - if (uip_find_conn(portno)) + if (uip_tcplistener(portno)) { /* It is in use... return EADDRINUSE */ @@ -373,7 +341,39 @@ struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) } /**************************************************************************** - * Name: uip_tcpactive() + * Name: uip_tcplistener() + * + * Description: + * Given a local port number, find the TCP connection that listens on this + * this port. + * + * Primary uses: (1) to determine if a port number is available, (2) to + * To idenfity the socket that will accept new connections on a local port. + * + ****************************************************************************/ + +struct uip_conn *uip_tcplistener(uint16 portno) +{ + struct uip_conn *conn; + int i; + + /* Check if this port number is in use by any active UIP TCP connection */ + + for (i = 0; i < UIP_CONNS; i++) + { + conn = &g_tcp_connections[i]; + if (conn->tcpstateflags != UIP_CLOSED && conn->lport == htons(g_last_tcp_port)) + { + /* The portnumber is in use, return the connection */ + + return conn; + } + } + return NULL; +} + +/**************************************************************************** + * Name: uip_tcpaccept() * * Description: * Called when uip_interupt matches the incoming packet with a connection @@ -385,7 +385,7 @@ struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf) * ****************************************************************************/ -struct uip_conn *uip_tcplistener(struct uip_tcpip_hdr *buf) +struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf) { struct uip_conn *conn = uip_tcpalloc(); if (conn) diff --git a/net/uip/uip.c b/net/uip/uip.c index 49536fa413..3cfb37b2a5 100644 --- a/net/uip/uip.c +++ b/net/uip/uip.c @@ -156,10 +156,6 @@ uint8 uip_flags; struct uip_conn *uip_conn; -/* The uip_listenports list all currently listening ports. */ - -uint16 uip_listenports[UIP_LISTENPORTS]; - #ifdef CONFIG_NET_UDP struct uip_udp_conn *uip_udp_conn; #endif /* CONFIG_NET_UDP */ @@ -361,10 +357,9 @@ uint16 uip_udpchksum(struct uip_driver_s *dev) void uip_init(void) { - for (c = 0; c < UIP_LISTENPORTS; ++c) - { - uip_listenports[c] = 0; - } + /* Initialize the listening port structures */ + + uip_listeninit(); /* Initialize the TCP/IP connection structures */ @@ -379,30 +374,6 @@ void uip_init(void) /* IPv4 initialization. */ } -void uip_unlisten(uint16 port) -{ - for (c = 0; c < UIP_LISTENPORTS; ++c) - { - if (uip_listenports[c] == port) - { - uip_listenports[c] = 0; - return; - } - } -} - -void uip_listen(uint16 port) -{ - for (c = 0; c < UIP_LISTENPORTS; ++c) - { - if (uip_listenports[c] == 0) - { - uip_listenports[c] = port; - return; - } - } -} - /* IP fragment reassembly: not well-tested. */ #if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6) @@ -1195,9 +1166,8 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) tmp16 = BUF->destport; /* Next, check listening connections. */ - for (c = 0; c < UIP_LISTENPORTS; ++c) + if (uip_islistener(tmp16)) { - if (tmp16 == uip_listenports[c]) goto found_listen; } @@ -1267,14 +1237,32 @@ void uip_interrupt(struct uip_driver_s *dev, uint8 flag) found_listen: - /* First allocate a new connection structure */ + /* First allocate a new connection structure and see if there is any + * user application to accept it. + */ - uip_connr = uip_tcplistener(BUF); + uip_connr = uip_tcpaccept(BUF); + if (uip_connr) + { + /* The connection structure was successfully allocated. Now see + * there is an application waiting to accept the connection (or at + * least queue it it for acceptance). + */ + if (uip_accept(uip_connr, tmp16) != OK) + { + /* No, then we have to give the connection back */ + + uip_tcpfree(uip_connr); + uip_connr = NULL; + } + } + if (!uip_connr) { - /* All connections are used already, we drop packet and hope that + /* Either (1) all available connections are in use, or (2) there is no + * application in place to accept the connection. We drop packet and hope that * the remote end will retransmit the packet at a time when we - * have more spare connections. + * have more spare connections or someone waiting to accept the connection. */ UIP_STAT(++uip_stat.tcp.syndrop); diff --git a/netutils/Makefile b/netutils/Makefile index 9c4536ff01..3232dd5f2f 100644 --- a/netutils/Makefile +++ b/netutils/Makefile @@ -72,38 +72,39 @@ $(COBJS): %$(OBJEXT): %.c $(CC) -c $(CFLAGS) $< -o $@ $(BIN): $(OBJS) - ( for obj in $(OBJS) ; do \ + @( for obj in $(OBJS) ; do \ $(AR) $@ $${obj} || \ { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \ done ; ) makestrings$(EXEEXT): uiplib/makestrings.c - gcc -O2 -Wall -o makestrings$(EXEEXT) uiplib/makestrings.c + @gcc -O2 -Wall $< -o $@ .strings: makestrings$(EXEEXT) uiplib/netutil-strings - ./makestrings uiplib/netutil-strings + @./makestrings uiplib/netutil-strings + @touch $@ Make.str: makestrings$(EXEEXT) uiplib/netutil-strings - ./makestrings -s uiplib/netutil-strings >Make.str + @./makestrings -s uiplib/netutil-strings >Make.str .depend: Makefile $(SRCS) ifeq ($(CONFIG_NET),y) - $(MKDEP) --dep-path . --dep-path uiplib --dep-path dhcpc --dep-path smtp --dep-path webclient \ + @$(MKDEP) --dep-path . --dep-path uiplib --dep-path dhcpc --dep-path smtp --dep-path webclient \ --dep-path resolv --dep-path telnetd --dep-path webserver \ $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep endif - touch $@ + @touch $@ depend: .strings Make.str .depend clean: - rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~ - rm -f uiplib/*~ dhcpc/*~ resolv/*~ smtp/*~ telnetd/*~ webclient/*~ webserver/*~ - if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi + @rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~ + @rm -f uiplib/*~ dhcpc/*~ resolv/*~ smtp/*~ telnetd/*~ webclient/*~ webserver/*~ + @if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi distclean: clean - rm -f Make.dep .depend - rm -f $(STRNG_CSRCS) $(STRNG_ASRCS) - rm -f Make.str netutil-strings.h makestrings$(EXEEXT) + @rm -f Make.dep .depend + @rm -f $(STRNG_CSRCS) $(STRNG_ASRCS) + @rm -f Make.str netutil-strings.h makestrings$(EXEEXT) -include Make.dep diff --git a/netutils/webserver/httpd.c b/netutils/webserver/httpd.c index dfccdef6cd..7c3271fd61 100644 --- a/netutils/webserver/httpd.c +++ b/netutils/webserver/httpd.c @@ -1,17 +1,24 @@ -/* httpd +/**************************************************************************** + * httpd * httpd Web server - * Author: Adam Dunkels * - * The uIP web server is a very simplistic implementation of an HTTP - * server. It can serve web pages and files from a read-only ROM - * filesystem, and provides a very small scripting language. + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * - * Copyright (c) 2004, Adam Dunkels. - * All rights reserved. + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * Copyright (c) 2004, Adam Dunkels. + * All rights reserved. + * + * The uIP web server is a very simplistic implementation of an HTTP + * server. It can serve web pages and files from a read-only ROM + * filesystem, and provides a very small scripting language. * * 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 @@ -32,10 +39,15 @@ * 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 #include +#include #include #include @@ -44,7 +56,9 @@ #include "httpd-cgi.h" #include "netutil-strings.h" -#include +/**************************************************************************** + * Definitions + ****************************************************************************/ #define STATE_WAITING 0 #define STATE_OUTPUT 1 @@ -59,6 +73,10 @@ #define SEND_STR(psock, str) psock_send(psock, str, strlen(str)) +/**************************************************************************** + * Private Functions + ****************************************************************************/ + static inline int send_file(struct httpd_state *pstate) { return send(pstate->sockout, pstate->file.data, pstate->file.len, 0); @@ -256,16 +274,31 @@ static void handle_connection(struct httpd_state *pstate) } } -void httpd_listen(void) +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: httpd_listen + * + * Description: + * This is the main processing thread for the webserver. It never returns + * unless an error occurs + * + ****************************************************************************/ + +int httpd_listen(void) { #warning "this is all very broken at the moment" } -/* Initialize the web server +/**************************************************************************** + * Name: httpd_init * - * This function initializes the web server and should be - * called at system boot-up. - */ + * Description: + * This function initializes the web server and should be called at system + * boot-up. + * + ****************************************************************************/ void httpd_init(void) {