diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-09-09 17:20:56 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-09-09 17:20:56 +0000 |
commit | 7a65f932826220c741ffbf5698b48692a787d915 (patch) | |
tree | 825e048f8fc18b7e69cb155ad96b7254566a3ffe /nuttx/net/uip | |
parent | d12e00bdd6ffbb39ab5d45d5d5a484d293108021 (diff) | |
download | px4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.tar.gz px4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.tar.bz2 px4-nuttx-7a65f932826220c741ffbf5698b48692a787d915.zip |
Implement TCP send; remove uIP proto-sockets
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@339 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/net/uip')
-rw-r--r-- | nuttx/net/uip/Make.defs | 2 | ||||
-rw-r--r-- | nuttx/net/uip/psock.c | 385 | ||||
-rw-r--r-- | nuttx/net/uip/uip-tcpconn.c | 109 |
3 files changed, 86 insertions, 410 deletions
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs index 96691792d..4ad51f9bc 100644 --- a/nuttx/net/uip/Make.defs +++ b/nuttx/net/uip/Make.defs @@ -34,6 +34,6 @@ ############################################################################ UIP_ASRCS = -UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c \ +UIP_CSRCS = uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c \ uip-tcpconn.c uip-udpconn.c uip-wait.c diff --git a/nuttx/net/uip/psock.c b/nuttx/net/uip/psock.c deleted file mode 100644 index 55676c3c2..000000000 --- a/nuttx/net/uip/psock.c +++ /dev/null @@ -1,385 +0,0 @@ -/**************************************************************************** - * net/uip/psock.c - * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <spudmonkey@racsa.co.cr> - * - * Based on uIP which also has a BSD style license: - * - * Copyright (c) 2004, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <pthread.h> -#include <debug.h> - -#include <net/uip/uip.h> -#include <net/uip/uipopt.h> -#include <net/uip/psock.h> - -#define STATE_NONE 0 -#define STATE_ACKED 1 -#define STATE_READ 2 -#define STATE_BLOCKED_NEWDATA 3 -#define STATE_BLOCKED_CLOSE 4 -#define STATE_BLOCKED_SEND 5 -#define STATE_DATA_SENT 6 - -/* - * Return value of the buffering functions that indicates that a - * buffer was not filled by incoming data. - * - */ -#define BUF_NOT_FULL 0 -#define BUF_NOT_FOUND 0 - -/* - * Return value of the buffering functions that indicates that a - * buffer was completely filled by incoming data. - * - */ -#define BUF_FULL 1 - -/* - * Return value of the buffering functions that indicates that an - * end-marker byte was found. - * - */ -#define BUF_FOUND 2 - -static void buf_setup(struct psock_buf *buf, uint8 *bufptr, uint16 bufsize) -{ - buf->ptr = bufptr; - buf->left = bufsize; -} - -static uint8 buf_bufdata(struct psock_buf *buf, uint16 len, uint8 **dataptr, uint16 *datalen) -{ - if (*datalen < buf->left) - { - memcpy(buf->ptr, *dataptr, *datalen); - buf->ptr += *datalen; - buf->left -= *datalen; - *dataptr += *datalen; - *datalen = 0; - return BUF_NOT_FULL; - } - else if (*datalen == buf->left) - { - memcpy(buf->ptr, *dataptr, *datalen); - buf->ptr += *datalen; - buf->left = 0; - *dataptr += *datalen; - *datalen = 0; - return BUF_FULL; - } - else - { - memcpy(buf->ptr, *dataptr, buf->left); - buf->ptr += buf->left; - *datalen -= buf->left; - *dataptr += buf->left; - buf->left = 0; - return BUF_FULL; - } -} - -static uint8 buf_bufto(struct psock_buf *buf, uint8 endmarker, uint8 **dataptr, uint16 *datalen) -{ - uint8 c; - while(buf->left > 0 && *datalen > 0) - { - c = *buf->ptr = **dataptr; - ++*dataptr; - ++buf->ptr; - --*datalen; - --buf->left; - - if (c == endmarker) - { - return BUF_FOUND; - } - } - - if (*datalen == 0) - { - return BUF_NOT_FOUND; - } - - while(*datalen > 0) - { - c = **dataptr; - --*datalen; - ++*dataptr; - - if (c == endmarker) - { - return BUF_FOUND | BUF_FULL; - } - } - - return BUF_FULL; -} - -static boolean send_data(register struct psock *s) -{ - /* Inidicate that we are blocked waiting for the send to complete */ - - s->state = STATE_BLOCKED_SEND; - - /* Loop until we successfully send the data */ - - for (;;) - { - /* If the data has not been sent OR if it needs to be retransmitted, - * then send it now. - */ - - if (s->state != STATE_DATA_SENT || uip_rexmit()) - { - if (s->sendlen > uip_mss()) - { - uip_send(s->sendptr, uip_mss()); - } - else - { - uip_send(s->sendptr, s->sendlen); - } - - s->state = STATE_DATA_SENT; - } - - /* Check if all data has been sent and acknowledged */ - - if (s->state == STATE_DATA_SENT && uip_acked()) - { - /* Yes.. the data has been sent AND acknowledge */ - - if (s->sendlen > uip_mss()) - { - s->sendlen -= uip_mss(); - s->sendptr += uip_mss(); - } - else - { - s->sendptr += s->sendlen; - s->sendlen = 0; - } - - s->state = STATE_ACKED; - return TRUE; - } - - /* No.. then wait on the retransmit or acked events */ - - (void)uip_event_wait(UIP_ACKDATA|UIP_REXMIT); - } - - return FALSE; /* We never get here */ -} - -void psock_send(struct psock *s, const char *buf, unsigned int len) -{ - /* If there is no data to send, we exit immediately. */ - - if (len > 0) - { - /* Save the length of and a pointer to the data that is to be sent. */ - - s->sendptr = (const uint8*)buf; - s->sendlen = len; - s->state = STATE_NONE; - - /* Loop here until all data is sent. The s->sendlen variable is updated - * by the data_sent() function. - */ - - while(s->sendlen > 0) { - - /* Wait until the data has been sent and acknowledged */ - - send_data(s); - } - - /* Done */ - - s->state = STATE_NONE; - } -} - -void psock_generator_send(register struct psock *s, unsigned short (*generate)(void *), void *arg) -{ - /* Ensure that there is a generator function to call. */ - - if (generate != NULL) - { - /* Call the generator function to generate the data in the uip_appdata - * buffer. - */ - - s->sendlen = generate(arg); - s->sendptr = uip_appdata; - s->state = STATE_NONE; - - do - { - /* Call the generator function again if we are called to perform a - * retransmission. - */ - - if (uip_rexmit()) - { - generate(arg); - } - - /* Wait until all data is sent and acknowledged. */ - - send_data(s); - } - while(s->sendlen > 0); - - /* Done */ - - s->state = STATE_NONE; - } -} - -uint16 psock_datalen(struct psock *psock) -{ - return psock->bufsize - psock->buf.left; -} - -boolean psock_checknewdata(struct psock *s) -{ - if (s->readlen > 0) - { - /* There is data in the uip_appdata buffer that has not yet been read - * with the PSOCK_READ functions. - */ - return TRUE; - } - else if (s->state == STATE_READ) - { - /* All data in uip_appdata buffer already consumed. */ - - s->state = STATE_BLOCKED_NEWDATA; - return FALSE; - } - else if (uip_newdata()) - { - /* There is new data that has not been consumed. */ - - return TRUE; - } - else - { - /* There is no new data. */ - - return FALSE; - } -} - -void psock_waitnewdata(struct psock *s) -{ - while (!psock_checknewdata(s)) - { - uip_event_wait(UIP_NEWDATA); - } -} - -void psock_readto(register struct psock *psock, unsigned char c) -{ -restart: - buf_setup(&psock->buf, psock->bufptr, psock->bufsize); - - /* XXX: Should add buf_checkmarker() before do{} loop, if - incoming data has been handled while waiting for a write. */ - - do - { - if (psock->readlen == 0) - { - psock_waitnewdata(psock); - psock->state = STATE_READ; - psock->readptr = (uint8 *)uip_appdata; - psock->readlen = uip_datalen(); - } - } - while((buf_bufto(&psock->buf, c, &psock->readptr, &psock->readlen) & BUF_FOUND) == 0); - - if (psock_datalen(psock) == 0) - { - psock->state = STATE_NONE; - goto restart; - } -} - -void psock_readbuf(register struct psock *psock) -{ -restart: - buf_setup(&psock->buf, psock->bufptr, psock->bufsize); - - /* XXX: Should add buf_checkmarker() before do{} loop, if - incoming data has been handled while waiting for a write. */ - - do - { - if (psock->readlen == 0) - { - psock_waitnewdata(psock); - dbg("Waited for newdata\n"); - psock->state = STATE_READ; - psock->readptr = (uint8 *)uip_appdata; - psock->readlen = uip_datalen(); - } - } - while(buf_bufdata(&psock->buf, psock->bufsize, &psock->readptr, &psock->readlen) != BUF_FULL); - - if (psock_datalen(psock) == 0) - { - psock->state = STATE_NONE; - goto restart; - } -} - -void psock_init(register struct psock *psock, char *buffer, unsigned int buffersize) -{ - psock->state = STATE_NONE; - psock->readlen = 0; - psock->bufptr = (uint8*)buffer; - psock->bufsize = buffersize; - buf_setup(&psock->buf, (uint8*)buffer, buffersize); -} - diff --git a/nuttx/net/uip/uip-tcpconn.c b/nuttx/net/uip/uip-tcpconn.c index 9d1380f6b..8f14dc24b 100644 --- a/nuttx/net/uip/uip-tcpconn.c +++ b/nuttx/net/uip/uip-tcpconn.c @@ -123,6 +123,69 @@ static struct uip_conn *uip_find_conn(uint16 portno) } /**************************************************************************** + * Name: uip_selectport() + * + * Description: + * If the portnumber is zero; select an unused port for the connection. + * If the portnumber is non-zero, verify that no other connection has + * been created with this port number. + * + * Input Parameters: + * portno -- the selected port number in host order. Zero means no port + * selected. + * + * Return: + * 0 on success, -ERRNO on failure + * + * Assumptions: + * Interrupts are disabled + * + ****************************************************************************/ + +static int uip_selectport(uint16 portno) +{ + if (portno == 0) + { + /* No local port assigned. Loop until we find a valid listen port number + * that is not being used by any other connection. + */ + + do + { + /* Guess that the next available port number will be the one after + * the last port number assigned. + */ + portno = ++g_last_tcp_port; + + /* Make sure that the port number is within range */ + + if (g_last_tcp_port >= 32000) + { + g_last_tcp_port = 4096; + } + } + while (uip_find_conn(g_last_tcp_port)); + } + else + { + /* A port number has been supplied. Verify that no other TCP/IP + * connection is using this local port. + */ + + if (uip_find_conn(portno)) + { + /* It is in use... return EADDRINUSE */ + + return -EADDRINUSE; + } + } + + /* Return the selecte or verified port number */ + + return portno; +} + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -422,6 +485,20 @@ int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in6 *addr) int uip_tcpbind(struct uip_conn *conn, const struct sockaddr_in *addr) #endif { + irqstate_t flags; + int port; + + /* Verify or select a local port */ + + flags = irqsave(); + port = uip_selectport(ntohs(conn->lport)); + irqrestore(flags); + + if (port < 0) + { + return port; + } + #warning "Need to implement bind logic" return -ENOSYS; } @@ -453,7 +530,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr) #endif { irqstate_t flags; - uint16 port; + int port; /* The connection is expected to be in the UIP_ALLOCATED state.. i.e., * allocated via up_tcpalloc(), but not yet put into the active connections @@ -469,29 +546,13 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr) * one now. */ - port = ntohs(conn->lport); - if (port == 0) - { - /* No local port assigned. Loop until we find a valid listen port number\ - * that is not being used by any other connection. - */ - - do - { - /* Guess that the next available port number will be the one after - * the last port number assigned. - */ -#warning "This need protection from other threads and from interrupts" - port = ++g_last_tcp_port; - - /* Make sure that the port number is within range */ + flags = irqsave(); + port = uip_selectport(ntohs(conn->lport)); + irqrestore(flags); - if (g_last_tcp_port >= 32000) - { - g_last_tcp_port = 4096; - } - } - while (uip_find_conn(g_last_tcp_port)); + if (port < 0) + { + return port; } /* Initialize and return the connection structure, bind it to the port number */ @@ -511,7 +572,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr) conn->rto = UIP_RTO; conn->sa = 0; conn->sv = 16; /* Initial value of the RTT variance. */ - conn->lport = htons(port); + conn->lport = htons((uint16)port); /* The sockaddr port is 16 bits and already in network order */ |