Partial implementation of accept() and listen()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@354 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
b85008dc63
commit
69ec9510a0
@ -34,6 +34,6 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
extern void httpd_init(void);
|
||||
extern void httpd_listen(void);
|
||||
extern int httpd_listen(void);
|
||||
|
||||
#endif /* _NET_UIP_HTTPD_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.
|
||||
*
|
||||
|
217
net/accept.c
217
net/accept.c
@ -42,12 +42,72 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
48
net/listen.c
48
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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -44,6 +44,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <arch/irq.h>
|
||||
#include <net/uip/uip.h>
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
}
|
||||
|
206
net/uip/uip-listen.c
Normal file
206
net/uip/uip-listen.c
Normal file
@ -0,0 +1,206 @@
|
||||
/****************************************************************************
|
||||
* net/uip/uip-listen.c
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* A direct leverage of logic from uIP which also has b BSD style license
|
||||
*
|
||||
* Author: Adam Dunkels <adam@dunkels.com>
|
||||
* 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 <nuttx/config.h>
|
||||
#ifdef CONFIG_NET
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <net/uip/uipopt.h>
|
||||
|
||||
#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 */
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,17 +1,24 @@
|
||||
/* httpd
|
||||
/****************************************************************************
|
||||
* httpd
|
||||
* httpd Web server
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* 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 <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Copyright (c) 2004, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
* This is a leverage of similar logic from uIP:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* 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 <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <net/uip/uip.h>
|
||||
#include <net/uip/httpd.h>
|
||||
@ -44,7 +56,9 @@
|
||||
#include "httpd-cgi.h"
|
||||
#include "netutil-strings.h"
|
||||
|
||||
#include <string.h>
|
||||
/****************************************************************************
|
||||
* 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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user