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
This commit is contained in:
patacongo 2007-09-09 17:20:56 +00:00
parent 01207cc66e
commit dcf7c7c365
21 changed files with 889 additions and 1141 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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))

View File

@ -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);
}

View File

@ -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);
}
}
}
@ -147,6 +150,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 */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Perform the TCP/IP or UDP recv() operation */
#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.
*/
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;
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
/* Set up the start time for the timeout */
state.rf_starttime = g_system_timer;
if (psock->s_type == SOCK_STREAM)
#endif
{
ret = tcp_recvfrom(psock, buf, len, infrom);
}
#ifdef CONFIG_NET_UDP
else
{
ret = udp_recvfrom(psock, buf, len, infrom);
}
#endif
/* Setup the UDP socket */
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Handle returned errors */
ret = uip_udpconnect(psock->s_conn, NULL);
if (ret < 0)
{
irqrestore(save);
err = -ret;
goto errout;
}
/* Set up the callback in the connection */
/* Success return */
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)
{
/* Return EGAIN on a timeout */
err = -state.rf_buflen;
goto errout;
}
#endif
/* 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 ERROR;
}
#warning "Needs to return server address"
return state.rf_buflen;
#else
err = ENOSYS;
#endif
return ret;
errout:
*get_errno_ptr() = err;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -122,6 +122,69 @@ static struct uip_conn *uip_find_conn(uint16 portno)
return NULL;
}
/****************************************************************************
* 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)
flags = irqsave();
port = uip_selectport(ntohs(conn->lport));
irqrestore(flags);
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 */
if (g_last_tcp_port >= 32000)
{
g_last_tcp_port = 4096;
}
}
while (uip_find_conn(g_last_tcp_port));
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 */

View File

@ -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);
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_SEND_STR(&psmtp->psock, (char *)smtp_subject);
PSOCK_SEND_STR(&psmtp->psock, psmtp->subject);
PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnl);
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)
{
return ERROR;
}
psock_send(&psmtp->psock, psmtp->msg, psmtp->msglen);
if (send(sockfd, psmtp->msg, psmtp->msglen, 0) < 0)
{
return ERROR;
}
PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_crnlperiodcrnl);
if (send(sockfd, smtp_crnlperiodcrnl, strlen(smtp_crnlperiodcrnl), 0) < 0)
{
return ERROR;
}
if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
{
return ERROR;
}
psock_readto(&psmtp->psock, ISO_nl);
if (psmtp->buffer[0] != ISO_2)
{
PSOCK_CLOSE(&psmtp->psock);
psmtp->result = 8;
return;
return ERROR;
}
PSOCK_SEND_STR(&psmtp->psock, (char *)smtp_quit);
psmtp->result = 0;
}
/* This function is called by the UIP interrupt handling logic whenevent an
* event of interest occurs.
*/
void uip_interrupt_event(void)
{
#warning OBSOLETE -- needs to be redesigned
if (gpsmtp)
if (send(sockfd, smtp_quit, strlen(smtp_quit), 0) < 0)
{
if (uip_closed())
{
gpsmtp->connected = FALSE;
return;
}
if (uip_aborted() || uip_timedout())
{
gpsmtp->connected = FALSE;
}
sem_post((sem_t*)&gpsmtp->sem);
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? */
if (psmtp->result == OK )
{
/* No... Send the message */
smtp_send_message(psmtp);
}
return psmtp->result;
/* Send the message */
ret = smtp_send_message(sockfd, psmtp);
close(sockfd);
return ret;
}
void *smtp_open(void)

View File

@ -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;
struct httpd_state *pstate = (struct httpd_state *)arg;
char buffer[256];
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))? '!':' ');
}
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 */
}

View File

@ -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);

View File

@ -45,6 +45,7 @@
#include <net/uip/httpd.h>
#include "httpd.h"
#include "httpd-fsdata.h"
#ifndef NULL

View File

@ -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)
#define SEND_STR(psock, str) psock_send(psock, str, strlen(str))
static inline int send_file(struct httpd_state *pstate)
{
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;
return send(pstate->sockout, pstate->file.data, pstate->file.len, 0);
}
static void send_file(struct httpd_state *s)
static inline int send_part_of_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->len, 0);
}
static void send_part_of_file(struct httpd_state *s)
{
psock_send(&s->sout, s->file.data, s->len);
#warning REVISIT must not return until file sent
}
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);
ret = send(pstate->sockout, statushdr, strlen(statushdr), 0);
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
}
static void handle_output(struct httpd_state *s)
{
char *ptr;
if (!httpd_fs_open(s->filename, &s->file))
ptr = strrchr(pstate->filename, ISO_period);
if (ptr == NULL)
{
httpd_fs_open(http_404_html, &s->file);
strcpy(s->filename, http_404_html);
send_headers(s, http_header_404);
send_file(s);
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
{
send_headers(s, http_header_200);
ptr = strchr(s->filename, ISO_period);
ret = send(pstate->sockout, http_content_type_plain, strlen(http_content_type_plain), 0);
}
return ret;
}
static void handle_output(struct httpd_state *pstate)
{
char *ptr;
if (!httpd_fs_open(pstate->filename, &pstate->file))
{
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(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 (strncmp(s->inputbuf, http_get, 4) != 0)
if (recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0) < 0)
{
PSOCK_CLOSE(&s->sin);
return;
return ERROR;
}
if (strncmp(pstate->inputbuf, http_get, 4) != 0)
{
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);
if (strncmp(s->inputbuf, http_referer, 8) == 0)
recvlen = recv(pstate->sockin, pstate->inputbuf, HTTPD_INBUFFER_SIZE, 0);
if (recvlen < 0)
{
s->inputbuf[psock_datalen(&s->sin) - 2] = 0;
return ERROR;
}
if (strncmp(pstate->inputbuf, http_referer, 8) == 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

View File

@ -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 */