aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/x300/lwip/lwip-1.3.1/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/x300/lwip/lwip-1.3.1/src/api')
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/api_lib.c557
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/api_msg.c1232
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/err.c74
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/netbuf.c235
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/netdb.c356
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/netifapi.c126
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/sockets.c1970
-rw-r--r--firmware/x300/lwip/lwip-1.3.1/src/api/tcpip.c596
8 files changed, 0 insertions, 5146 deletions
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/api_lib.c b/firmware/x300/lwip/lwip-1.3.1/src/api/api_lib.c
deleted file mode 100644
index 86df911ea..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/api_lib.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/**
- * @file
- * Sequential API External module
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-/* This is the part of the API that is linked with
- the application */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/api.h"
-#include "lwip/tcpip.h"
-#include "lwip/memp.h"
-
-#include "lwip/ip.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
-
-#include <string.h>
-
-/**
- * Create a new netconn (of a specific type) that has a callback function.
- * The corresponding pcb is also created.
- *
- * @param t the type of 'connection' to create (@see enum netconn_type)
- * @param proto the IP protocol for RAW IP pcbs
- * @param callback a function to call on status changes (RX available, TX'ed)
- * @return a newly allocated struct netconn or
- * NULL on memory error
- */
-struct netconn*
-netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
-{
- struct netconn *conn;
- struct api_msg msg;
-
- conn = netconn_alloc(t, callback);
- if (conn != NULL ) {
- msg.function = do_newconn;
- msg.msg.msg.n.proto = proto;
- msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
-
- if (conn->err != ERR_OK) {
- LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
- LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL);
- LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL);
- LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL);
- sys_sem_free(conn->op_completed);
- sys_mbox_free(conn->recvmbox);
- memp_free(MEMP_NETCONN, conn);
- return NULL;
- }
- }
- return conn;
-}
-
-/**
- * Close a netconn 'connection' and free its resources.
- * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
- * after this returns.
- *
- * @param conn the netconn to delete
- * @return ERR_OK if the connection was deleted
- */
-err_t
-netconn_delete(struct netconn *conn)
-{
- struct api_msg msg;
-
- /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
- if (conn == NULL) {
- return ERR_OK;
- }
-
- msg.function = do_delconn;
- msg.msg.conn = conn;
- tcpip_apimsg(&msg);
-
- conn->pcb.tcp = NULL;
- netconn_free(conn);
-
- return ERR_OK;
-}
-
-/**
- * Get the local or remote IP address and port of a netconn.
- * For RAW netconns, this returns the protocol instead of a port!
- *
- * @param conn the netconn to query
- * @param addr a pointer to which to save the IP address
- * @param port a pointer to which to save the port (or protocol for RAW)
- * @param local 1 to get the local IP address, 0 to get the remote one
- * @return ERR_CONN for invalid connections
- * ERR_OK if the information was retrieved
- */
-err_t
-netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
- LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
- LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
-
- msg.function = do_getaddr;
- msg.msg.conn = conn;
- msg.msg.msg.ad.ipaddr = addr;
- msg.msg.msg.ad.port = port;
- msg.msg.msg.ad.local = local;
- TCPIP_APIMSG(&msg);
-
- return conn->err;
-}
-
-/**
- * Bind a netconn to a specific local IP address and port.
- * Binding one netconn twice might not always be checked correctly!
- *
- * @param conn the netconn to bind
- * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
- * to bind to all addresses)
- * @param port the local port to bind the netconn to (not used for RAW)
- * @return ERR_OK if bound, any other err_t on failure
- */
-err_t
-netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_bind;
- msg.msg.conn = conn;
- msg.msg.msg.bc.ipaddr = addr;
- msg.msg.msg.bc.port = port;
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-
-/**
- * Connect a netconn to a specific remote IP address and port.
- *
- * @param conn the netconn to connect
- * @param addr the remote IP address to connect to
- * @param port the remote port to connect to (no used for RAW)
- * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
- */
-err_t
-netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_connect;
- msg.msg.conn = conn;
- msg.msg.msg.bc.ipaddr = addr;
- msg.msg.msg.bc.port = port;
- /* This is the only function which need to not block tcpip_thread */
- tcpip_apimsg(&msg);
- return conn->err;
-}
-
-/**
- * Disconnect a netconn from its current peer (only valid for UDP netconns).
- *
- * @param conn the netconn to disconnect
- * @return TODO: return value is not set here...
- */
-err_t
-netconn_disconnect(struct netconn *conn)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_disconnect;
- msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-
-/**
- * Set a TCP netconn into listen mode
- *
- * @param conn the tcp netconn to set to listen mode
- * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
- * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
- * don't return any error (yet?))
- */
-err_t
-netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
-{
- struct api_msg msg;
-
- /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
- LWIP_UNUSED_ARG(backlog);
-
- LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_listen;
- msg.msg.conn = conn;
-#if TCP_LISTEN_BACKLOG
- msg.msg.msg.lb.backlog = backlog;
-#endif /* TCP_LISTEN_BACKLOG */
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-
-/**
- * Accept a new connection on a TCP listening netconn.
- *
- * @param conn the TCP listen netconn
- * @return the newly accepted netconn or NULL on timeout
- */
-struct netconn *
-netconn_accept(struct netconn *conn)
-{
- struct netconn *newconn;
-
- LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return NULL;);
- LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;);
-
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
- newconn = NULL;
- } else
-#else
- sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
- {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
-
-#if TCP_LISTEN_BACKLOG
- if (newconn != NULL) {
- /* Let the stack know that we have accepted the connection. */
- struct api_msg msg;
- msg.function = do_recv;
- msg.msg.conn = conn;
- TCPIP_APIMSG(&msg);
- }
-#endif /* TCP_LISTEN_BACKLOG */
- }
-
- return newconn;
-}
-
-/**
- * Receive data (in form of a netbuf containing a packet buffer) from a netconn
- *
- * @param conn the netconn from which to receive data
- * @return a new netbuf containing received data or NULL on memory error or timeout
- */
-struct netbuf *
-netconn_recv(struct netconn *conn)
-{
- struct api_msg msg;
- struct netbuf *buf = NULL;
- struct pbuf *p;
- u16_t len;
-
- LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return NULL;);
-
- if (conn->recvmbox == SYS_MBOX_NULL) {
- /* @todo: should calling netconn_recv on a TCP listen conn be fatal (ERR_CONN)?? */
- /* TCP listen conns don't have a recvmbox! */
- conn->err = ERR_CONN;
- return NULL;
- }
-
- if (ERR_IS_FATAL(conn->err)) {
- return NULL;
- }
-
- if (conn->type == NETCONN_TCP) {
-#if LWIP_TCP
- if (conn->state == NETCONN_LISTEN) {
- /* @todo: should calling netconn_recv on a TCP listen conn be fatal?? */
- conn->err = ERR_CONN;
- return NULL;
- }
-
- buf = memp_malloc(MEMP_NETBUF);
-
- if (buf == NULL) {
- conn->err = ERR_MEM;
- return NULL;
- }
-
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- conn->err = ERR_TIMEOUT;
- p = NULL;
- }
-#else
- sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
-
- if (p != NULL) {
- len = p->tot_len;
- SYS_ARCH_DEC(conn->recv_avail, len);
- } else {
- len = 0;
- }
-
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
-
- /* If we are closed, we indicate that we no longer wish to use the socket */
- if (p == NULL) {
- memp_free(MEMP_NETBUF, buf);
- /* Avoid to lose any previous error code */
- if (conn->err == ERR_OK) {
- conn->err = ERR_CLSD;
- }
- return NULL;
- }
-
- buf->p = p;
- buf->ptr = p;
- buf->port = 0;
- buf->addr = NULL;
-
- /* Let the stack know that we have taken the data. */
- msg.function = do_recv;
- msg.msg.conn = conn;
- if (buf != NULL) {
- msg.msg.msg.r.len = buf->p->tot_len;
- } else {
- msg.msg.msg.r.len = 1;
- }
- TCPIP_APIMSG(&msg);
-#endif /* LWIP_TCP */
- } else {
-#if (LWIP_UDP || LWIP_RAW)
-#if LWIP_SO_RCVTIMEO
- if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
- buf = NULL;
- }
-#else
- sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, 0);
-#endif /* LWIP_SO_RCVTIMEO*/
- if (buf!=NULL) {
- SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
- }
-#endif /* (LWIP_UDP || LWIP_RAW) */
- }
-
- LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
-
- return buf;
-}
-
-/**
- * Send data (in form of a netbuf) to a specific remote IP address and port.
- * Only to be used for UDP and RAW netconns (not TCP).
- *
- * @param conn the netconn over which to send data
- * @param buf a netbuf containing the data to send
- * @param addr the remote IP address to which to send the data
- * @param port the remote port to which to send the data
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
-{
- if (buf != NULL) {
- buf->addr = addr;
- buf->port = port;
- return netconn_send(conn, buf);
- }
- return ERR_VAL;
-}
-
-/**
- * Send data over a UDP or RAW netconn (that is already connected).
- *
- * @param conn the UDP or RAW netconn over which to send data
- * @param buf a netbuf containing the data to send
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_send(struct netconn *conn, struct netbuf *buf)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
-
- LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
- msg.function = do_send;
- msg.msg.conn = conn;
- msg.msg.msg.b = buf;
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-
-/**
- * Send data over a TCP netconn.
- *
- * @param conn the TCP netconn over which to send data
- * @param dataptr pointer to the application buffer that contains the data to send
- * @param size size of the application data to send
- * @param apiflags combination of following flags :
- * - NETCONN_COPY (0x01) data will be copied into memory belonging to the stack
- * - NETCONN_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent
- * @return ERR_OK if data was sent, any other err_t on error
- */
-err_t
-netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
- LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
-
- msg.function = do_write;
- msg.msg.conn = conn;
- msg.msg.msg.w.dataptr = dataptr;
- msg.msg.msg.w.apiflags = apiflags;
- msg.msg.msg.w.len = size;
- /* For locking the core: this _can_ be delayed on low memory/low send buffer,
- but if it is, this is done inside api_msg.c:do_write(), so we can use the
- non-blocking version here. */
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-
-/**
- * Close a TCP netconn (doesn't delete it).
- *
- * @param conn the TCP netconn to close
- * @return ERR_OK if the netconn was closed, any other err_t on error
- */
-err_t
-netconn_close(struct netconn *conn)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_close;
- msg.msg.conn = conn;
- tcpip_apimsg(&msg);
- return conn->err;
-}
-
-#if LWIP_IGMP
-/**
- * Join multicast groups for UDP netconns.
- *
- * @param conn the UDP netconn for which to change multicast addresses
- * @param multiaddr IP address of the multicast group to join or leave
- * @param interface the IP address of the network interface on which to send
- * the igmp message
- * @param join_or_leave flag whether to send a join- or leave-message
- * @return ERR_OK if the action was taken, any err_t on error
- */
-err_t
-netconn_join_leave_group(struct netconn *conn,
- struct ip_addr *multiaddr,
- struct ip_addr *interface,
- enum netconn_igmp join_or_leave)
-{
- struct api_msg msg;
-
- LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
-
- msg.function = do_join_leave_group;
- msg.msg.conn = conn;
- msg.msg.msg.jl.multiaddr = multiaddr;
- msg.msg.msg.jl.interface = interface;
- msg.msg.msg.jl.join_or_leave = join_or_leave;
- TCPIP_APIMSG(&msg);
- return conn->err;
-}
-#endif /* LWIP_IGMP */
-
-#if LWIP_DNS
-/**
- * Execute a DNS query, only one IP address is returned
- *
- * @param name a string representation of the DNS host name to query
- * @param addr a preallocated struct ip_addr where to store the resolved IP address
- * @return ERR_OK: resolving succeeded
- * ERR_MEM: memory error, try again later
- * ERR_ARG: dns client not initialized or invalid hostname
- * ERR_VAL: dns server response was invalid
- */
-err_t
-netconn_gethostbyname(const char *name, struct ip_addr *addr)
-{
- struct dns_api_msg msg;
- err_t err;
- sys_sem_t sem;
-
- LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
- LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
-
- sem = sys_sem_new(0);
- if (sem == SYS_SEM_NULL) {
- return ERR_MEM;
- }
-
- msg.name = name;
- msg.addr = addr;
- msg.err = &err;
- msg.sem = sem;
-
- tcpip_callback(do_gethostbyname, &msg);
- sys_sem_wait(sem);
- sys_sem_free(sem);
-
- return err;
-}
-#endif /* LWIP_DNS*/
-
-#endif /* LWIP_NETCONN */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/api_msg.c b/firmware/x300/lwip/lwip-1.3.1/src/api/api_msg.c
deleted file mode 100644
index 28d101019..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/api_msg.c
+++ /dev/null
@@ -1,1232 +0,0 @@
-/**
- * @file
- * Sequential API Internal module
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/api_msg.h"
-
-#include "lwip/ip.h"
-#include "lwip/udp.h"
-#include "lwip/tcp.h"
-#include "lwip/raw.h"
-
-#include "lwip/memp.h"
-#include "lwip/tcpip.h"
-#include "lwip/igmp.h"
-#include "lwip/dns.h"
-
-#include <string.h>
-
-/* forward declarations */
-#if LWIP_TCP
-static err_t do_writemore(struct netconn *conn);
-static void do_close_internal(struct netconn *conn);
-#endif
-
-#if LWIP_RAW
-/**
- * Receive callback function for RAW netconns.
- * Doesn't 'eat' the packet, only references it and sends it to
- * conn->recvmbox
- *
- * @see raw.h (struct raw_pcb.recv) for parameters and return value
- */
-static u8_t
-recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr)
-{
- struct pbuf *q;
- struct netbuf *buf;
- struct netconn *conn;
-#if LWIP_SO_RCVBUF
- int recv_avail;
-#endif /* LWIP_SO_RCVBUF */
-
- LWIP_UNUSED_ARG(addr);
- conn = arg;
-
-#if LWIP_SO_RCVBUF
- SYS_ARCH_GET(conn->recv_avail, recv_avail);
- if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) &&
- ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) {
-#else /* LWIP_SO_RCVBUF */
- if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) {
-#endif /* LWIP_SO_RCVBUF */
- /* copy the whole packet into new pbufs */
- q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
- if(q != NULL) {
- if (pbuf_copy(q, p) != ERR_OK) {
- pbuf_free(q);
- q = NULL;
- }
- }
-
- if(q != NULL) {
- buf = memp_malloc(MEMP_NETBUF);
- if (buf == NULL) {
- pbuf_free(q);
- return 0;
- }
-
- buf->p = q;
- buf->ptr = q;
- buf->addr = &(((struct ip_hdr*)(q->payload))->src);
- buf->port = pcb->protocol;
-
- if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
- netbuf_delete(buf);
- return 0;
- } else {
- SYS_ARCH_INC(conn->recv_avail, q->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
- }
- }
- }
-
- return 0; /* do not eat the packet */
-}
-#endif /* LWIP_RAW*/
-
-#if LWIP_UDP
-/**
- * Receive callback function for UDP netconns.
- * Posts the packet to conn->recvmbox or deletes it on memory error.
- *
- * @see udp.h (struct udp_pcb.recv) for parameters
- */
-static void
-recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr, u16_t port)
-{
- struct netbuf *buf;
- struct netconn *conn;
-#if LWIP_SO_RCVBUF
- int recv_avail;
-#endif /* LWIP_SO_RCVBUF */
-
- LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
- LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
- LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
- conn = arg;
- LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
-
-#if LWIP_SO_RCVBUF
- SYS_ARCH_GET(conn->recv_avail, recv_avail);
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) ||
- ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
-#else /* LWIP_SO_RCVBUF */
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
-#endif /* LWIP_SO_RCVBUF */
- pbuf_free(p);
- return;
- }
-
- buf = memp_malloc(MEMP_NETBUF);
- if (buf == NULL) {
- pbuf_free(p);
- return;
- } else {
- buf->p = p;
- buf->ptr = p;
- buf->addr = addr;
- buf->port = port;
- }
-
- if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
- netbuf_delete(buf);
- return;
- } else {
- SYS_ARCH_INC(conn->recv_avail, p->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
- }
-}
-#endif /* LWIP_UDP */
-
-#if LWIP_TCP
-/**
- * Receive callback function for TCP netconns.
- * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
- *
- * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
- */
-static err_t
-recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
-{
- struct netconn *conn;
- u16_t len;
-
- LWIP_UNUSED_ARG(pcb);
- LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
- LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
- conn = arg;
- LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
-
- if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
- return ERR_VAL;
- }
-
- conn->err = err;
- if (p != NULL) {
- len = p->tot_len;
- SYS_ARCH_INC(conn->recv_avail, len);
- } else {
- len = 0;
- }
-
- if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
- return ERR_MEM;
- } else {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
- }
-
- return ERR_OK;
-}
-
-/**
- * Poll callback function for TCP netconns.
- * Wakes up an application thread that waits for a connection to close
- * or data to be sent. The application thread then takes the
- * appropriate action to go on.
- *
- * Signals the conn->sem.
- * netconn_close waits for conn->sem if closing failed.
- *
- * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
- */
-static err_t
-poll_tcp(void *arg, struct tcp_pcb *pcb)
-{
- struct netconn *conn = arg;
-
- LWIP_UNUSED_ARG(pcb);
- LWIP_ASSERT("conn != NULL", (conn != NULL));
-
- if (conn->state == NETCONN_WRITE) {
- do_writemore(conn);
- } else if (conn->state == NETCONN_CLOSE) {
- do_close_internal(conn);
- }
-
- return ERR_OK;
-}
-
-/**
- * Sent callback function for TCP netconns.
- * Signals the conn->sem and calls API_EVENT.
- * netconn_write waits for conn->sem if send buffer is low.
- *
- * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
- */
-static err_t
-sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
-{
- struct netconn *conn = arg;
-
- LWIP_UNUSED_ARG(pcb);
- LWIP_ASSERT("conn != NULL", (conn != NULL));
-
- if (conn->state == NETCONN_WRITE) {
- LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
- do_writemore(conn);
- } else if (conn->state == NETCONN_CLOSE) {
- do_close_internal(conn);
- }
-
- if (conn) {
- if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) {
- API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
- }
- }
-
- return ERR_OK;
-}
-
-/**
- * Error callback function for TCP netconns.
- * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
- * The application thread has then to decide what to do.
- *
- * @see tcp.h (struct tcp_pcb.err) for parameters
- */
-static void
-err_tcp(void *arg, err_t err)
-{
- struct netconn *conn;
-
- conn = arg;
- LWIP_ASSERT("conn != NULL", (conn != NULL));
-
- conn->pcb.tcp = NULL;
-
- conn->err = err;
- if (conn->recvmbox != SYS_MBOX_NULL) {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- sys_mbox_post(conn->recvmbox, NULL);
- }
- if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) {
- conn->state = NETCONN_NONE;
- sys_sem_signal(conn->op_completed);
- }
- if (conn->acceptmbox != SYS_MBOX_NULL) {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- sys_mbox_post(conn->acceptmbox, NULL);
- }
- if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) {
- /* calling do_writemore/do_close_internal is not necessary
- since the pcb has already been deleted! */
- conn->state = NETCONN_NONE;
- /* wake up the waiting task */
- sys_sem_signal(conn->op_completed);
- }
-}
-
-/**
- * Setup a tcp_pcb with the correct callback function pointers
- * and their arguments.
- *
- * @param conn the TCP netconn to setup
- */
-static void
-setup_tcp(struct netconn *conn)
-{
- struct tcp_pcb *pcb;
-
- pcb = conn->pcb.tcp;
- tcp_arg(pcb, conn);
- tcp_recv(pcb, recv_tcp);
- tcp_sent(pcb, sent_tcp);
- tcp_poll(pcb, poll_tcp, 4);
- tcp_err(pcb, err_tcp);
-}
-
-/**
- * Accept callback function for TCP netconns.
- * Allocates a new netconn and posts that to conn->acceptmbox.
- *
- * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
- */
-static err_t
-accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
-{
- struct netconn *newconn;
- struct netconn *conn;
-
-#if API_MSG_DEBUG
-#if TCP_DEBUG
- tcp_debug_print_state(newpcb->state);
-#endif /* TCP_DEBUG */
-#endif /* API_MSG_DEBUG */
- conn = (struct netconn *)arg;
-
- LWIP_ERROR("accept_function: invalid conn->acceptmbox",
- conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);
-
- /* We have to set the callback here even though
- * the new socket is unknown. conn->socket is marked as -1. */
- newconn = netconn_alloc(conn->type, conn->callback);
- if (newconn == NULL) {
- return ERR_MEM;
- }
- newconn->pcb.tcp = newpcb;
- setup_tcp(newconn);
- newconn->err = err;
-
- if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
- /* When returning != ERR_OK, the connection is aborted in tcp_process(),
- so do nothing here! */
- newconn->pcb.tcp = NULL;
- netconn_free(newconn);
- return ERR_MEM;
- } else {
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- }
-
- return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Create a new pcb of a specific type.
- * Called from do_newconn().
- *
- * @param msg the api_msg_msg describing the connection type
- * @return msg->conn->err, but the return value is currently ignored
- */
-static err_t
-pcb_new(struct api_msg_msg *msg)
-{
- msg->conn->err = ERR_OK;
-
- LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
-
- /* Allocate a PCB for this connection */
- switch(NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
- if(msg->conn->pcb.raw == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
- raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->pcb.udp = udp_new();
- if(msg->conn->pcb.udp == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
-#if LWIP_UDPLITE
- if (msg->conn->type==NETCONN_UDPLITE) {
- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
- }
-#endif /* LWIP_UDPLITE */
- if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
- }
- udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->pcb.tcp = tcp_new();
- if(msg->conn->pcb.tcp == NULL) {
- msg->conn->err = ERR_MEM;
- break;
- }
- setup_tcp(msg->conn);
- break;
-#endif /* LWIP_TCP */
- default:
- /* Unsupported netconn type, e.g. protocol disabled */
- msg->conn->err = ERR_VAL;
- break;
- }
-
- return msg->conn->err;
-}
-
-/**
- * Create a new pcb of a specific type inside a netconn.
- * Called from netconn_new_with_proto_and_callback.
- *
- * @param msg the api_msg_msg describing the connection type
- */
-void
-do_newconn(struct api_msg_msg *msg)
-{
- if(msg->conn->pcb.tcp == NULL) {
- pcb_new(msg);
- }
- /* Else? This "new" connection already has a PCB allocated. */
- /* Is this an error condition? Should it be deleted? */
- /* We currently just are happy and return. */
-
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Create a new netconn (of a specific type) that has a callback function.
- * The corresponding pcb is NOT created!
- *
- * @param t the type of 'connection' to create (@see enum netconn_type)
- * @param proto the IP protocol for RAW IP pcbs
- * @param callback a function to call on status changes (RX available, TX'ed)
- * @return a newly allocated struct netconn or
- * NULL on memory error
- */
-struct netconn*
-netconn_alloc(enum netconn_type t, netconn_callback callback)
-{
- struct netconn *conn;
- int size;
-
- conn = memp_malloc(MEMP_NETCONN);
- if (conn == NULL) {
- return NULL;
- }
-
- conn->err = ERR_OK;
- conn->type = t;
- conn->pcb.tcp = NULL;
-
-#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \
- (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE)
- size = DEFAULT_RAW_RECVMBOX_SIZE;
-#else
- switch(NETCONNTYPE_GROUP(t)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- size = DEFAULT_RAW_RECVMBOX_SIZE;
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- size = DEFAULT_UDP_RECVMBOX_SIZE;
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- size = DEFAULT_TCP_RECVMBOX_SIZE;
- break;
-#endif /* LWIP_TCP */
- default:
- LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);
- break;
- }
-#endif
-
- if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) {
- memp_free(MEMP_NETCONN, conn);
- return NULL;
- }
- if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) {
- sys_sem_free(conn->op_completed);
- memp_free(MEMP_NETCONN, conn);
- return NULL;
- }
-
- conn->acceptmbox = SYS_MBOX_NULL;
- conn->state = NETCONN_NONE;
- /* initialize socket to -1 since 0 is a valid socket */
- conn->socket = -1;
- conn->callback = callback;
- conn->recv_avail = 0;
-#if LWIP_TCP
- conn->write_msg = NULL;
- conn->write_offset = 0;
-#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 0;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-#endif /* LWIP_TCP */
-#if LWIP_SO_RCVTIMEO
- conn->recv_timeout = 0;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
- conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
-#endif /* LWIP_SO_RCVBUF */
- return conn;
-}
-
-/**
- * Delete a netconn and all its resources.
- * The pcb is NOT freed (since we might not be in the right thread context do this).
- *
- * @param conn the netconn to free
- */
-void
-netconn_free(struct netconn *conn)
-{
- void *mem;
- LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
-
- /* Drain the recvmbox. */
- if (conn->recvmbox != SYS_MBOX_NULL) {
- while (sys_mbox_tryfetch(conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
- if (conn->type == NETCONN_TCP) {
- if(mem != NULL) {
- pbuf_free((struct pbuf *)mem);
- }
- } else {
- netbuf_delete((struct netbuf *)mem);
- }
- }
- sys_mbox_free(conn->recvmbox);
- conn->recvmbox = SYS_MBOX_NULL;
- }
-
- /* Drain the acceptmbox. */
- if (conn->acceptmbox != SYS_MBOX_NULL) {
- while (sys_mbox_tryfetch(conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
- netconn_delete((struct netconn *)mem);
- }
- sys_mbox_free(conn->acceptmbox);
- conn->acceptmbox = SYS_MBOX_NULL;
- }
-
- sys_sem_free(conn->op_completed);
- conn->op_completed = SYS_SEM_NULL;
-
- memp_free(MEMP_NETCONN, conn);
-}
-
-#if LWIP_TCP
-/**
- * Internal helper function to close a TCP netconn: since this sometimes
- * doesn't work at the first attempt, this function is called from multiple
- * places.
- *
- * @param conn the TCP netconn to close
- */
-static void
-do_close_internal(struct netconn *conn)
-{
- err_t err;
-
- LWIP_ASSERT("invalid conn", (conn != NULL));
- LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));
- LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
- LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
-
- /* Set back some callback pointers */
- tcp_arg(conn->pcb.tcp, NULL);
- if (conn->pcb.tcp->state == LISTEN) {
- tcp_accept(conn->pcb.tcp, NULL);
- } else {
- tcp_recv(conn->pcb.tcp, NULL);
- tcp_accept(conn->pcb.tcp, NULL);
- /* some callbacks have to be reset if tcp_close is not successful */
- tcp_sent(conn->pcb.tcp, NULL);
- tcp_poll(conn->pcb.tcp, NULL, 4);
- tcp_err(conn->pcb.tcp, NULL);
- }
- /* Try to close the connection */
- err = tcp_close(conn->pcb.tcp);
- if (err == ERR_OK) {
- /* Closing succeeded */
- conn->state = NETCONN_NONE;
- /* Set back some callback pointers as conn is going away */
- conn->pcb.tcp = NULL;
- conn->err = ERR_OK;
- /* Trigger select() in socket layer. This send should something else so the
- errorfd is set, not the read and write fd! */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
- API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
- /* wake up the application task */
- sys_sem_signal(conn->op_completed);
- } else {
- /* Closing failed, restore some of the callbacks */
- /* Closing of listen pcb will never fail! */
- LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));
- tcp_sent(conn->pcb.tcp, sent_tcp);
- tcp_poll(conn->pcb.tcp, poll_tcp, 4);
- tcp_err(conn->pcb.tcp, err_tcp);
- tcp_arg(conn->pcb.tcp, conn);
- }
- /* If closing didn't succeed, we get called again either
- from poll_tcp or from sent_tcp */
-}
-#endif /* LWIP_TCP */
-
-/**
- * Delete the pcb inside a netconn.
- * Called from netconn_delete.
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_delconn(struct api_msg_msg *msg)
-{
- if (msg->conn->pcb.tcp != NULL) {
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- raw_remove(msg->conn->pcb.raw);
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->pcb.udp->recv_arg = NULL;
- udp_remove(msg->conn->pcb.udp);
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->state = NETCONN_CLOSE;
- do_close_internal(msg->conn);
- /* API_EVENT is called inside do_close_internal, before releasing
- the application thread, so we can return at this point! */
- return;
-#endif /* LWIP_TCP */
- default:
- break;
- }
- }
- /* tcp netconns don't come here! */
-
- /* Trigger select() in socket layer. This send should something else so the
- errorfd is set, not the read and write fd! */
- API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
- API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
-
- if (msg->conn->op_completed != SYS_SEM_NULL) {
- sys_sem_signal(msg->conn->op_completed);
- }
-}
-
-/**
- * Bind a pcb contained in a netconn
- * Called from netconn_bind.
- *
- * @param msg the api_msg_msg pointing to the connection and containing
- * the IP address and port to bind to
- */
-void
-do_bind(struct api_msg_msg *msg)
-{
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- msg->conn->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);
- break;
-#endif /* LWIP_TCP */
- default:
- break;
- }
- } else {
- /* msg->conn->pcb is NULL */
- msg->conn->err = ERR_VAL;
- }
- }
- TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_TCP
-/**
- * TCP callback function if a connection (opened by tcp_connect/do_connect) has
- * been established (or reset by the remote host).
- *
- * @see tcp.h (struct tcp_pcb.connected) for parameters and return values
- */
-static err_t
-do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
-{
- struct netconn *conn;
-
- LWIP_UNUSED_ARG(pcb);
-
- conn = arg;
-
- if (conn == NULL) {
- return ERR_VAL;
- }
-
- conn->err = err;
- if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
- setup_tcp(conn);
- }
- conn->state = NETCONN_NONE;
- sys_sem_signal(conn->op_completed);
- return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Connect a pcb contained inside a netconn
- * Called from netconn_connect.
- *
- * @param msg the api_msg_msg pointing to the connection and containing
- * the IP address and port to connect to
- */
-void
-do_connect(struct api_msg_msg *msg)
-{
- if (msg->conn->pcb.tcp == NULL) {
- sys_sem_signal(msg->conn->op_completed);
- return;
- }
-
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- msg->conn->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
- sys_sem_signal(msg->conn->op_completed);
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- msg->conn->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
- sys_sem_signal(msg->conn->op_completed);
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- msg->conn->state = NETCONN_CONNECT;
- setup_tcp(msg->conn);
- msg->conn->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
- do_connected);
- /* sys_sem_signal() is called from do_connected (or err_tcp()),
- * when the connection is established! */
- break;
-#endif /* LWIP_TCP */
- default:
- break;
- }
-}
-
-/**
- * Connect a pcb contained inside a netconn
- * Only used for UDP netconns.
- * Called from netconn_disconnect.
- *
- * @param msg the api_msg_msg pointing to the connection to disconnect
- */
-void
-do_disconnect(struct api_msg_msg *msg)
-{
-#if LWIP_UDP
- if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
- udp_disconnect(msg->conn->pcb.udp);
- }
-#endif /* LWIP_UDP */
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Set a TCP pcb contained in a netconn into listen mode
- * Called from netconn_listen.
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_listen(struct api_msg_msg *msg)
-{
-#if LWIP_TCP
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- if (msg->conn->type == NETCONN_TCP) {
- if (msg->conn->pcb.tcp->state == CLOSED) {
-#if TCP_LISTEN_BACKLOG
- struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
-#else /* TCP_LISTEN_BACKLOG */
- struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
-#endif /* TCP_LISTEN_BACKLOG */
- if (lpcb == NULL) {
- msg->conn->err = ERR_MEM;
- } else {
- /* delete the recvmbox and allocate the acceptmbox */
- if (msg->conn->recvmbox != SYS_MBOX_NULL) {
- /** @todo: should we drain the recvmbox here? */
- sys_mbox_free(msg->conn->recvmbox);
- msg->conn->recvmbox = SYS_MBOX_NULL;
- }
- if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
- if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) {
- msg->conn->err = ERR_MEM;
- }
- }
- if (msg->conn->err == ERR_OK) {
- msg->conn->state = NETCONN_LISTEN;
- msg->conn->pcb.tcp = lpcb;
- tcp_arg(msg->conn->pcb.tcp, msg->conn);
- tcp_accept(msg->conn->pcb.tcp, accept_function);
- }
- }
- } else {
- msg->conn->err = ERR_CONN;
- }
- }
- }
- }
-#endif /* LWIP_TCP */
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Send some data on a RAW or UDP pcb contained in a netconn
- * Called from netconn_send
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_send(struct api_msg_msg *msg)
-{
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- if (msg->msg.b->addr == NULL) {
- msg->conn->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
- } else {
- msg->conn->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
- }
- break;
-#endif
-#if LWIP_UDP
- case NETCONN_UDP:
- if (msg->msg.b->addr == NULL) {
- msg->conn->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
- } else {
- msg->conn->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
- }
- break;
-#endif /* LWIP_UDP */
- default:
- break;
- }
- }
- }
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Indicate data has been received from a TCP pcb contained in a netconn
- * Called from netconn_recv
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_recv(struct api_msg_msg *msg)
-{
-#if LWIP_TCP
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- if (msg->conn->type == NETCONN_TCP) {
-#if TCP_LISTEN_BACKLOG
- if (msg->conn->pcb.tcp->state == LISTEN) {
- tcp_accepted(msg->conn->pcb.tcp);
- } else
-#endif /* TCP_LISTEN_BACKLOG */
- {
- tcp_recved(msg->conn->pcb.tcp, msg->msg.r.len);
- }
- }
- }
- }
-#endif /* LWIP_TCP */
- TCPIP_APIMSG_ACK(msg);
-}
-
-#if LWIP_TCP
-/**
- * See if more data needs to be written from a previous call to netconn_write.
- * Called initially from do_write. If the first call can't send all data
- * (because of low memory or empty send-buffer), this function is called again
- * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
- * blocking application thread (waiting in netconn_write) is released.
- *
- * @param conn netconn (that is currently in state NETCONN_WRITE) to process
- * @return ERR_OK
- * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
- */
-static err_t
-do_writemore(struct netconn *conn)
-{
- err_t err;
- void *dataptr;
- u16_t len, available;
- u8_t write_finished = 0;
- size_t diff;
-
- LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
-
- dataptr = (u8_t*)conn->write_msg->msg.w.dataptr + conn->write_offset;
- diff = conn->write_msg->msg.w.len - conn->write_offset;
- if (diff > 0xffffUL) { /* max_u16_t */
- len = 0xffff;
-#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
-#endif
- } else {
- len = (u16_t)diff;
- }
- available = tcp_sndbuf(conn->pcb.tcp);
- if (available < len) {
- /* don't try to write more than sendbuf */
- len = available;
-#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
-#endif
- }
-
- err = tcp_write(conn->pcb.tcp, dataptr, len, conn->write_msg->msg.w.apiflags);
- LWIP_ASSERT("do_writemore: invalid length!", ((conn->write_offset + len) <= conn->write_msg->msg.w.len));
- if (err == ERR_OK) {
- conn->write_offset += len;
- if (conn->write_offset == conn->write_msg->msg.w.len) {
- /* everything was written */
- write_finished = 1;
- conn->write_msg = NULL;
- conn->write_offset = 0;
- /* API_EVENT might call tcp_tmr, so reset conn->state now */
- conn->state = NETCONN_NONE;
- }
- err = tcp_output_nagle(conn->pcb.tcp);
- conn->err = err;
- if ((err == ERR_OK) && (tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT)) {
- API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
- }
- } else if (err == ERR_MEM) {
- /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
- we do NOT return to the application thread, since ERR_MEM is
- only a temporary error! */
-
- /* tcp_enqueue returned ERR_MEM, try tcp_output anyway */
- err = tcp_output(conn->pcb.tcp);
-
-#if LWIP_TCPIP_CORE_LOCKING
- conn->write_delayed = 1;
-#endif
- } else {
- /* On errors != ERR_MEM, we don't try writing any more but return
- the error to the application thread. */
- conn->err = err;
- write_finished = 1;
- }
-
- if (write_finished) {
- /* everything was written: set back connection state
- and back to application task */
- conn->state = NETCONN_NONE;
-#if LWIP_TCPIP_CORE_LOCKING
- if (conn->write_delayed != 0)
-#endif
- {
- sys_sem_signal(conn->op_completed);
- }
- }
-#if LWIP_TCPIP_CORE_LOCKING
- else
- return ERR_MEM;
-#endif
- return ERR_OK;
-}
-#endif /* LWIP_TCP */
-
-/**
- * Send some data on a TCP pcb contained in a netconn
- * Called from netconn_write
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_write(struct api_msg_msg *msg)
-{
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
-#if LWIP_TCP
- msg->conn->state = NETCONN_WRITE;
- /* set all the variables used by do_writemore */
- LWIP_ASSERT("already writing", msg->conn->write_msg == NULL &&
- msg->conn->write_offset == 0);
- msg->conn->write_msg = msg;
- msg->conn->write_offset = 0;
-#if LWIP_TCPIP_CORE_LOCKING
- msg->conn->write_delayed = 0;
- if (do_writemore(msg->conn) != ERR_OK) {
- LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
- UNLOCK_TCPIP_CORE();
- sys_arch_sem_wait(msg->conn->op_completed, 0);
- LOCK_TCPIP_CORE();
- LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
- }
-#else
- do_writemore(msg->conn);
-#endif
- /* for both cases: if do_writemore was called, don't ACK the APIMSG! */
- return;
-#endif /* LWIP_TCP */
-#if (LWIP_UDP || LWIP_RAW)
- } else {
- msg->conn->err = ERR_VAL;
-#endif /* (LWIP_UDP || LWIP_RAW) */
- }
- }
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Return a connection's local or remote address
- * Called from netconn_getaddr
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_getaddr(struct api_msg_msg *msg)
-{
- if (msg->conn->pcb.ip != NULL) {
- *(msg->msg.ad.ipaddr) = (msg->msg.ad.local?msg->conn->pcb.ip->local_ip:msg->conn->pcb.ip->remote_ip);
-
- switch (NETCONNTYPE_GROUP(msg->conn->type)) {
-#if LWIP_RAW
- case NETCONN_RAW:
- if (msg->msg.ad.local) {
- *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
- } else {
- /* return an error as connecting is only a helper for upper layers */
- msg->conn->err = ERR_CONN;
- }
- break;
-#endif /* LWIP_RAW */
-#if LWIP_UDP
- case NETCONN_UDP:
- if (msg->msg.ad.local) {
- *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
- } else {
- if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
- msg->conn->err = ERR_CONN;
- } else {
- *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
- }
- }
- break;
-#endif /* LWIP_UDP */
-#if LWIP_TCP
- case NETCONN_TCP:
- *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port);
- break;
-#endif /* LWIP_TCP */
- }
- } else {
- msg->conn->err = ERR_CONN;
- }
- TCPIP_APIMSG_ACK(msg);
-}
-
-/**
- * Close a TCP pcb contained in a netconn
- * Called from netconn_close
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_close(struct api_msg_msg *msg)
-{
-#if LWIP_TCP
- if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
- msg->conn->state = NETCONN_CLOSE;
- do_close_internal(msg->conn);
- /* for tcp netconns, do_close_internal ACKs the message */
- } else
-#endif /* LWIP_TCP */
- {
- msg->conn->err = ERR_VAL;
- TCPIP_APIMSG_ACK(msg);
- }
-}
-
-#if LWIP_IGMP
-/**
- * Join multicast groups for UDP netconns.
- * Called from netconn_join_leave_group
- *
- * @param msg the api_msg_msg pointing to the connection
- */
-void
-do_join_leave_group(struct api_msg_msg *msg)
-{
- if (!ERR_IS_FATAL(msg->conn->err)) {
- if (msg->conn->pcb.tcp != NULL) {
- if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
-#if LWIP_UDP
- if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
- msg->conn->err = igmp_joingroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
- } else {
- msg->conn->err = igmp_leavegroup(msg->msg.jl.interface, msg->msg.jl.multiaddr);
- }
-#endif /* LWIP_UDP */
-#if (LWIP_TCP || LWIP_RAW)
- } else {
- msg->conn->err = ERR_VAL;
-#endif /* (LWIP_TCP || LWIP_RAW) */
- }
- }
- }
- TCPIP_APIMSG_ACK(msg);
-}
-#endif /* LWIP_IGMP */
-
-#if LWIP_DNS
-/**
- * Callback function that is called when DNS name is resolved
- * (or on timeout). A waiting application thread is waked up by
- * signaling the semaphore.
- */
-static void
-do_dns_found(const char *name, struct ip_addr *ipaddr, void *arg)
-{
- struct dns_api_msg *msg = (struct dns_api_msg*)arg;
-
- LWIP_ASSERT("DNS response for wrong host name", strcmp(msg->name, name) == 0);
-
- if (ipaddr == NULL) {
- /* timeout or memory error */
- *msg->err = ERR_VAL;
- } else {
- /* address was resolved */
- *msg->err = ERR_OK;
- *msg->addr = *ipaddr;
- }
- /* wake up the application task waiting in netconn_gethostbyname */
- sys_sem_signal(msg->sem);
-}
-
-/**
- * Execute a DNS query
- * Called from netconn_gethostbyname
- *
- * @param arg the dns_api_msg pointing to the query
- */
-void
-do_gethostbyname(void *arg)
-{
- struct dns_api_msg *msg = (struct dns_api_msg*)arg;
-
- *msg->err = dns_gethostbyname(msg->name, msg->addr, do_dns_found, msg);
- if (*msg->err != ERR_INPROGRESS) {
- /* on error or immediate success, wake up the application
- * task waiting in netconn_gethostbyname */
- sys_sem_signal(msg->sem);
- }
-}
-#endif /* LWIP_DNS */
-
-#endif /* LWIP_NETCONN */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/err.c b/firmware/x300/lwip/lwip-1.3.1/src/api/err.c
deleted file mode 100644
index a90cb98c8..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/err.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @file
- * Error Management module
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/err.h"
-
-#ifdef LWIP_DEBUG
-
-static const char *err_strerr[] = {
- "Ok.", /* ERR_OK 0 */
- "Out of memory error.", /* ERR_MEM -1 */
- "Buffer error.", /* ERR_BUF -2 */
- "Timeout.", /* ERR_TIMEOUT -3 */
- "Routing problem.", /* ERR_RTE -4 */
- "Connection aborted.", /* ERR_ABRT -5 */
- "Connection reset.", /* ERR_RST -6 */
- "Connection closed.", /* ERR_CLSD -7 */
- "Not connected.", /* ERR_CONN -8 */
- "Illegal value.", /* ERR_VAL -9 */
- "Illegal argument.", /* ERR_ARG -10 */
- "Address in use.", /* ERR_USE -11 */
- "Low-level netif error.", /* ERR_IF -12 */
- "Already connected.", /* ERR_ISCONN -13 */
- "Operation in progress." /* ERR_INPROGRESS -14 */
-};
-
-/**
- * Convert an lwip internal error to a string representation.
- *
- * @param err an lwip internal err_t
- * @return a string representation for err
- */
-const char *
-lwip_strerr(err_t err)
-{
- return err_strerr[-err];
-
-}
-
-#endif /* LWIP_DEBUG */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/netbuf.c b/firmware/x300/lwip/lwip-1.3.1/src/api/netbuf.c
deleted file mode 100644
index af44eefc7..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/netbuf.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/**
- * @file
- * Network buffer management
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/netbuf.h"
-#include "lwip/memp.h"
-
-#include <string.h>
-
-/**
- * Create (allocate) and initialize a new netbuf.
- * The netbuf doesn't yet contain a packet buffer!
- *
- * @return a pointer to a new netbuf
- * NULL on lack of memory
- */
-struct
-netbuf *netbuf_new(void)
-{
- struct netbuf *buf;
-
- buf = memp_malloc(MEMP_NETBUF);
- if (buf != NULL) {
- buf->p = NULL;
- buf->ptr = NULL;
- buf->addr = NULL;
- return buf;
- } else {
- return NULL;
- }
-}
-
-/**
- * Deallocate a netbuf allocated by netbuf_new().
- *
- * @param buf pointer to a netbuf allocated by netbuf_new()
- */
-void
-netbuf_delete(struct netbuf *buf)
-{
- if (buf != NULL) {
- if (buf->p != NULL) {
- pbuf_free(buf->p);
- buf->p = buf->ptr = NULL;
- }
- memp_free(MEMP_NETBUF, buf);
- }
-}
-
-/**
- * Allocate memory for a packet buffer for a given netbuf.
- *
- * @param buf the netbuf for which to allocate a packet buffer
- * @param size the size of the packet buffer to allocate
- * @return pointer to the allocated memory
- * NULL if no memory could be allocated
- */
-void *
-netbuf_alloc(struct netbuf *buf, u16_t size)
-{
- LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;);
-
- /* Deallocate any previously allocated memory. */
- if (buf->p != NULL) {
- pbuf_free(buf->p);
- }
- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
- if (buf->p == NULL) {
- return NULL;
- }
- LWIP_ASSERT("check that first pbuf can hold size",
- (buf->p->len >= size));
- buf->ptr = buf->p;
- return buf->p->payload;
-}
-
-/**
- * Free the packet buffer included in a netbuf
- *
- * @param buf pointer to the netbuf which contains the packet buffer to free
- */
-void
-netbuf_free(struct netbuf *buf)
-{
- LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
- if (buf->p != NULL) {
- pbuf_free(buf->p);
- }
- buf->p = buf->ptr = NULL;
-}
-
-/**
- * Let a netbuf reference existing (non-volatile) data.
- *
- * @param buf netbuf which should reference the data
- * @param dataptr pointer to the data to reference
- * @param size size of the data
- * @return ERR_OK if data is referenced
- * ERR_MEM if data couldn't be referenced due to lack of memory
- */
-err_t
-netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size)
-{
- LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;);
- if (buf->p != NULL) {
- pbuf_free(buf->p);
- }
- buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
- if (buf->p == NULL) {
- buf->ptr = NULL;
- return ERR_MEM;
- }
- buf->p->payload = (void*)dataptr;
- buf->p->len = buf->p->tot_len = size;
- buf->ptr = buf->p;
- return ERR_OK;
-}
-
-/**
- * Chain one netbuf to another (@see pbuf_chain)
- *
- * @param head the first netbuf
- * @param tail netbuf to chain after head, freed by this function, may not be reference after returning
- */
-void
-netbuf_chain(struct netbuf *head, struct netbuf *tail)
-{
- LWIP_ERROR("netbuf_ref: invalid head", (head != NULL), return;);
- LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;);
- pbuf_cat(head->p, tail->p);
- head->ptr = head->p;
- memp_free(MEMP_NETBUF, tail);
-}
-
-/**
- * Get the data pointer and length of the data inside a netbuf.
- *
- * @param buf netbuf to get the data from
- * @param dataptr pointer to a void pointer where to store the data pointer
- * @param len pointer to an u16_t where the length of the data is stored
- * @return ERR_OK if the information was retreived,
- * ERR_BUF on error.
- */
-err_t
-netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
-{
- LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);
- LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);
- LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);
-
- if (buf->ptr == NULL) {
- return ERR_BUF;
- }
- *dataptr = buf->ptr->payload;
- *len = buf->ptr->len;
- return ERR_OK;
-}
-
-/**
- * Move the current data pointer of a packet buffer contained in a netbuf
- * to the next part.
- * The packet buffer itself is not modified.
- *
- * @param buf the netbuf to modify
- * @return -1 if there is no next part
- * 1 if moved to the next part but now there is no next part
- * 0 if moved to the next part and there are still more parts
- */
-s8_t
-netbuf_next(struct netbuf *buf)
-{
- LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return -1;);
- if (buf->ptr->next == NULL) {
- return -1;
- }
- buf->ptr = buf->ptr->next;
- if (buf->ptr->next == NULL) {
- return 1;
- }
- return 0;
-}
-
-/**
- * Move the current data pointer of a packet buffer contained in a netbuf
- * to the beginning of the packet.
- * The packet buffer itself is not modified.
- *
- * @param buf the netbuf to modify
- */
-void
-netbuf_first(struct netbuf *buf)
-{
- LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;);
- buf->ptr = buf->p;
-}
-
-#endif /* LWIP_NETCONN */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/netdb.c b/firmware/x300/lwip/lwip-1.3.1/src/api/netdb.c
deleted file mode 100644
index 8aa237f4c..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/netdb.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/**
- * @file
- * API functions for name resolving
- *
- */
-
-/*
- * 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Simon Goldschmidt
- *
- */
-
-#include "lwip/netdb.h"
-
-#if LWIP_DNS && LWIP_SOCKET
-
-#include "lwip/err.h"
-#include "lwip/mem.h"
-#include "lwip/ip_addr.h"
-#include "lwip/api.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-/** helper struct for gethostbyname_r to access the char* buffer */
-struct gethostbyname_r_helper {
- struct ip_addr *addrs;
- struct ip_addr addr;
- char *aliases;
-};
-
-/** h_errno is exported in netdb.h for access by applications. */
-#if LWIP_DNS_API_DECLARE_H_ERRNO
-int h_errno;
-#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */
-
-/** define "hostent" variables storage: 0 if we use a static (but unprotected)
- * set of variables for lwip_gethostbyname, 1 if we use a local storage */
-#ifndef LWIP_DNS_API_HOSTENT_STORAGE
-#define LWIP_DNS_API_HOSTENT_STORAGE 0
-#endif
-
-/** define "hostent" variables storage */
-#if LWIP_DNS_API_HOSTENT_STORAGE
-#define HOSTENT_STORAGE
-#else
-#define HOSTENT_STORAGE static
-#endif /* LWIP_DNS_API_STATIC_HOSTENT */
-
-/**
- * Returns an entry containing addresses of address family AF_INET
- * for the host with name name.
- * Due to dns_gethostbyname limitations, only one address is returned.
- *
- * @param name the hostname to resolve
- * @return an entry containing addresses of address family AF_INET
- * for the host with name name
- */
-struct hostent*
-lwip_gethostbyname(const char *name)
-{
- err_t err;
- struct ip_addr addr;
-
- /* buffer variables for lwip_gethostbyname() */
- HOSTENT_STORAGE struct hostent s_hostent;
- HOSTENT_STORAGE char *s_aliases;
- HOSTENT_STORAGE struct ip_addr s_hostent_addr;
- HOSTENT_STORAGE struct ip_addr *s_phostent_addr;
-
- /* query host IP address */
- err = netconn_gethostbyname(name, &addr);
- if (err != ERR_OK) {
- LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
- h_errno = HOST_NOT_FOUND;
- return NULL;
- }
-
- /* fill hostent */
- s_hostent_addr = addr;
- s_phostent_addr = &s_hostent_addr;
- s_hostent.h_name = (char*)name;
- s_hostent.h_aliases = &s_aliases;
- s_hostent.h_addrtype = AF_INET;
- s_hostent.h_length = sizeof(struct ip_addr);
- s_hostent.h_addr_list = (char**)&s_phostent_addr;
-
-#if DNS_DEBUG
- /* dump hostent */
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", s_hostent.h_aliases));
- if (s_hostent.h_aliases != NULL) {
- u8_t idx;
- for ( idx=0; s_hostent.h_aliases[idx]; idx++) {
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %p\n", idx, s_hostent.h_aliases[idx]));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases[%i]-> == %s\n", idx, s_hostent.h_aliases[idx]));
- }
- }
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", s_hostent.h_addr_list));
- if (s_hostent.h_addr_list != NULL) {
- u8_t idx;
- for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
- LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, inet_ntoa(*((struct in_addr*)(s_hostent.h_addr_list[idx])))));
- }
- }
-#endif /* DNS_DEBUG */
-
-#if LWIP_DNS_API_HOSTENT_STORAGE
- /* this function should return the "per-thread" hostent after copy from s_hostent */
- return sys_thread_hostent(&s_hostent);
-#else
- return &s_hostent;
-#endif /* LWIP_DNS_API_HOSTENT_STORAGE */
-}
-
-/**
- * Thread-safe variant of lwip_gethostbyname: instead of using a static
- * buffer, this function takes buffer and errno pointers as arguments
- * and uses these for the result.
- *
- * @param name the hostname to resolve
- * @param ret pre-allocated struct where to store the result
- * @param buf pre-allocated buffer where to store additional data
- * @param buflen the size of buf
- * @param result pointer to a hostent pointer that is set to ret on success
- * and set to zero on error
- * @param h_errnop pointer to an int where to store errors (instead of modifying
- * the global h_errno)
- * @return 0 on success, non-zero on error, additional error information
- * is stored in *h_errnop instead of h_errno to be thread-safe
- */
-int
-lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
- size_t buflen, struct hostent **result, int *h_errnop)
-{
- err_t err;
- struct gethostbyname_r_helper *h;
- char *hostname;
- size_t namelen;
- int lh_errno;
-
- if (h_errnop == NULL) {
- /* ensure h_errnop is never NULL */
- h_errnop = &lh_errno;
- }
-
- if (result == NULL) {
- /* not all arguments given */
- *h_errnop = EINVAL;
- return -1;
- }
- /* first thing to do: set *result to nothing */
- *result = NULL;
- if ((name == NULL) || (ret == NULL) || (buf == 0)) {
- /* not all arguments given */
- *h_errnop = EINVAL;
- return -1;
- }
-
- namelen = strlen(name);
- if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) {
- /* buf can't hold the data needed + a copy of name */
- *h_errnop = ERANGE;
- return -1;
- }
-
- h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf);
- hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
-
- /* query host IP address */
- err = netconn_gethostbyname(name, &(h->addr));
- if (err != ERR_OK) {
- LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
- *h_errnop = ENSRNOTFOUND;
- return -1;
- }
-
- /* copy the hostname into buf */
- MEMCPY(hostname, name, namelen);
- hostname[namelen] = 0;
-
- /* fill hostent */
- h->addrs = &(h->addr);
- h->aliases = NULL;
- ret->h_name = (char*)hostname;
- ret->h_aliases = &(h->aliases);
- ret->h_addrtype = AF_INET;
- ret->h_length = sizeof(struct ip_addr);
- ret->h_addr_list = (char**)&(h->addrs);
-
- /* set result != NULL */
- *result = ret;
-
- /* return success */
- return 0;
-}
-
-/**
- * Frees one or more addrinfo structures returned by getaddrinfo(), along with
- * any additional storage associated with those structures. If the ai_next field
- * of the structure is not null, the entire list of structures is freed.
- *
- * @param ai struct addrinfo to free
- */
-void
-lwip_freeaddrinfo(struct addrinfo *ai)
-{
- struct addrinfo *next;
-
- while (ai != NULL) {
- if (ai->ai_addr != NULL) {
- mem_free(ai->ai_addr);
- }
- if (ai->ai_canonname != NULL) {
- mem_free(ai->ai_canonname);
- }
- next = ai->ai_next;
- mem_free(ai);
- ai = next;
- }
-}
-
-/**
- * Translates the name of a service location (for example, a host name) and/or
- * a service name and returns a set of socket addresses and associated
- * information to be used in creating a socket with which to address the
- * specified service.
- * Memory for the result is allocated internally and must be freed by calling
- * lwip_freeaddrinfo()!
- *
- * Due to a limitation in dns_gethostbyname, only the first address of a
- * host is returned.
- * Also, service names are not supported (only port numbers)!
- *
- * @param nodename descriptive name or address string of the host
- * (may be NULL -> local address)
- * @param servname port number as string of NULL
- * @param hints structure containing input values that set socktype and protocol
- * @param res pointer to a pointer where to store the result (set to NULL on failure)
- * @return 0 on success, non-zero on failure
- */
-int
-lwip_getaddrinfo(const char *nodename, const char *servname,
- const struct addrinfo *hints, struct addrinfo **res)
-{
- err_t err;
- struct ip_addr addr;
- struct addrinfo *ai;
- struct sockaddr_in *sa = NULL;
- int port_nr = 0;
-
- if (res == NULL) {
- return EAI_FAIL;
- }
- *res = NULL;
- if ((nodename == NULL) && (servname == NULL)) {
- return EAI_NONAME;
- }
-
- if (servname != NULL) {
- /* service name specified: convert to port number
- * @todo?: currently, only ASCII integers (port numbers) are supported! */
- port_nr = atoi(servname);
- if ((port_nr <= 0) || (port_nr > 0xffff)) {
- return EAI_SERVICE;
- }
- }
-
- if (nodename != NULL) {
- /* service location specified, try to resolve */
- err = netconn_gethostbyname(nodename, &addr);
- if (err != ERR_OK) {
- return EAI_FAIL;
- }
- } else {
- /* service location specified, use loopback address */
- addr.addr = INADDR_LOOPBACK;
- }
-
- ai = mem_malloc(sizeof(struct addrinfo));
- if (ai == NULL) {
- goto memerr;
- }
- memset(ai, 0, sizeof(struct addrinfo));
- sa = mem_malloc(sizeof(struct sockaddr_in));
- if (sa == NULL) {
- goto memerr;
- }
- memset(sa, 0, sizeof(struct sockaddr_in));
- /* set up sockaddr */
- sa->sin_addr.s_addr = addr.addr;
- sa->sin_family = AF_INET;
- sa->sin_len = sizeof(struct sockaddr_in);
- sa->sin_port = htons(port_nr);
-
- /* set up addrinfo */
- ai->ai_family = AF_INET;
- if (hints != NULL) {
- /* copy socktype & protocol from hints if specified */
- ai->ai_socktype = hints->ai_socktype;
- ai->ai_protocol = hints->ai_protocol;
- }
- if (nodename != NULL) {
- /* copy nodename to canonname if specified */
- size_t namelen = strlen(nodename);
- LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
- ai->ai_canonname = mem_malloc((mem_size_t)(namelen + 1));
- if (ai->ai_canonname == NULL) {
- goto memerr;
- }
- MEMCPY(ai->ai_canonname, nodename, namelen);
- ai->ai_canonname[namelen] = 0;
- }
- ai->ai_addrlen = sizeof(struct sockaddr_in);
- ai->ai_addr = (struct sockaddr*)sa;
-
- *res = ai;
-
- return 0;
-memerr:
- if (ai != NULL) {
- mem_free(ai);
- }
- if (sa != NULL) {
- mem_free(sa);
- }
- return EAI_MEMORY;
-}
-
-#endif /* LWIP_DNS && LWIP_SOCKET */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/netifapi.c b/firmware/x300/lwip/lwip-1.3.1/src/api/netifapi.c
deleted file mode 100644
index 491837378..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/netifapi.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * @file
- * Network Interface Sequential API module
- *
- */
-
-/*
- * 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/netifapi.h"
-#include "lwip/tcpip.h"
-
-/**
- * Call netif_add() inside the tcpip_thread context.
- */
-void
-do_netifapi_netif_add( struct netifapi_msg_msg *msg)
-{
- if (!netif_add( msg->netif,
- msg->msg.add.ipaddr,
- msg->msg.add.netmask,
- msg->msg.add.gw,
- msg->msg.add.state,
- msg->msg.add.init,
- msg->msg.add.input)) {
- msg->err = ERR_IF;
- } else {
- msg->err = ERR_OK;
- }
- TCPIP_NETIFAPI_ACK(msg);
-}
-
-/**
- * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the
- * tcpip_thread context.
- */
-void
-do_netifapi_netif_common( struct netifapi_msg_msg *msg)
-{
- if (msg->msg.common.errtfunc!=NULL) {
- msg->err =
- msg->msg.common.errtfunc(msg->netif);
- } else {
- msg->err = ERR_OK;
- msg->msg.common.voidfunc(msg->netif);
- }
- TCPIP_NETIFAPI_ACK(msg);
-}
-
-/**
- * Call netif_add() in a thread-safe way by running that function inside the
- * tcpip_thread context.
- *
- * @note for params @see netif_add()
- */
-err_t
-netifapi_netif_add(struct netif *netif,
- struct ip_addr *ipaddr,
- struct ip_addr *netmask,
- struct ip_addr *gw,
- void *state,
- err_t (* init)(struct netif *netif),
- err_t (* input)(struct pbuf *p, struct netif *netif))
-{
- struct netifapi_msg msg;
- msg.function = do_netifapi_netif_add;
- msg.msg.netif = netif;
- msg.msg.msg.add.ipaddr = ipaddr;
- msg.msg.msg.add.netmask = netmask;
- msg.msg.msg.add.gw = gw;
- msg.msg.msg.add.state = state;
- msg.msg.msg.add.init = init;
- msg.msg.msg.add.input = input;
- TCPIP_NETIFAPI(&msg);
- return msg.msg.err;
-}
-
-/**
- * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe
- * way by running that function inside the tcpip_thread context.
- *
- * @note use only for functions where there is only "netif" parameter.
- */
-err_t
-netifapi_netif_common( struct netif *netif,
- void (* voidfunc)(struct netif *netif),
- err_t (* errtfunc)(struct netif *netif) )
-{
- struct netifapi_msg msg;
- msg.function = do_netifapi_netif_common;
- msg.msg.netif = netif;
- msg.msg.msg.common.voidfunc = voidfunc;
- msg.msg.msg.common.errtfunc = errtfunc;
- TCPIP_NETIFAPI(&msg);
- return msg.msg.err;
-}
-
-#endif /* LWIP_NETIF_API */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/sockets.c b/firmware/x300/lwip/lwip-1.3.1/src/api/sockets.c
deleted file mode 100644
index f177261e1..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/sockets.c
+++ /dev/null
@@ -1,1970 +0,0 @@
-/**
- * @file
- * Sockets BSD-Like API module
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
- *
- */
-
-#include "lwip/opt.h"
-
-#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/sockets.h"
-#include "lwip/api.h"
-#include "lwip/sys.h"
-#include "lwip/igmp.h"
-#include "lwip/inet.h"
-#include "lwip/tcp.h"
-#include "lwip/raw.h"
-#include "lwip/udp.h"
-#include "lwip/tcpip.h"
-
-#include <string.h>
-
-#define NUM_SOCKETS MEMP_NUM_NETCONN
-
-/** Contains all internal pointers and states used for a socket */
-struct lwip_socket {
- /** sockets currently are built on netconns, each socket has one netconn */
- struct netconn *conn;
- /** data that was left from the previous read */
- struct netbuf *lastdata;
- /** offset in the data that was left from the previous read */
- u16_t lastoffset;
- /** number of times data was received, set by event_callback(),
- tested by the receive and select functions */
- s16_t rcvevent;
- /** number of times data was received, set by event_callback(),
- tested by select */
- u16_t sendevent;
- /** socket flags (currently, only used for O_NONBLOCK) */
- u16_t flags;
- /** last error that occurred on this socket */
- int err;
-};
-
-/** Description for a task waiting in select */
-struct lwip_select_cb {
- /** Pointer to the next waiting task */
- struct lwip_select_cb *next;
- /** readset passed to select */
- fd_set *readset;
- /** writeset passed to select */
- fd_set *writeset;
- /** unimplemented: exceptset passed to select */
- fd_set *exceptset;
- /** don't signal the same semaphore twice: set to 1 when signalled */
- int sem_signalled;
- /** semaphore to wake up a task waiting for select */
- sys_sem_t sem;
-};
-
-/** This struct is used to pass data to the set/getsockopt_internal
- * functions running in tcpip_thread context (only a void* is allowed) */
-struct lwip_setgetsockopt_data {
- /** socket struct for which to change options */
- struct lwip_socket *sock;
- /** socket index for which to change options */
- int s;
- /** level of the option to process */
- int level;
- /** name of the option to process */
- int optname;
- /** set: value to set the option to
- * get: value of the option is stored here */
- void *optval;
- /** size of *optval */
- socklen_t *optlen;
- /** if an error occures, it is temporarily stored here */
- err_t err;
-};
-
-/** The global array of available sockets */
-static struct lwip_socket sockets[NUM_SOCKETS];
-/** The global list of tasks waiting for select */
-static struct lwip_select_cb *select_cb_list;
-
-/** Semaphore protecting the sockets array */
-static sys_sem_t socksem;
-/** Semaphore protecting select_cb_list */
-static sys_sem_t selectsem;
-
-/** Table to quickly map an lwIP error (err_t) to a socket error
- * by using -err as an index */
-static const int err_to_errno_table[] = {
- 0, /* ERR_OK 0 No error, everything OK. */
- ENOMEM, /* ERR_MEM -1 Out of memory error. */
- ENOBUFS, /* ERR_BUF -2 Buffer error. */
- ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */
- EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
- ECONNABORTED, /* ERR_ABRT -5 Connection aborted. */
- ECONNRESET, /* ERR_RST -6 Connection reset. */
- ESHUTDOWN, /* ERR_CLSD -7 Connection closed. */
- ENOTCONN, /* ERR_CONN -8 Not connected. */
- EINVAL, /* ERR_VAL -9 Illegal value. */
- EIO, /* ERR_ARG -10 Illegal argument. */
- EADDRINUSE, /* ERR_USE -11 Address in use. */
- -1, /* ERR_IF -12 Low-level netif error */
- -1, /* ERR_ISCONN -13 Already connected. */
- EINPROGRESS /* ERR_INPROGRESS -14 Operation in progress */
-};
-
-#define ERR_TO_ERRNO_TABLE_SIZE \
- (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
-
-#define err_to_errno(err) \
- ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
- err_to_errno_table[-(err)] : EIO)
-
-#ifdef ERRNO
-#ifndef set_errno
-#define set_errno(err) errno = (err)
-#endif
-#else
-#define set_errno(err)
-#endif
-
-#define sock_set_errno(sk, e) do { \
- sk->err = (e); \
- set_errno(sk->err); \
-} while (0)
-
-/* Forward delcaration of some functions */
-static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
-static void lwip_getsockopt_internal(void *arg);
-static void lwip_setsockopt_internal(void *arg);
-
-/**
- * Initialize this module. This function has to be called before any other
- * functions in this module!
- */
-void
-lwip_socket_init(void)
-{
- socksem = sys_sem_new(1);
- selectsem = sys_sem_new(1);
-}
-
-/**
- * Map a externally used socket index to the internal socket representation.
- *
- * @param s externally used socket index
- * @return struct lwip_socket for the socket or NULL if not found
- */
-static struct lwip_socket *
-get_socket(int s)
-{
- struct lwip_socket *sock;
-
- if ((s < 0) || (s >= NUM_SOCKETS)) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
- set_errno(EBADF);
- return NULL;
- }
-
- sock = &sockets[s];
-
- if (!sock->conn) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
- set_errno(EBADF);
- return NULL;
- }
-
- return sock;
-}
-
-/**
- * Allocate a new socket for a given netconn.
- *
- * @param newconn the netconn for which to allocate a socket
- * @return the index of the new socket; -1 on error
- */
-static int
-alloc_socket(struct netconn *newconn)
-{
- int i;
-
- /* Protect socket array */
- sys_sem_wait(socksem);
-
- /* allocate a new socket identifier */
- for (i = 0; i < NUM_SOCKETS; ++i) {
- if (!sockets[i].conn) {
- sockets[i].conn = newconn;
- sockets[i].lastdata = NULL;
- sockets[i].lastoffset = 0;
- sockets[i].rcvevent = 0;
- sockets[i].sendevent = 1; /* TCP send buf is empty */
- sockets[i].flags = 0;
- sockets[i].err = 0;
- sys_sem_signal(socksem);
- return i;
- }
- }
- sys_sem_signal(socksem);
- return -1;
-}
-
-/* Below this, the well-known socket functions are implemented.
- * Use google.com or opengroup.org to get a good description :-)
- *
- * Exceptions are documented!
- */
-
-int
-lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- struct lwip_socket *sock, *nsock;
- struct netconn *newconn;
- struct ip_addr naddr;
- u16_t port;
- int newsock;
- struct sockaddr_in sin;
- err_t err;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
- sock_set_errno(sock, EWOULDBLOCK);
- return -1;
- }
-
- newconn = netconn_accept(sock->conn);
- if (!newconn) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) failed, err=%d\n", s, sock->conn->err));
- sock_set_errno(sock, err_to_errno(sock->conn->err));
- return -1;
- }
-
- /* get the IP address and port of the remote host */
- err = netconn_peer(newconn, &naddr, &port);
- if (err != ERR_OK) {
- netconn_delete(newconn);
- sock_set_errno(sock, err_to_errno(err));
- return -1;
- }
-
- /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
- * not be NULL if addr is valid.
- */
- if (NULL != addr) {
- LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = naddr.addr;
-
- if (*addrlen > sizeof(sin))
- *addrlen = sizeof(sin);
-
- MEMCPY(addr, &sin, *addrlen);
- }
-
- newsock = alloc_socket(newconn);
- if (newsock == -1) {
- netconn_delete(newconn);
- sock_set_errno(sock, ENFILE);
- return -1;
- }
- LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
- newconn->callback = event_callback;
- nsock = &sockets[newsock];
- LWIP_ASSERT("invalid socket pointer", nsock != NULL);
-
- sys_sem_wait(socksem);
- /* See event_callback: If data comes in right away after an accept, even
- * though the server task might not have created a new socket yet.
- * In that case, newconn->socket is counted down (newconn->socket--),
- * so nsock->rcvevent is >= 1 here!
- */
- nsock->rcvevent += -1 - newconn->socket;
- newconn->socket = newsock;
- sys_sem_signal(socksem);
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
- ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
-
- sock_set_errno(sock, 0);
- return newsock;
-}
-
-int
-lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
-{
- struct lwip_socket *sock;
- struct ip_addr local_addr;
- u16_t local_port;
- err_t err;
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
- sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
- local_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
- local_port = ((const struct sockaddr_in *)name)->sin_port;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
- ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
-
- err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
-
- if (err != ERR_OK) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
- sock_set_errno(sock, err_to_errno(err));
- return -1;
- }
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
- sock_set_errno(sock, 0);
- return 0;
-}
-
-int
-lwip_close(int s)
-{
- struct lwip_socket *sock;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
-
- sock = get_socket(s);
- if (!sock) {
- return -1;
- }
-
- netconn_delete(sock->conn);
-
- sys_sem_wait(socksem);
- if (sock->lastdata) {
- netbuf_delete(sock->lastdata);
- }
- sock->lastdata = NULL;
- sock->lastoffset = 0;
- sock->conn = NULL;
- sock_set_errno(sock, 0);
- sys_sem_signal(socksem);
- return 0;
-}
-
-int
-lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
-{
- struct lwip_socket *sock;
- err_t err;
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)name)->sin_family) == AF_INET)),
- sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
- if (((const struct sockaddr_in *)name)->sin_family == AF_UNSPEC) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
- err = netconn_disconnect(sock->conn);
- } else {
- struct ip_addr remote_addr;
- u16_t remote_port;
-
- remote_addr.addr = ((const struct sockaddr_in *)name)->sin_addr.s_addr;
- remote_port = ((const struct sockaddr_in *)name)->sin_port;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
- ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
-
- err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
- }
-
- if (err != ERR_OK) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
- sock_set_errno(sock, err_to_errno(err));
- return -1;
- }
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
- sock_set_errno(sock, 0);
- return 0;
-}
-
-/**
- * Set a socket into listen mode.
- * The socket may not have been used for another connection previously.
- *
- * @param s the socket to set to listening mode
- * @param backlog (ATTENTION: need TCP_LISTEN_BACKLOG=1)
- * @return 0 on success, non-zero on failure
- */
-int
-lwip_listen(int s, int backlog)
-{
- struct lwip_socket *sock;
- err_t err;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- /* limit the "backlog" parameter to fit in an u8_t */
- if (backlog < 0) {
- backlog = 0;
- }
- if (backlog > 0xff) {
- backlog = 0xff;
- }
-
- err = netconn_listen_with_backlog(sock->conn, backlog);
-
- if (err != ERR_OK) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
- sock_set_errno(sock, err_to_errno(err));
- return -1;
- }
-
- sock_set_errno(sock, 0);
- return 0;
-}
-
-int
-lwip_recvfrom(int s, void *mem, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen)
-{
- struct lwip_socket *sock;
- struct netbuf *buf;
- u16_t buflen, copylen, off = 0;
- struct ip_addr *addr;
- u16_t port;
- u8_t done = 0;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- do {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", (void*)sock->lastdata));
- /* Check if there is data left from the last recv operation. */
- if (sock->lastdata) {
- buf = sock->lastdata;
- } else {
- /* If this is non-blocking call, then check first */
- if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
- (sock->rcvevent <= 0)) {
- if (off > 0) {
- /* already received data, return that */
- sock_set_errno(sock, 0);
- return off;
- }
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
- sock_set_errno(sock, EWOULDBLOCK);
- return -1;
- }
-
- /* No data was left from the previous operation, so we try to get
- some from the network. */
- sock->lastdata = buf = netconn_recv(sock->conn);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", (void*)buf));
-
- if (!buf) {
- if (off > 0) {
- /* already received data, return that */
- sock_set_errno(sock, 0);
- return off;
- }
- /* We should really do some error checking here. */
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
- sock_set_errno(sock, (((sock->conn->pcb.ip != NULL) && (sock->conn->err == ERR_OK))
- ? ETIMEDOUT : err_to_errno(sock->conn->err)));
- return 0;
- }
- }
-
- buflen = netbuf_len(buf);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%"U16_F" sock->lastoffset=%"U16_F"\n",
- buflen, len, off, sock->lastoffset));
-
- buflen -= sock->lastoffset;
-
- if (len > buflen) {
- copylen = buflen;
- } else {
- copylen = (u16_t)len;
- }
-
- /* copy the contents of the received buffer into
- the supplied memory pointer mem */
- netbuf_copy_partial(buf, (u8_t*)mem + off, copylen, sock->lastoffset);
-
- off += copylen;
-
- if (netconn_type(sock->conn) == NETCONN_TCP) {
- LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
- len -= copylen;
- if ( (len <= 0) ||
- (buf->p->flags & PBUF_FLAG_PUSH) ||
- (sock->rcvevent <= 0) ||
- ((flags & MSG_PEEK)!=0)) {
- done = 1;
- }
- } else {
- done = 1;
- }
-
- /* Check to see from where the data was.*/
- if (done) {
- if (from && fromlen) {
- struct sockaddr_in sin;
-
- if (netconn_type(sock->conn) == NETCONN_TCP) {
- addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
- netconn_getaddr(sock->conn, addr, &port, 0);
- } else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
- }
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = addr->addr;
-
- if (*fromlen > sizeof(sin)) {
- *fromlen = sizeof(sin);
- }
-
- MEMCPY(from, &sin, *fromlen);
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
- ip_addr_debug_print(SOCKETS_DEBUG, addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
- } else {
- #if SOCKETS_DEBUG
- struct sockaddr_in sin;
-
- if (netconn_type(sock->conn) == NETCONN_TCP) {
- addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
- netconn_getaddr(sock->conn, addr, &port, 0);
- } else {
- addr = netbuf_fromaddr(buf);
- port = netbuf_fromport(buf);
- }
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
- ip_addr_debug_print(SOCKETS_DEBUG, addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%"U16_F"\n", port, off));
- #endif /* SOCKETS_DEBUG */
- }
- }
-
- /* If we don't peek the incoming message... */
- if ((flags & MSG_PEEK)==0) {
- /* If this is a TCP socket, check if there is data left in the
- buffer. If so, it should be saved in the sock structure for next
- time around. */
- if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
- sock->lastdata = buf;
- sock->lastoffset += copylen;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
- } else {
- sock->lastdata = NULL;
- sock->lastoffset = 0;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
- netbuf_delete(buf);
- }
- }
- } while (!done);
-
- sock_set_errno(sock, 0);
- return off;
-}
-
-int
-lwip_read(int s, void *mem, size_t len)
-{
- return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
-}
-
-int
-lwip_recv(int s, void *mem, size_t len, int flags)
-{
- return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
-}
-
-int
-lwip_send(int s, const void *data, size_t size, int flags)
-{
- struct lwip_socket *sock;
- err_t err;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
- s, data, size, flags));
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- if (sock->conn->type != NETCONN_TCP) {
-#if (LWIP_UDP || LWIP_RAW)
- return lwip_sendto(s, data, size, flags, NULL, 0);
-#else
- sock_set_errno(sock, err_to_errno(ERR_ARG));
- return -1;
-#endif /* (LWIP_UDP || LWIP_RAW) */
- }
-
- err = netconn_write(sock->conn, data, size, NETCONN_COPY | ((flags & MSG_MORE)?NETCONN_MORE:0));
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
- sock_set_errno(sock, err_to_errno(err));
- return (err == ERR_OK ? (int)size : -1);
-}
-
-int
-lwip_sendto(int s, const void *data, size_t size, int flags,
- const struct sockaddr *to, socklen_t tolen)
-{
- struct lwip_socket *sock;
- struct ip_addr remote_addr;
- err_t err;
- u16_t short_size;
-#if !LWIP_TCPIP_CORE_LOCKING
- struct netbuf buf;
- u16_t remote_port;
-#endif
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- if (sock->conn->type == NETCONN_TCP) {
-#if LWIP_TCP
- return lwip_send(s, data, size, flags);
-#else
- sock_set_errno(sock, err_to_errno(ERR_ARG));
- return -1;
-#endif /* LWIP_TCP */
- }
-
- LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
- short_size = (u16_t)size;
- LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
- ((tolen == sizeof(struct sockaddr_in)) &&
- ((((const struct sockaddr_in *)to)->sin_family) == AF_INET))),
- sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
-
-#if LWIP_TCPIP_CORE_LOCKING
- /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
- { struct pbuf* p;
-
- p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
- if (p == NULL) {
- err = ERR_MEM;
- } else {
- p->payload = (void*)data;
- p->len = p->tot_len = short_size;
-
- remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
-
- LOCK_TCPIP_CORE();
- if (sock->conn->type==NETCONN_RAW) {
- err = sock->conn->err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
- } else {
- err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, &remote_addr, ntohs(((const struct sockaddr_in *)to)->sin_port));
- }
- UNLOCK_TCPIP_CORE();
-
- pbuf_free(p);
- }
- }
-#else
- /* initialize a buffer */
- buf.p = buf.ptr = NULL;
- if (to) {
- remote_addr.addr = ((const struct sockaddr_in *)to)->sin_addr.s_addr;
- remote_port = ntohs(((const struct sockaddr_in *)to)->sin_port);
- buf.addr = &remote_addr;
- buf.port = remote_port;
- } else {
- remote_addr.addr = 0;
- remote_port = 0;
- buf.addr = NULL;
- buf.port = 0;
- }
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
- s, data, short_size, flags));
- ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
-
- /* make the buffer point to the data that should be sent */
-#if LWIP_NETIF_TX_SINGLE_PBUF
- /* Allocate a new netbuf and copy the data into it. */
- if (netbuf_alloc(&buf, short_size) == NULL) {
- err = ERR_MEM;
- } else {
- err = netbuf_take(&buf, data, short_size);
- }
-#else /* LWIP_NETIF_TX_SINGLE_PBUF */
- err = netbuf_ref(&buf, data, short_size);
-#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
- if (err == ERR_OK) {
- /* send the data */
- err = netconn_send(sock->conn, &buf);
- }
-
- /* deallocated the buffer */
- netbuf_free(&buf);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
- sock_set_errno(sock, err_to_errno(err));
- return (err == ERR_OK ? short_size : -1);
-}
-
-int
-lwip_socket(int domain, int type, int protocol)
-{
- struct netconn *conn;
- int i;
-
- LWIP_UNUSED_ARG(domain);
-
- /* create a netconn */
- switch (type) {
- case SOCK_RAW:
- conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
- domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
- break;
- case SOCK_DGRAM:
- conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
- NETCONN_UDPLITE : NETCONN_UDP, event_callback);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
- domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
- break;
- case SOCK_STREAM:
- conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
- domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
- break;
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
- domain, type, protocol));
- set_errno(EINVAL);
- return -1;
- }
-
- if (!conn) {
- LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
- set_errno(ENOBUFS);
- return -1;
- }
-
- i = alloc_socket(conn);
-
- if (i == -1) {
- netconn_delete(conn);
- set_errno(ENFILE);
- return -1;
- }
- conn->socket = i;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
- set_errno(0);
- return i;
-}
-
-int
-lwip_write(int s, const void *data, size_t size)
-{
- return lwip_send(s, data, size, 0);
-}
-
-/**
- * Go through the readset and writeset lists and see which socket of the sockets
- * set in the sets has events. On return, readset, writeset and exceptset have
- * the sockets enabled that had events.
- *
- * exceptset is not used for now!!!
- *
- * @param maxfdp1 the highest socket index in the sets
- * @param readset in: set of sockets to check for read events;
- * out: set of sockets that had read events
- * @param writeset in: set of sockets to check for write events;
- * out: set of sockets that had write events
- * @param exceptset not yet implemented
- * @return number of sockets that had events (read+write)
- */
-static int
-lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
-{
- int i, nready = 0;
- fd_set lreadset, lwriteset, lexceptset;
- struct lwip_socket *p_sock;
-
- FD_ZERO(&lreadset);
- FD_ZERO(&lwriteset);
- FD_ZERO(&lexceptset);
-
- /* Go through each socket in each list to count number of sockets which
- currently match */
- for(i = 0; i < maxfdp1; i++) {
- if (FD_ISSET(i, readset)) {
- /* See if netconn of this socket is ready for read */
- p_sock = get_socket(i);
- if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
- FD_SET(i, &lreadset);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
- nready++;
- }
- }
- if (FD_ISSET(i, writeset)) {
- /* See if netconn of this socket is ready for write */
- p_sock = get_socket(i);
- if (p_sock && p_sock->sendevent) {
- FD_SET(i, &lwriteset);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
- nready++;
- }
- }
- }
- *readset = lreadset;
- *writeset = lwriteset;
- FD_ZERO(exceptset);
-
- return nready;
-}
-
-
-/**
- * Processing exceptset is not yet implemented.
- */
-int
-lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
- struct timeval *timeout)
-{
- int i;
- int nready;
- fd_set lreadset, lwriteset, lexceptset;
- u32_t msectimeout;
- struct lwip_select_cb select_cb;
- struct lwip_select_cb *p_selcb;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
- maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
- timeout ? (long)timeout->tv_sec : (long)-1,
- timeout ? (long)timeout->tv_usec : (long)-1));
-
- select_cb.next = 0;
- select_cb.readset = readset;
- select_cb.writeset = writeset;
- select_cb.exceptset = exceptset;
- select_cb.sem_signalled = 0;
-
- /* Protect ourselves searching through the list */
- sys_sem_wait(selectsem);
-
- if (readset)
- lreadset = *readset;
- else
- FD_ZERO(&lreadset);
- if (writeset)
- lwriteset = *writeset;
- else
- FD_ZERO(&lwriteset);
- if (exceptset)
- lexceptset = *exceptset;
- else
- FD_ZERO(&lexceptset);
-
- /* Go through each socket in each list to count number of sockets which
- currently match */
- nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
-
- /* If we don't have any current events, then suspend if we are supposed to */
- if (!nready) {
- if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
- sys_sem_signal(selectsem);
- if (readset)
- FD_ZERO(readset);
- if (writeset)
- FD_ZERO(writeset);
- if (exceptset)
- FD_ZERO(exceptset);
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
- set_errno(0);
-
- return 0;
- }
-
- /* add our semaphore to list */
- /* We don't actually need any dynamic memory. Our entry on the
- * list is only valid while we are in this function, so it's ok
- * to use local variables */
-
- select_cb.sem = sys_sem_new(0);
- /* Note that we are still protected */
- /* Put this select_cb on top of list */
- select_cb.next = select_cb_list;
- select_cb_list = &select_cb;
-
- /* Now we can safely unprotect */
- sys_sem_signal(selectsem);
-
- /* Now just wait to be woken */
- if (timeout == 0)
- /* Wait forever */
- msectimeout = 0;
- else {
- msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
- if(msectimeout == 0)
- msectimeout = 1;
- }
-
- i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
-
- /* Take us off the list */
- sys_sem_wait(selectsem);
- if (select_cb_list == &select_cb)
- select_cb_list = select_cb.next;
- else
- for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
- if (p_selcb->next == &select_cb) {
- p_selcb->next = select_cb.next;
- break;
- }
- }
-
- sys_sem_signal(selectsem);
-
- sys_sem_free(select_cb.sem);
- if (i == 0) {
- /* Timeout */
- if (readset)
- FD_ZERO(readset);
- if (writeset)
- FD_ZERO(writeset);
- if (exceptset)
- FD_ZERO(exceptset);
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
- set_errno(0);
-
- return 0;
- }
-
- if (readset)
- lreadset = *readset;
- else
- FD_ZERO(&lreadset);
- if (writeset)
- lwriteset = *writeset;
- else
- FD_ZERO(&lwriteset);
- if (exceptset)
- lexceptset = *exceptset;
- else
- FD_ZERO(&lexceptset);
-
- /* See what's set */
- nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
- } else
- sys_sem_signal(selectsem);
-
- if (readset)
- *readset = lreadset;
- if (writeset)
- *writeset = lwriteset;
- if (exceptset)
- *exceptset = lexceptset;
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
- set_errno(0);
-
- return nready;
-}
-
-/**
- * Callback registered in the netconn layer for each socket-netconn.
- * Processes recvevent (data available) and wakes up tasks waiting for select.
- */
-static void
-event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
-{
- int s;
- struct lwip_socket *sock;
- struct lwip_select_cb *scb;
-
- LWIP_UNUSED_ARG(len);
-
- /* Get socket */
- if (conn) {
- s = conn->socket;
- if (s < 0) {
- /* Data comes in right away after an accept, even though
- * the server task might not have created a new socket yet.
- * Just count down (or up) if that's the case and we
- * will use the data later. Note that only receive events
- * can happen before the new socket is set up. */
- sys_sem_wait(socksem);
- if (conn->socket < 0) {
- if (evt == NETCONN_EVT_RCVPLUS) {
- conn->socket--;
- }
- sys_sem_signal(socksem);
- return;
- }
- sys_sem_signal(socksem);
- }
-
- sock = get_socket(s);
- if (!sock) {
- return;
- }
- } else {
- return;
- }
-
- sys_sem_wait(selectsem);
- /* Set event as required */
- switch (evt) {
- case NETCONN_EVT_RCVPLUS:
- sock->rcvevent++;
- break;
- case NETCONN_EVT_RCVMINUS:
- sock->rcvevent--;
- break;
- case NETCONN_EVT_SENDPLUS:
- sock->sendevent = 1;
- break;
- case NETCONN_EVT_SENDMINUS:
- sock->sendevent = 0;
- break;
- default:
- LWIP_ASSERT("unknown event", 0);
- break;
- }
- sys_sem_signal(selectsem);
-
- /* Now decide if anyone is waiting for this socket */
- /* NOTE: This code is written this way to protect the select link list
- but to avoid a deadlock situation by releasing socksem before
- signalling for the select. This means we need to go through the list
- multiple times ONLY IF a select was actually waiting. We go through
- the list the number of waiting select calls + 1. This list is
- expected to be small. */
- while (1) {
- sys_sem_wait(selectsem);
- for (scb = select_cb_list; scb; scb = scb->next) {
- if (scb->sem_signalled == 0) {
- /* Test this select call for our socket */
- if (scb->readset && FD_ISSET(s, scb->readset))
- if (sock->rcvevent > 0)
- break;
- if (scb->writeset && FD_ISSET(s, scb->writeset))
- if (sock->sendevent)
- break;
- }
- }
- if (scb) {
- scb->sem_signalled = 1;
- sys_sem_signal(scb->sem);
- sys_sem_signal(selectsem);
- } else {
- sys_sem_signal(selectsem);
- break;
- }
- }
-}
-
-/**
- * Unimplemented: Close one end of a full-duplex connection.
- * Currently, the full connection is closed.
- */
-int
-lwip_shutdown(int s, int how)
-{
- LWIP_UNUSED_ARG(how);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
- return lwip_close(s); /* XXX temporary hack until proper implementation */
-}
-
-static int
-lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
-{
- struct lwip_socket *sock;
- struct sockaddr_in sin;
- struct ip_addr naddr;
-
- sock = get_socket(s);
- if (!sock)
- return -1;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
-
- /* get the IP address and port */
- netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
- ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
-
- sin.sin_port = htons(sin.sin_port);
- sin.sin_addr.s_addr = naddr.addr;
-
- if (*namelen > sizeof(sin))
- *namelen = sizeof(sin);
-
- MEMCPY(name, &sin, *namelen);
- sock_set_errno(sock, 0);
- return 0;
-}
-
-int
-lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
-{
- return lwip_getaddrname(s, name, namelen, 0);
-}
-
-int
-lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
-{
- return lwip_getaddrname(s, name, namelen, 1);
-}
-
-int
-lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
-{
- err_t err = ERR_OK;
- struct lwip_socket *sock = get_socket(s);
- struct lwip_setgetsockopt_data data;
-
- if (!sock)
- return -1;
-
- if ((NULL == optval) || (NULL == optlen)) {
- sock_set_errno(sock, EFAULT);
- return -1;
- }
-
- /* Do length and type checks for the various options first, to keep it readable. */
- switch (level) {
-
-/* Level: SOL_SOCKET */
- case SOL_SOCKET:
- switch (optname) {
-
- case SO_ACCEPTCONN:
- case SO_BROADCAST:
- /* UNIMPL case SO_DEBUG: */
- /* UNIMPL case SO_DONTROUTE: */
- case SO_ERROR:
- case SO_KEEPALIVE:
- /* UNIMPL case SO_CONTIMEO: */
- /* UNIMPL case SO_SNDTIMEO: */
-#if LWIP_SO_RCVTIMEO
- case SO_RCVTIMEO:
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
- case SO_RCVBUF:
-#endif /* LWIP_SO_RCVBUF */
- /* UNIMPL case SO_OOBINLINE: */
- /* UNIMPL case SO_SNDBUF: */
- /* UNIMPL case SO_RCVLOWAT: */
- /* UNIMPL case SO_SNDLOWAT: */
-#if SO_REUSE
- case SO_REUSEADDR:
- case SO_REUSEPORT:
-#endif /* SO_REUSE */
- case SO_TYPE:
- /* UNIMPL case SO_USELOOPBACK: */
- if (*optlen < sizeof(int)) {
- err = EINVAL;
- }
- break;
-
- case SO_NO_CHECK:
- if (*optlen < sizeof(int)) {
- err = EINVAL;
- }
-#if LWIP_UDP
- if ((sock->conn->type != NETCONN_UDP) ||
- ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
- /* this flag is only available for UDP, not for UDP lite */
- err = EAFNOSUPPORT;
- }
-#endif /* LWIP_UDP */
- break;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-
-/* Level: IPPROTO_IP */
- case IPPROTO_IP:
- switch (optname) {
- /* UNIMPL case IP_HDRINCL: */
- /* UNIMPL case IP_RCVDSTADDR: */
- /* UNIMPL case IP_RCVIF: */
- case IP_TTL:
- case IP_TOS:
- if (*optlen < sizeof(int)) {
- err = EINVAL;
- }
- break;
-#if LWIP_IGMP
- case IP_MULTICAST_TTL:
- if (*optlen < sizeof(u8_t)) {
- err = EINVAL;
- }
- break;
- case IP_MULTICAST_IF:
- if (*optlen < sizeof(struct in_addr)) {
- err = EINVAL;
- }
- break;
-#endif /* LWIP_IGMP */
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
- case IPPROTO_TCP:
- if (*optlen < sizeof(int)) {
- err = EINVAL;
- break;
- }
-
- /* If this is no TCP socket, ignore any options. */
- if (sock->conn->type != NETCONN_TCP)
- return 0;
-
- switch (optname) {
- case TCP_NODELAY:
- case TCP_KEEPALIVE:
-#if LWIP_TCP_KEEPALIVE
- case TCP_KEEPIDLE:
- case TCP_KEEPINTVL:
- case TCP_KEEPCNT:
-#endif /* LWIP_TCP_KEEPALIVE */
- break;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-#endif /* LWIP_TCP */
-#if LWIP_UDP && LWIP_UDPLITE
-/* Level: IPPROTO_UDPLITE */
- case IPPROTO_UDPLITE:
- if (*optlen < sizeof(int)) {
- err = EINVAL;
- break;
- }
-
- /* If this is no UDP lite socket, ignore any options. */
- if (sock->conn->type != NETCONN_UDPLITE)
- return 0;
-
- switch (optname) {
- case UDPLITE_SEND_CSCOV:
- case UDPLITE_RECV_CSCOV:
- break;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-#endif /* LWIP_UDP && LWIP_UDPLITE*/
-/* UNDEFINED LEVEL */
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
- s, level, optname));
- err = ENOPROTOOPT;
- } /* switch */
-
-
- if (err != ERR_OK) {
- sock_set_errno(sock, err);
- return -1;
- }
-
- /* Now do the actual option processing */
- data.sock = sock;
- data.level = level;
- data.optname = optname;
- data.optval = optval;
- data.optlen = optlen;
- data.err = err;
- tcpip_callback(lwip_getsockopt_internal, &data);
- sys_arch_sem_wait(sock->conn->op_completed, 0);
- /* maybe lwip_getsockopt_internal has changed err */
- err = data.err;
-
- sock_set_errno(sock, err);
- return err ? -1 : 0;
-}
-
-static void
-lwip_getsockopt_internal(void *arg)
-{
- struct lwip_socket *sock;
-#ifdef LWIP_DEBUG
- int s;
-#endif /* LWIP_DEBUG */
- int level, optname;
- void *optval;
- struct lwip_setgetsockopt_data *data;
-
- LWIP_ASSERT("arg != NULL", arg != NULL);
-
- data = (struct lwip_setgetsockopt_data*)arg;
- sock = data->sock;
-#ifdef LWIP_DEBUG
- s = data->s;
-#endif /* LWIP_DEBUG */
- level = data->level;
- optname = data->optname;
- optval = data->optval;
-
- switch (level) {
-
-/* Level: SOL_SOCKET */
- case SOL_SOCKET:
- switch (optname) {
-
- /* The option flags */
- case SO_ACCEPTCONN:
- case SO_BROADCAST:
- /* UNIMPL case SO_DEBUG: */
- /* UNIMPL case SO_DONTROUTE: */
- case SO_KEEPALIVE:
- /* UNIMPL case SO_OOBINCLUDE: */
-#if SO_REUSE
- case SO_REUSEADDR:
- case SO_REUSEPORT:
-#endif /* SO_REUSE */
- /*case SO_USELOOPBACK: UNIMPL */
- *(int*)optval = sock->conn->pcb.ip->so_options & optname;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
- s, optname, (*(int*)optval?"on":"off")));
- break;
-
- case SO_TYPE:
- switch (NETCONNTYPE_GROUP(sock->conn->type)) {
- case NETCONN_RAW:
- *(int*)optval = SOCK_RAW;
- break;
- case NETCONN_TCP:
- *(int*)optval = SOCK_STREAM;
- break;
- case NETCONN_UDP:
- *(int*)optval = SOCK_DGRAM;
- break;
- default: /* unrecognized socket type */
- *(int*)optval = sock->conn->type;
- LWIP_DEBUGF(SOCKETS_DEBUG,
- ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
- s, *(int *)optval));
- } /* switch (sock->conn->type) */
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
- s, *(int *)optval));
- break;
-
- case SO_ERROR:
- if (sock->err == 0) {
- sock_set_errno(sock, err_to_errno(sock->conn->err));
- }
- *(int *)optval = sock->err;
- sock->err = 0;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
- s, *(int *)optval));
- break;
-
-#if LWIP_SO_RCVTIMEO
- case SO_RCVTIMEO:
- *(int *)optval = sock->conn->recv_timeout;
- break;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
- case SO_RCVBUF:
- *(int *)optval = sock->conn->recv_bufsize;
- break;
-#endif /* LWIP_SO_RCVBUF */
-#if LWIP_UDP
- case SO_NO_CHECK:
- *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
- break;
-#endif /* LWIP_UDP*/
- } /* switch (optname) */
- break;
-
-/* Level: IPPROTO_IP */
- case IPPROTO_IP:
- switch (optname) {
- case IP_TTL:
- *(int*)optval = sock->conn->pcb.ip->ttl;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
- s, *(int *)optval));
- break;
- case IP_TOS:
- *(int*)optval = sock->conn->pcb.ip->tos;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
- s, *(int *)optval));
- break;
-#if LWIP_IGMP
- case IP_MULTICAST_TTL:
- *(u8_t*)optval = sock->conn->pcb.ip->ttl;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
- s, *(int *)optval));
- break;
- case IP_MULTICAST_IF:
- ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
- s, *(u32_t *)optval));
- break;
-#endif /* LWIP_IGMP */
- } /* switch (optname) */
- break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
- case IPPROTO_TCP:
- switch (optname) {
- case TCP_NODELAY:
- *(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
- s, (*(int*)optval)?"on":"off") );
- break;
- case TCP_KEEPALIVE:
- *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
- s, *(int *)optval));
- break;
-
-#if LWIP_TCP_KEEPALIVE
- case TCP_KEEPIDLE:
- *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
- s, *(int *)optval));
- break;
- case TCP_KEEPINTVL:
- *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
- s, *(int *)optval));
- break;
- case TCP_KEEPCNT:
- *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
- s, *(int *)optval));
- break;
-#endif /* LWIP_TCP_KEEPALIVE */
-
- } /* switch (optname) */
- break;
-#endif /* LWIP_TCP */
-#if LWIP_UDP && LWIP_UDPLITE
- /* Level: IPPROTO_UDPLITE */
- case IPPROTO_UDPLITE:
- switch (optname) {
- case UDPLITE_SEND_CSCOV:
- *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
- s, (*(int*)optval)) );
- break;
- case UDPLITE_RECV_CSCOV:
- *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
- s, (*(int*)optval)) );
- break;
- } /* switch (optname) */
- break;
-#endif /* LWIP_UDP */
- } /* switch (level) */
- sys_sem_signal(sock->conn->op_completed);
-}
-
-int
-lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
-{
- struct lwip_socket *sock = get_socket(s);
- int err = ERR_OK;
- struct lwip_setgetsockopt_data data;
-
- if (!sock)
- return -1;
-
- if (NULL == optval) {
- sock_set_errno(sock, EFAULT);
- return -1;
- }
-
- /* Do length and type checks for the various options first, to keep it readable. */
- switch (level) {
-
-/* Level: SOL_SOCKET */
- case SOL_SOCKET:
- switch (optname) {
-
- case SO_BROADCAST:
- /* UNIMPL case SO_DEBUG: */
- /* UNIMPL case SO_DONTROUTE: */
- case SO_KEEPALIVE:
- /* UNIMPL case case SO_CONTIMEO: */
- /* UNIMPL case case SO_SNDTIMEO: */
-#if LWIP_SO_RCVTIMEO
- case SO_RCVTIMEO:
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
- case SO_RCVBUF:
-#endif /* LWIP_SO_RCVBUF */
- /* UNIMPL case SO_OOBINLINE: */
- /* UNIMPL case SO_SNDBUF: */
- /* UNIMPL case SO_RCVLOWAT: */
- /* UNIMPL case SO_SNDLOWAT: */
-#if SO_REUSE
- case SO_REUSEADDR:
- case SO_REUSEPORT:
-#endif /* SO_REUSE */
- /* UNIMPL case SO_USELOOPBACK: */
- if (optlen < sizeof(int)) {
- err = EINVAL;
- }
- break;
- case SO_NO_CHECK:
- if (optlen < sizeof(int)) {
- err = EINVAL;
- }
-#if LWIP_UDP
- if ((sock->conn->type != NETCONN_UDP) ||
- ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
- /* this flag is only available for UDP, not for UDP lite */
- err = EAFNOSUPPORT;
- }
-#endif /* LWIP_UDP */
- break;
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-
-/* Level: IPPROTO_IP */
- case IPPROTO_IP:
- switch (optname) {
- /* UNIMPL case IP_HDRINCL: */
- /* UNIMPL case IP_RCVDSTADDR: */
- /* UNIMPL case IP_RCVIF: */
- case IP_TTL:
- case IP_TOS:
- if (optlen < sizeof(int)) {
- err = EINVAL;
- }
- break;
-#if LWIP_IGMP
- case IP_MULTICAST_TTL:
- if (optlen < sizeof(u8_t)) {
- err = EINVAL;
- }
- if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
- err = EAFNOSUPPORT;
- }
- break;
- case IP_MULTICAST_IF:
- if (optlen < sizeof(struct in_addr)) {
- err = EINVAL;
- }
- if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
- err = EAFNOSUPPORT;
- }
- break;
- case IP_ADD_MEMBERSHIP:
- case IP_DROP_MEMBERSHIP:
- if (optlen < sizeof(struct ip_mreq)) {
- err = EINVAL;
- }
- if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
- err = EAFNOSUPPORT;
- }
- break;
-#endif /* LWIP_IGMP */
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
- case IPPROTO_TCP:
- if (optlen < sizeof(int)) {
- err = EINVAL;
- break;
- }
-
- /* If this is no TCP socket, ignore any options. */
- if (sock->conn->type != NETCONN_TCP)
- return 0;
-
- switch (optname) {
- case TCP_NODELAY:
- case TCP_KEEPALIVE:
-#if LWIP_TCP_KEEPALIVE
- case TCP_KEEPIDLE:
- case TCP_KEEPINTVL:
- case TCP_KEEPCNT:
-#endif /* LWIP_TCP_KEEPALIVE */
- break;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-#endif /* LWIP_TCP */
-#if LWIP_UDP && LWIP_UDPLITE
-/* Level: IPPROTO_UDPLITE */
- case IPPROTO_UDPLITE:
- if (optlen < sizeof(int)) {
- err = EINVAL;
- break;
- }
-
- /* If this is no UDP lite socket, ignore any options. */
- if (sock->conn->type != NETCONN_UDPLITE)
- return 0;
-
- switch (optname) {
- case UDPLITE_SEND_CSCOV:
- case UDPLITE_RECV_CSCOV:
- break;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
- s, optname));
- err = ENOPROTOOPT;
- } /* switch (optname) */
- break;
-#endif /* LWIP_UDP && LWIP_UDPLITE */
-/* UNDEFINED LEVEL */
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
- s, level, optname));
- err = ENOPROTOOPT;
- } /* switch (level) */
-
-
- if (err != ERR_OK) {
- sock_set_errno(sock, err);
- return -1;
- }
-
-
- /* Now do the actual option processing */
- data.sock = sock;
- data.level = level;
- data.optname = optname;
- data.optval = (void*)optval;
- data.optlen = &optlen;
- data.err = err;
- tcpip_callback(lwip_setsockopt_internal, &data);
- sys_arch_sem_wait(sock->conn->op_completed, 0);
- /* maybe lwip_setsockopt_internal has changed err */
- err = data.err;
-
- sock_set_errno(sock, err);
- return err ? -1 : 0;
-}
-
-static void
-lwip_setsockopt_internal(void *arg)
-{
- struct lwip_socket *sock;
-#ifdef LWIP_DEBUG
- int s;
-#endif /* LWIP_DEBUG */
- int level, optname;
- const void *optval;
- struct lwip_setgetsockopt_data *data;
-
- LWIP_ASSERT("arg != NULL", arg != NULL);
-
- data = (struct lwip_setgetsockopt_data*)arg;
- sock = data->sock;
-#ifdef LWIP_DEBUG
- s = data->s;
-#endif /* LWIP_DEBUG */
- level = data->level;
- optname = data->optname;
- optval = data->optval;
-
- switch (level) {
-
-/* Level: SOL_SOCKET */
- case SOL_SOCKET:
- switch (optname) {
-
- /* The option flags */
- case SO_BROADCAST:
- /* UNIMPL case SO_DEBUG: */
- /* UNIMPL case SO_DONTROUTE: */
- case SO_KEEPALIVE:
- /* UNIMPL case SO_OOBINCLUDE: */
-#if SO_REUSE
- case SO_REUSEADDR:
- case SO_REUSEPORT:
-#endif /* SO_REUSE */
- /* UNIMPL case SO_USELOOPBACK: */
- if (*(int*)optval) {
- sock->conn->pcb.ip->so_options |= optname;
- } else {
- sock->conn->pcb.ip->so_options &= ~optname;
- }
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
- s, optname, (*(int*)optval?"on":"off")));
- break;
-#if LWIP_SO_RCVTIMEO
- case SO_RCVTIMEO:
- sock->conn->recv_timeout = ( *(int*)optval );
- break;
-#endif /* LWIP_SO_RCVTIMEO */
-#if LWIP_SO_RCVBUF
- case SO_RCVBUF:
- sock->conn->recv_bufsize = ( *(int*)optval );
- break;
-#endif /* LWIP_SO_RCVBUF */
-#if LWIP_UDP
- case SO_NO_CHECK:
- if (*(int*)optval) {
- udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
- } else {
- udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
- }
- break;
-#endif /* LWIP_UDP */
- } /* switch (optname) */
- break;
-
-/* Level: IPPROTO_IP */
- case IPPROTO_IP:
- switch (optname) {
- case IP_TTL:
- sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
- s, sock->conn->pcb.ip->ttl));
- break;
- case IP_TOS:
- sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
- s, sock->conn->pcb.ip->tos));
- break;
-#if LWIP_IGMP
- case IP_MULTICAST_TTL:
- sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
- break;
- case IP_MULTICAST_IF:
- sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr;
- break;
- case IP_ADD_MEMBERSHIP:
- case IP_DROP_MEMBERSHIP:
- {
- /* If this is a TCP or a RAW socket, ignore these options. */
- struct ip_mreq *imr = (struct ip_mreq *)optval;
- if(optname == IP_ADD_MEMBERSHIP){
- data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
- } else {
- data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
- }
- if(data->err != ERR_OK) {
- data->err = EADDRNOTAVAIL;
- }
- }
- break;
-#endif /* LWIP_IGMP */
- } /* switch (optname) */
- break;
-
-#if LWIP_TCP
-/* Level: IPPROTO_TCP */
- case IPPROTO_TCP:
- switch (optname) {
- case TCP_NODELAY:
- if (*(int*)optval) {
- sock->conn->pcb.tcp->flags |= TF_NODELAY;
- } else {
- sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
- }
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
- s, (*(int *)optval)?"on":"off") );
- break;
- case TCP_KEEPALIVE:
- sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
- s, sock->conn->pcb.tcp->keep_idle));
- break;
-
-#if LWIP_TCP_KEEPALIVE
- case TCP_KEEPIDLE:
- sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
- s, sock->conn->pcb.tcp->keep_idle));
- break;
- case TCP_KEEPINTVL:
- sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
- s, sock->conn->pcb.tcp->keep_intvl));
- break;
- case TCP_KEEPCNT:
- sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
- s, sock->conn->pcb.tcp->keep_cnt));
- break;
-#endif /* LWIP_TCP_KEEPALIVE */
-
- } /* switch (optname) */
- break;
-#endif /* LWIP_TCP*/
-#if LWIP_UDP && LWIP_UDPLITE
- /* Level: IPPROTO_UDPLITE */
- case IPPROTO_UDPLITE:
- switch (optname) {
- case UDPLITE_SEND_CSCOV:
- if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
- /* don't allow illegal values! */
- sock->conn->pcb.udp->chksum_len_tx = 8;
- } else {
- sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
- }
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
- s, (*(int*)optval)) );
- break;
- case UDPLITE_RECV_CSCOV:
- if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
- /* don't allow illegal values! */
- sock->conn->pcb.udp->chksum_len_rx = 8;
- } else {
- sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
- }
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
- s, (*(int*)optval)) );
- break;
- } /* switch (optname) */
- break;
-#endif /* LWIP_UDP */
- } /* switch (level) */
- sys_sem_signal(sock->conn->op_completed);
-}
-
-int
-lwip_ioctl(int s, long cmd, void *argp)
-{
- struct lwip_socket *sock = get_socket(s);
- u16_t buflen = 0;
- s16_t recv_avail;
-
- if (!sock)
- return -1;
-
- switch (cmd) {
- case FIONREAD:
- if (!argp) {
- sock_set_errno(sock, EINVAL);
- return -1;
- }
-
- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
- if (recv_avail < 0)
- recv_avail = 0;
- *((u16_t*)argp) = (u16_t)recv_avail;
-
- /* Check if there is data left from the last recv operation. /maq 041215 */
- if (sock->lastdata) {
- buflen = netbuf_len(sock->lastdata);
- buflen -= sock->lastoffset;
-
- *((u16_t*)argp) += buflen;
- }
-
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
- sock_set_errno(sock, 0);
- return 0;
-
- case FIONBIO:
- if (argp && *(u32_t*)argp)
- sock->flags |= O_NONBLOCK;
- else
- sock->flags &= ~O_NONBLOCK;
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
- sock_set_errno(sock, 0);
- return 0;
-
- default:
- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
- sock_set_errno(sock, ENOSYS); /* not yet implemented */
- return -1;
- } /* switch (cmd) */
-}
-
-#endif /* LWIP_SOCKET */
diff --git a/firmware/x300/lwip/lwip-1.3.1/src/api/tcpip.c b/firmware/x300/lwip/lwip-1.3.1/src/api/tcpip.c
deleted file mode 100644
index 002df90b2..000000000
--- a/firmware/x300/lwip/lwip-1.3.1/src/api/tcpip.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/**
- * @file
- * Sequential API Main thread module
- *
- */
-
-/*
- * Copyright (c) 2001-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. 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.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
-
-#include "lwip/opt.h"
-
-#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/sys.h"
-#include "lwip/memp.h"
-#include "lwip/pbuf.h"
-#include "lwip/ip_frag.h"
-#include "lwip/tcp.h"
-#include "lwip/autoip.h"
-#include "lwip/dhcp.h"
-#include "lwip/igmp.h"
-#include "lwip/dns.h"
-#include "lwip/tcpip.h"
-#include "lwip/init.h"
-#include "netif/etharp.h"
-#include "netif/ppp_oe.h"
-
-/* global variables */
-static void (* tcpip_init_done)(void *arg);
-static void *tcpip_init_done_arg;
-static sys_mbox_t mbox = SYS_MBOX_NULL;
-
-#if LWIP_TCPIP_CORE_LOCKING
-/** The global semaphore to lock the stack. */
-sys_sem_t lock_tcpip_core;
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
-#if LWIP_TCP
-/* global variable that shows if the tcp timer is currently scheduled or not */
-static int tcpip_tcp_timer_active;
-
-/**
- * Timer callback function that calls tcp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-tcpip_tcp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
-
- /* call TCP timer handler */
- tcp_tmr();
- /* timer still needed? */
- if (tcp_active_pcbs || tcp_tw_pcbs) {
- /* restart timer */
- sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
- } else {
- /* disable timer */
- tcpip_tcp_timer_active = 0;
- }
-}
-
-#if !NO_SYS
-/**
- * Called from TCP_REG when registering a new PCB:
- * the reason is to have the TCP timer only running when
- * there are active (or time-wait) PCBs.
- */
-void
-tcp_timer_needed(void)
-{
- /* timer is off but needed again? */
- if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
- /* enable and start timer */
- tcpip_tcp_timer_active = 1;
- sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
- }
-}
-#endif /* !NO_SYS */
-#endif /* LWIP_TCP */
-
-#if IP_REASSEMBLY
-/**
- * Timer callback function that calls ip_reass_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-ip_reass_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
- ip_reass_tmr();
- sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
-}
-#endif /* IP_REASSEMBLY */
-
-#if LWIP_ARP
-/**
- * Timer callback function that calls etharp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-arp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
- etharp_tmr();
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-}
-#endif /* LWIP_ARP */
-
-#if LWIP_DHCP
-/**
- * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dhcp_timer_coarse(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
- dhcp_coarse_tmr();
- sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
-}
-
-/**
- * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dhcp_timer_fine(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
- dhcp_fine_tmr();
- sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
-}
-#endif /* LWIP_DHCP */
-
-#if LWIP_AUTOIP
-/**
- * Timer callback function that calls autoip_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-autoip_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n"));
- autoip_tmr();
- sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
-}
-#endif /* LWIP_AUTOIP */
-
-#if LWIP_IGMP
-/**
- * Timer callback function that calls igmp_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-igmp_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
- igmp_tmr();
- sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
-}
-#endif /* LWIP_IGMP */
-
-#if LWIP_DNS
-/**
- * Timer callback function that calls dns_tmr() and reschedules itself.
- *
- * @param arg unused argument
- */
-static void
-dns_timer(void *arg)
-{
- LWIP_UNUSED_ARG(arg);
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n"));
- dns_tmr();
- sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
-}
-#endif /* LWIP_DNS */
-
-/**
- * The main lwIP thread. This thread has exclusive access to lwIP core functions
- * (unless access to them is not locked). Other threads communicate with this
- * thread using message boxes.
- *
- * It also starts all the timers to make sure they are running in the right
- * thread context.
- *
- * @param arg unused argument
- */
-static void
-tcpip_thread(void *arg)
-{
- struct tcpip_msg *msg;
- LWIP_UNUSED_ARG(arg);
-
-#if IP_REASSEMBLY
- sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
-#endif /* IP_REASSEMBLY */
-#if LWIP_ARP
- sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
-#endif /* LWIP_ARP */
-#if LWIP_DHCP
- sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
- sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
-#endif /* LWIP_DHCP */
-#if LWIP_AUTOIP
- sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
-#endif /* LWIP_AUTOIP */
-#if LWIP_IGMP
- sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
-#endif /* LWIP_IGMP */
-#if LWIP_DNS
- sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
-#endif /* LWIP_DNS */
-
- if (tcpip_init_done != NULL) {
- tcpip_init_done(tcpip_init_done_arg);
- }
-
- LOCK_TCPIP_CORE();
- while (1) { /* MAIN Loop */
- sys_mbox_fetch(mbox, (void *)&msg);
- switch (msg->type) {
-#if LWIP_NETCONN
- case TCPIP_MSG_API:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
- msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
- break;
-#endif /* LWIP_NETCONN */
-
- case TCPIP_MSG_INPKT:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
-#if LWIP_ARP
- if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
- ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
- } else
-#endif /* LWIP_ARP */
- { ip_input(msg->msg.inp.p, msg->msg.inp.netif);
- }
- memp_free(MEMP_TCPIP_MSG_INPKT, msg);
- break;
-
-#if LWIP_NETIF_API
- case TCPIP_MSG_NETIFAPI:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
- msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
- break;
-#endif /* LWIP_NETIF_API */
-
- case TCPIP_MSG_CALLBACK:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
- msg->msg.cb.f(msg->msg.cb.ctx);
- memp_free(MEMP_TCPIP_MSG_API, msg);
- break;
-
- case TCPIP_MSG_TIMEOUT:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
- sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
- memp_free(MEMP_TCPIP_MSG_API, msg);
- break;
- case TCPIP_MSG_UNTIMEOUT:
- LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
- sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
- memp_free(MEMP_TCPIP_MSG_API, msg);
- break;
-
- default:
- break;
- }
- }
-}
-
-/**
- * Pass a received packet to tcpip_thread for input processing
- *
- * @param p the received packet, p->payload pointing to the Ethernet header or
- * to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
- * @param inp the network interface on which the packet was received
- */
-err_t
-tcpip_input(struct pbuf *p, struct netif *inp)
-{
- struct tcpip_msg *msg;
-
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
- if (msg == NULL) {
- return ERR_MEM;
- }
-
- msg->type = TCPIP_MSG_INPKT;
- msg->msg.inp.p = p;
- msg->msg.inp.netif = inp;
- if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
- memp_free(MEMP_TCPIP_MSG_INPKT, msg);
- return ERR_MEM;
- }
- return ERR_OK;
- }
- return ERR_VAL;
-}
-
-/**
- * Call a specific function in the thread context of
- * tcpip_thread for easy access synchronization.
- * A function called in that way may access lwIP core code
- * without fearing concurrent access.
- *
- * @param f the function to call
- * @param ctx parameter passed to f
- * @param block 1 to block until the request is posted, 0 to non-blocking mode
- * @return ERR_OK if the function was called, another err_t if not
- */
-err_t
-tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
-{
- struct tcpip_msg *msg;
-
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_API);
- if (msg == NULL) {
- return ERR_MEM;
- }
-
- msg->type = TCPIP_MSG_CALLBACK;
- msg->msg.cb.f = f;
- msg->msg.cb.ctx = ctx;
- if (block) {
- sys_mbox_post(mbox, msg);
- } else {
- if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
- memp_free(MEMP_TCPIP_MSG_API, msg);
- return ERR_MEM;
- }
- }
- return ERR_OK;
- }
- return ERR_VAL;
-}
-
-/**
- * call sys_timeout in tcpip_thread
- *
- * @param msec time in miliseconds for timeout
- * @param h function to be called on timeout
- * @param arg argument to pass to timeout function h
- * @return ERR_MEM on memory error, ERR_OK otherwise
- */
-err_t
-tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
-{
- struct tcpip_msg *msg;
-
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_API);
- if (msg == NULL) {
- return ERR_MEM;
- }
-
- msg->type = TCPIP_MSG_TIMEOUT;
- msg->msg.tmo.msecs = msecs;
- msg->msg.tmo.h = h;
- msg->msg.tmo.arg = arg;
- sys_mbox_post(mbox, msg);
- return ERR_OK;
- }
- return ERR_VAL;
-}
-
-/**
- * call sys_untimeout in tcpip_thread
- *
- * @param msec time in miliseconds for timeout
- * @param h function to be called on timeout
- * @param arg argument to pass to timeout function h
- * @return ERR_MEM on memory error, ERR_OK otherwise
- */
-err_t
-tcpip_untimeout(sys_timeout_handler h, void *arg)
-{
- struct tcpip_msg *msg;
-
- if (mbox != SYS_MBOX_NULL) {
- msg = memp_malloc(MEMP_TCPIP_MSG_API);
- if (msg == NULL) {
- return ERR_MEM;
- }
-
- msg->type = TCPIP_MSG_UNTIMEOUT;
- msg->msg.tmo.h = h;
- msg->msg.tmo.arg = arg;
- sys_mbox_post(mbox, msg);
- return ERR_OK;
- }
- return ERR_VAL;
-}
-
-#if LWIP_NETCONN
-/**
- * Call the lower part of a netconn_* function
- * This function is then running in the thread context
- * of tcpip_thread and has exclusive access to lwIP core code.
- *
- * @param apimsg a struct containing the function to call and its parameters
- * @return ERR_OK if the function was called, another err_t if not
- */
-err_t
-tcpip_apimsg(struct api_msg *apimsg)
-{
- struct tcpip_msg msg;
-
- if (mbox != SYS_MBOX_NULL) {
- msg.type = TCPIP_MSG_API;
- msg.msg.apimsg = apimsg;
- sys_mbox_post(mbox, &msg);
- sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
- return ERR_OK;
- }
- return ERR_VAL;
-}
-
-#if LWIP_TCPIP_CORE_LOCKING
-/**
- * Call the lower part of a netconn_* function
- * This function has exclusive access to lwIP core code by locking it
- * before the function is called.
- *
- * @param apimsg a struct containing the function to call and its parameters
- * @return ERR_OK (only for compatibility fo tcpip_apimsg())
- */
-err_t
-tcpip_apimsg_lock(struct api_msg *apimsg)
-{
- LOCK_TCPIP_CORE();
- apimsg->function(&(apimsg->msg));
- UNLOCK_TCPIP_CORE();
- return ERR_OK;
-
-}
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-#endif /* LWIP_NETCONN */
-
-#if LWIP_NETIF_API
-#if !LWIP_TCPIP_CORE_LOCKING
-/**
- * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
- * function.
- *
- * @param netifapimsg a struct containing the function to call and its parameters
- * @return error code given back by the function that was called
- */
-err_t
-tcpip_netifapi(struct netifapi_msg* netifapimsg)
-{
- struct tcpip_msg msg;
-
- if (mbox != SYS_MBOX_NULL) {
- netifapimsg->msg.sem = sys_sem_new(0);
- if (netifapimsg->msg.sem == SYS_SEM_NULL) {
- netifapimsg->msg.err = ERR_MEM;
- return netifapimsg->msg.err;
- }
-
- msg.type = TCPIP_MSG_NETIFAPI;
- msg.msg.netifapimsg = netifapimsg;
- sys_mbox_post(mbox, &msg);
- sys_sem_wait(netifapimsg->msg.sem);
- sys_sem_free(netifapimsg->msg.sem);
- return netifapimsg->msg.err;
- }
- return ERR_VAL;
-}
-#else /* !LWIP_TCPIP_CORE_LOCKING */
-/**
- * Call the lower part of a netifapi_* function
- * This function has exclusive access to lwIP core code by locking it
- * before the function is called.
- *
- * @param netifapimsg a struct containing the function to call and its parameters
- * @return ERR_OK (only for compatibility fo tcpip_netifapi())
- */
-err_t
-tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
-{
- LOCK_TCPIP_CORE();
- netifapimsg->function(&(netifapimsg->msg));
- UNLOCK_TCPIP_CORE();
- return netifapimsg->msg.err;
-}
-#endif /* !LWIP_TCPIP_CORE_LOCKING */
-#endif /* LWIP_NETIF_API */
-
-/**
- * Initialize this module:
- * - initialize all sub modules
- * - start the tcpip_thread
- *
- * @param initfunc a function to call when tcpip_thread is running and finished initializing
- * @param arg argument to pass to initfunc
- */
-void
-tcpip_init(void (* initfunc)(void *), void *arg)
-{
- lwip_init();
-
- tcpip_init_done = initfunc;
- tcpip_init_done_arg = arg;
- mbox = sys_mbox_new(TCPIP_MBOX_SIZE);
-#if LWIP_TCPIP_CORE_LOCKING
- lock_tcpip_core = sys_sem_new(1);
-#endif /* LWIP_TCPIP_CORE_LOCKING */
-
- sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
-}
-
-/**
- * Simple callback function used with tcpip_callback to free a pbuf
- * (pbuf_free has a wrong signature for tcpip_callback)
- *
- * @param p The pbuf (chain) to be dereferenced.
- */
-static void
-pbuf_free_int(void *p)
-{
- struct pbuf *q = p;
- pbuf_free(q);
-}
-
-/**
- * A simple wrapper function that allows you to free a pbuf from interrupt context.
- *
- * @param p The pbuf (chain) to be dereferenced.
- * @return ERR_OK if callback could be enqueued, an err_t if not
- */
-err_t
-pbuf_free_callback(struct pbuf *p)
-{
- return tcpip_callback_with_block(pbuf_free_int, p, 0);
-}
-
-/**
- * A simple wrapper function that allows you to free heap memory from
- * interrupt context.
- *
- * @param m the heap memory to free
- * @return ERR_OK if callback could be enqueued, an err_t if not
- */
-err_t
-mem_free_callback(void *m)
-{
- return tcpip_callback_with_block(mem_free, m, 0);
-}
-
-#endif /* !NO_SYS */