Initial revision

This commit is contained in:
likewise
2002-10-19 12:59:30 +00:00
commit f06e955072
145 changed files with 27001 additions and 0 deletions

639
src/api/api_lib.c Normal file
View File

@@ -0,0 +1,639 @@
/*
* Copyright (c) 2001, 2002 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/debug.h"
#include "lwip/api.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"
#include "lwip/debug.h"
/*-----------------------------------------------------------------------------------*/
struct
netbuf *netbuf_new(void)
{
struct netbuf *buf;
buf = memp_mallocp(MEMP_NETBUF);
if(buf != NULL) {
buf->p = NULL;
buf->ptr = NULL;
return buf;
} else {
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_delete(struct netbuf *buf)
{
if(buf != NULL) {
if(buf->p != NULL) {
pbuf_free(buf->p);
buf->p = buf->ptr = NULL;
}
memp_freep(MEMP_NETBUF, buf);
}
}
/*-----------------------------------------------------------------------------------*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
/* 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;
}
buf->ptr = buf->p;
return buf->p->payload;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_free(struct netbuf *buf)
{
if(buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = buf->ptr = NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
{
if(buf->p != NULL) {
pbuf_free(buf->p);
}
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_ROM);
buf->p->payload = dataptr;
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
pbuf_chain(head->p, tail->p);
head->ptr = head->p;
memp_freep(MEMP_NETBUF, tail);
}
/*-----------------------------------------------------------------------------------*/
u16_t
netbuf_len(struct netbuf *buf)
{
return buf->p->tot_len;
}
/*-----------------------------------------------------------------------------------*/
err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{
if(buf->ptr == NULL) {
return ERR_BUF;
}
*dataptr = buf->ptr->payload;
*len = buf->ptr->len;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
s8_t
netbuf_next(struct netbuf *buf)
{
if(buf->ptr->next == NULL) {
return -1;
}
buf->ptr = buf->ptr->next;
if(buf->ptr->next == NULL) {
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_first(struct netbuf *buf)
{
buf->ptr = buf->p;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
{
struct pbuf *p;
u16_t i, left;
left = 0;
if(buf == NULL) {
return;
}
/* This implementation is bad. It should use bcopy
instead. */
for(p = buf->p; left < len && p != NULL; p = p->next) {
if(offset != 0 && offset >= p->len) {
offset -= p->len;
} else {
for(i = offset; i < p->len; ++i) {
((char *)dataptr)[left] = ((char *)p->payload)[i];
if(++left >= len) {
return;
}
}
offset = 0;
}
}
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
{
netbuf_copy_partial(buf, dataptr, len, 0);
}
/*-----------------------------------------------------------------------------------*/
struct ip_addr *
netbuf_fromaddr(struct netbuf *buf)
{
return buf->fromaddr;
}
/*-----------------------------------------------------------------------------------*/
u16_t
netbuf_fromport(struct netbuf *buf)
{
return buf->fromport;
}
/*-----------------------------------------------------------------------------------*/
struct
netconn *netconn_new(enum netconn_type t)
{
struct netconn *conn;
conn = memp_mallocp(MEMP_NETCONN);
if(conn == NULL) {
return NULL;
}
conn->type = t;
conn->pcb.tcp = NULL;
if((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
memp_freep(MEMP_NETCONN, conn);
return NULL;
}
conn->recvmbox = SYS_MBOX_NULL;
conn->acceptmbox = SYS_MBOX_NULL;
conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE;
return conn;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_delete(struct netconn *conn)
{
struct api_msg *msg;
void *mem;
if(conn == NULL) {
return ERR_OK;
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_DELCONN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
/* Drain the recvmbox. */
if(conn->recvmbox != SYS_MBOX_NULL) {
while(sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != 0) {
if(conn->type == NETCONN_TCP) {
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_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != 0) {
netconn_delete((struct netconn *)mem);
}
sys_mbox_free(conn->acceptmbox);
conn->acceptmbox = SYS_MBOX_NULL;
}
sys_mbox_free(conn->mbox);
conn->mbox = SYS_MBOX_NULL;
if(conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem);
}
/* conn->sem = SYS_SEM_NULL;*/
memp_free(MEMP_NETCONN, conn);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
enum netconn_type
netconn_type(struct netconn *conn)
{
return conn->type;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_peer(struct netconn *conn, struct ip_addr **addr,
u16_t *port)
{
switch(conn->type) {
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
*addr = &(conn->pcb.udp->remote_ip);
*port = conn->pcb.udp->remote_port;
break;
case NETCONN_TCP:
*addr = &(conn->pcb.tcp->remote_ip);
*port = conn->pcb.tcp->remote_port;
break;
}
return (conn->err = ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_addr(struct netconn *conn, struct ip_addr **addr,
u16_t *port)
{
switch(conn->type) {
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
*addr = &(conn->pcb.udp->local_ip);
*port = conn->pcb.udp->local_port;
break;
case NETCONN_TCP:
*addr = &(conn->pcb.tcp->local_ip);
*port = conn->pcb.tcp->local_port;
break;
}
return (conn->err = ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr,
u16_t port)
{
struct api_msg *msg;
if(conn == NULL) {
return ERR_VAL;
}
if(conn->type != NETCONN_TCP &&
conn->recvmbox == SYS_MBOX_NULL) {
if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_BIND;
msg->msg.conn = conn;
msg->msg.msg.bc.ipaddr = addr;
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr,
u16_t port)
{
struct api_msg *msg;
if(conn == NULL) {
return ERR_VAL;
}
if(conn->recvmbox == SYS_MBOX_NULL) {
if((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return ERR_MEM;
}
msg->type = API_MSG_CONNECT;
msg->msg.conn = conn;
msg->msg.msg.bc.ipaddr = addr;
msg->msg.msg.bc.port = port;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_listen(struct netconn *conn)
{
struct api_msg *msg;
if(conn == NULL) {
return ERR_VAL;
}
if(conn->acceptmbox == SYS_MBOX_NULL) {
conn->acceptmbox = sys_mbox_new();
if(conn->acceptmbox == SYS_MBOX_NULL) {
return ERR_MEM;
}
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_LISTEN;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
struct netconn *
netconn_accept(struct netconn *conn)
{
struct netconn *newconn;
if(conn == NULL) {
return NULL;
}
sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
return newconn;
}
/*-----------------------------------------------------------------------------------*/
struct netbuf *
netconn_recv(struct netconn *conn)
{
struct api_msg *msg;
struct netbuf *buf;
struct pbuf *p;
if(conn == NULL) {
return NULL;
}
if(conn->recvmbox == SYS_MBOX_NULL) {
conn->err = ERR_CONN;
return NULL;
}
if(conn->err != ERR_OK) {
return NULL;
}
if(conn->type == NETCONN_TCP) {
if(conn->pcb.tcp->state == LISTEN) {
conn->err = ERR_CONN;
return NULL;
}
buf = memp_mallocp(MEMP_NETBUF);
if(buf == NULL) {
conn->err = ERR_MEM;
return NULL;
}
sys_mbox_fetch(conn->recvmbox, (void **)&p);
/* If we are closed, we indicate that we no longer wish to recieve
data by setting conn->recvmbox to SYS_MBOX_NULL. */
if(p == NULL) {
memp_freep(MEMP_NETBUF, buf);
sys_mbox_free(conn->recvmbox);
conn->recvmbox = SYS_MBOX_NULL;
return NULL;
}
buf->p = p;
buf->ptr = p;
buf->fromport = 0;
buf->fromaddr = NULL;
/* Let the stack know that we have taken the data. */
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
conn->err = ERR_MEM;
return buf;
}
msg->type = API_MSG_RECV;
msg->msg.conn = conn;
if(buf != NULL) {
msg->msg.msg.len = buf->p->tot_len;
} else {
msg->msg.msg.len = 1;
}
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
} else {
sys_mbox_fetch(conn->recvmbox, (void **)&buf);
}
DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", buf, conn->err));
return buf;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
struct api_msg *msg;
if(conn == NULL) {
return ERR_VAL;
}
if(conn->err != ERR_OK) {
return conn->err;
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
msg->type = API_MSG_SEND;
msg->msg.conn = conn;
msg->msg.msg.p = buf->p;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
memp_freep(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
{
struct api_msg *msg;
u16_t len;
if(conn == NULL) {
return ERR_VAL;
}
if(conn->err != ERR_OK) {
return conn->err;
}
if(conn->sem == SYS_SEM_NULL) {
conn->sem = sys_sem_new(0);
if(conn->sem == SYS_SEM_NULL) {
return ERR_MEM;
}
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
msg->type = API_MSG_WRITE;
msg->msg.conn = conn;
conn->state = NETCONN_WRITE;
while(conn->err == ERR_OK && size > 0) {
msg->msg.msg.w.dataptr = dataptr;
msg->msg.msg.w.copy = copy;
if(conn->type == NETCONN_TCP) {
if(tcp_sndbuf(conn->pcb.tcp) == 0) {
sys_sem_wait(conn->sem);
if(conn->err != ERR_OK) {
goto ret;
}
}
if(size > tcp_sndbuf(conn->pcb.tcp)) {
/* We cannot send more than one send buffer's worth of data at a
time. */
len = tcp_sndbuf(conn->pcb.tcp);
} else {
len = size;
}
} else {
len = size;
}
DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
msg->msg.msg.w.len = len;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
if(conn->err == ERR_OK) {
dataptr = (void *)((char *)dataptr + len);
size -= len;
} else if(conn->err == ERR_MEM) {
conn->err = ERR_OK;
sys_sem_wait(conn->sem);
} else {
goto ret;
}
}
ret:
memp_freep(MEMP_API_MSG, msg);
conn->state = NETCONN_NONE;
if(conn->sem != SYS_SEM_NULL) {
sys_sem_free(conn->sem);
conn->sem = SYS_SEM_NULL;
}
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_close(struct netconn *conn)
{
struct api_msg *msg;
if(conn == NULL) {
return ERR_VAL;
}
if((msg = memp_mallocp(MEMP_API_MSG)) == NULL) {
return (conn->err = ERR_MEM);
}
conn->state = NETCONN_CLOSE;
again:
msg->type = API_MSG_CLOSE;
msg->msg.conn = conn;
api_msg_post(msg);
sys_mbox_fetch(conn->mbox, NULL);
if(conn->err == ERR_MEM &&
conn->sem != SYS_SEM_NULL) {
sys_sem_wait(conn->sem);
goto again;
}
conn->state = NETCONN_NONE;
memp_freep(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_err(struct netconn *conn)
{
return conn->err;
}
/*-----------------------------------------------------------------------------------*/

544
src/api/api_msg.c Normal file
View File

@@ -0,0 +1,544 @@
/*
* Copyright (c) 2001, 2002 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/debug.h"
#include "lwip/arch.h"
#include "lwip/api_msg.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
/*-----------------------------------------------------------------------------------*/
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct netconn *conn;
conn = arg;
if(conn == NULL) {
pbuf_free(p);
return ERR_VAL;
}
if(conn->recvmbox != SYS_MBOX_NULL) {
conn->err = err;
sys_mbox_post(conn->recvmbox, p);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_UDP
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;
conn = arg;
if(conn == NULL) {
pbuf_free(p);
return;
}
if(conn->recvmbox != SYS_MBOX_NULL) {
buf = memp_mallocp(MEMP_NETBUF);
if(buf == NULL) {
pbuf_free(p);
return;
} else {
buf->p = p;
buf->ptr = p;
buf->fromaddr = addr;
buf->fromport = port;
}
sys_mbox_post(conn->recvmbox, buf);
}
}
#endif /* LWIP_UDP */
/*-----------------------------------------------------------------------------------*/
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
struct netconn *conn;
conn = arg;
if(conn != NULL &&
(conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct netconn *conn;
conn = arg;
if(conn != NULL && conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
err_tcp(void *arg, err_t err)
{
struct netconn *conn;
conn = arg;
conn->pcb.tcp = NULL;
conn->err = err;
if(conn->recvmbox != SYS_MBOX_NULL) {
sys_mbox_post(conn->recvmbox, NULL);
}
if(conn->mbox != SYS_MBOX_NULL) {
sys_mbox_post(conn->mbox, NULL);
}
if(conn->acceptmbox != SYS_MBOX_NULL) {
sys_mbox_post(conn->acceptmbox, NULL);
}
if(conn->sem != SYS_SEM_NULL) {
sys_sem_signal(conn->sem);
}
}
/*-----------------------------------------------------------------------------------*/
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);
}
/*-----------------------------------------------------------------------------------*/
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
sys_mbox_t *mbox;
struct netconn *newconn;
#if API_MSG_DEBUG
#if TCP_DEBUG
tcp_debug_print_state(newpcb->state);
#endif /* TCP_DEBUG */
#endif /* API_MSG_DEBUG */
mbox = (sys_mbox_t *)arg;
newconn = memp_mallocp(MEMP_NETCONN);
if(newconn == NULL) {
return ERR_MEM;
}
newconn->type = NETCONN_TCP;
newconn->pcb.tcp = newpcb;
setup_tcp(newconn);
newconn->recvmbox = sys_mbox_new();
if(newconn->recvmbox == SYS_MBOX_NULL) {
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->mbox = sys_mbox_new();
if(newconn->mbox == SYS_MBOX_NULL) {
sys_mbox_free(newconn->recvmbox);
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->sem = sys_sem_new(0);
if(newconn->sem == SYS_SEM_NULL) {
sys_mbox_free(newconn->recvmbox);
sys_mbox_free(newconn->mbox);
memp_free(MEMP_NETCONN, newconn);
return ERR_MEM;
}
newconn->acceptmbox = SYS_MBOX_NULL;
newconn->err = err;
sys_mbox_post(*mbox, newconn);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
do_newconn(struct api_msg_msg *msg)
{
}
/*-----------------------------------------------------------------------------------*/
static void
do_delconn(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
msg->conn->pcb.udp->recv_arg = NULL;
udp_remove(msg->conn->pcb.udp);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
if(msg->conn->pcb.tcp->state == LISTEN) {
tcp_accept(msg->conn->pcb.tcp, NULL);
tcp_close(msg->conn->pcb.tcp);
} else {
tcp_arg(msg->conn->pcb.tcp, NULL);
tcp_sent(msg->conn->pcb.tcp, NULL);
tcp_recv(msg->conn->pcb.tcp, NULL);
tcp_poll(msg->conn->pcb.tcp, NULL, 0);
tcp_err(msg->conn->pcb.tcp, NULL);
if(tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
tcp_abort(msg->conn->pcb.tcp);
}
}
break;
}
}
if(msg->conn->mbox != SYS_MBOX_NULL) {
sys_mbox_post(msg->conn->mbox, NULL);
}
}
/*-----------------------------------------------------------------------------------*/
static void
do_bind(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp == NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
setup_tcp(msg->conn);
break;
}
}
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
msg->msg.bc.ipaddr, msg->msg.bc.port);
break;
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netconn *conn;
conn = arg;
if(conn == NULL) {
return ERR_VAL;
}
conn->err = err;
if(conn->type == NETCONN_TCP && err == ERR_OK) {
setup_tcp(conn);
}
sys_mbox_post(conn->mbox, NULL);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
do_connect(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp == NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDPNOCHKSUM:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
case NETCONN_UDP:
msg->conn->pcb.udp = udp_new();
if(msg->conn->pcb.udp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_new();
if(msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
sys_mbox_post(msg->conn->mbox, NULL);
return;
}
break;
}
}
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
sys_mbox_post(msg->conn->mbox, NULL);
break;
#endif
case NETCONN_TCP:
/* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
setup_tcp(msg->conn);
tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/
break;
}
}
/*-----------------------------------------------------------------------------------*/
static void
do_listen(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
if(msg->conn->pcb.tcp == NULL) {
msg->conn->err = ERR_MEM;
} else {
if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
msg->conn->acceptmbox = sys_mbox_new();
if(msg->conn->acceptmbox == SYS_MBOX_NULL) {
msg->conn->err = ERR_MEM;
break;
}
}
tcp_arg(msg->conn->pcb.tcp, (void *)&(msg->conn->acceptmbox));
tcp_accept(msg->conn->pcb.tcp, accept_function);
}
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_accept(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
break;
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
do_send(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
udp_send(msg->conn->pcb.udp, msg->msg.p);
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_recv(struct api_msg_msg *msg)
{
if(msg->conn->pcb.tcp != NULL) {
if(msg->conn->type == NETCONN_TCP) {
tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_write(struct api_msg_msg *msg)
{
err_t err;
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
msg->conn->err = ERR_VAL;
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
msg->msg.w.len, msg->msg.w.copy);
/* This is the Nagle algorithm: inhibit the sending of new TCP
segments when new outgoing data arrives from the user if any
previously transmitted data on the connection remains
unacknowledged. */
if(err == ERR_OK && msg->conn->pcb.tcp->unacked == NULL) {
tcp_output(msg->conn->pcb.tcp);
}
msg->conn->err = err;
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_close(struct api_msg_msg *msg)
{
err_t err;
if(msg->conn->pcb.tcp != NULL) {
switch(msg->conn->type) {
#if LWIP_UDP
case NETCONN_UDPLITE:
/* FALLTHROUGH */
case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */
case NETCONN_UDP:
break;
#endif /* LWIP_UDP */
case NETCONN_TCP:
if(msg->conn->pcb.tcp->state == LISTEN) {
err = tcp_close(msg->conn->pcb.tcp);
}
msg->conn->err = err;
break;
}
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] = {
do_newconn,
do_delconn,
do_bind,
do_connect,
do_listen,
do_accept,
do_send,
do_recv,
do_write,
do_close
};
void
api_msg_input(struct api_msg *msg)
{
decode[msg->type](&(msg->msg));
}
/*-----------------------------------------------------------------------------------*/
void
api_msg_post(struct api_msg *msg)
{
tcpip_apimsg(msg);
}
/*-----------------------------------------------------------------------------------*/

59
src/api/err.c Normal file
View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2001, 2002 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 char *err_strerr[] = {"Ok.",
"Out of memory error.",
"Buffer error.",
"Connection aborted.",
"Connection reset.",
"Connection closed.",
"Not connected.",
"Illegal value.",
"Illegal argument.",
"Routing problem.",
"Address in use."
};
/*-----------------------------------------------------------------------------------*/
char *
lwip_strerr(err_t err)
{
return err_strerr[-err];
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */

441
src/api/sockets.c Normal file
View File

@@ -0,0 +1,441 @@
/*
* Copyright (c) 2001, 2002 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/debug.h"
#include "lwip/api.h"
#include "lwip/sockets.h"
#define NUM_SOCKETS 10
struct lwip_socket {
struct netconn *conn;
struct netbuf *lastdata;
u16_t lastoffset;
};
static struct lwip_socket sockets[NUM_SOCKETS];
/*-----------------------------------------------------------------------------------*/
static struct lwip_socket *
get_socket(int s)
{
struct lwip_socket *sock;
if(s > NUM_SOCKETS) {
/* errno = EBADF; */
return NULL;
}
sock = &sockets[s];
if(sock->conn == NULL) {
/* errno = EBADF; */
return NULL;
}
return sock;
}
/*-----------------------------------------------------------------------------------*/
static int
alloc_socket(struct netconn *newconn)
{
int i;
/* allocate a new socket identifier */
for(i = 0; i < NUM_SOCKETS; ++i) {
if(sockets[i].conn == NULL) {
sockets[i].conn = newconn;
sockets[i].lastdata = NULL;
sockets[i].lastoffset = 0;
return i;
}
}
return -1;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_accept(int s, struct sockaddr *addr, int *addrlen)
{
struct lwip_socket *sock;
struct netconn *newconn;
struct ip_addr *naddr;
u16_t port;
int newsock;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
newconn = netconn_accept(sock->conn);
/* get the IP address and port of the remote host */
netconn_peer(newconn, &naddr, &port);
((struct sockaddr_in *)addr)->sin_addr.s_addr = naddr->addr;
((struct sockaddr_in *)addr)->sin_port = port;
newsock = alloc_socket(newconn);
if(newsock == -1) {
netconn_delete(newconn);
/* errno = ENOBUFS; */
}
return newsock;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_bind(int s, struct sockaddr *name, int namelen)
{
struct lwip_socket *sock;
struct ip_addr remote_addr;
u16_t remote_port;
err_t err;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port;
err = netconn_bind(sock->conn, &remote_addr, ntohs(remote_port));
if(err != ERR_OK) {
/* errno = ... */
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_close(int s)
{
struct lwip_socket *sock;
DEBUGF(SOCKETS_DEBUG, ("close: socket %d\n", s));
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
netconn_delete(sock->conn);
if(sock->lastdata != NULL) {
netbuf_delete(sock->lastdata);
}
sock->lastdata = NULL;
sock->lastoffset = 0;
sock->conn = NULL;
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_connect(int s, struct sockaddr *name, int namelen)
{
struct lwip_socket *sock;
struct ip_addr remote_addr;
u16_t remote_port;
err_t err;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port;
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
if(err != ERR_OK) {
/* errno = ... */
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_listen(int s, int backlog)
{
struct lwip_socket *sock;
err_t err;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
err = netconn_listen(sock->conn);
if(err != ERR_OK) {
/* errno = ... */
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, int *fromlen)
{
struct lwip_socket *sock;
struct netbuf *buf;
u16_t buflen, copylen;
struct ip_addr *addr;
u16_t port;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
/* Check if there is data left from the last recv operation. */
if(sock->lastdata != NULL) {
buf = sock->lastdata;
} else {
/* No data was left from the previous operation, so we try to get
some from the network. */
buf = netconn_recv(sock->conn);
if(buf == NULL) {
/* We should really do some error checking here. */
return 0;
}
}
buflen = netbuf_len(buf);
buflen -= sock->lastoffset;
if(len > buflen) {
copylen = buflen;
} else {
copylen = len;
}
/* copy the contents of the received buffer into
the supplied memory pointer mem */
netbuf_copy_partial(buf, mem, copylen, sock->lastoffset);
/* 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;
} else {
sock->lastdata = NULL;
sock->lastoffset = 0;
netbuf_delete(buf);
}
/* Check to see from where the data was. */
if(from != NULL && fromlen != NULL) {
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
((struct sockaddr_in *)from)->sin_addr.s_addr = addr->addr;
((struct sockaddr_in *)from)->sin_port = port;
*fromlen = sizeof(struct sockaddr_in);
}
/* if the length of the received data is larger than
len, this data is discarded and we return len.
otherwise we return the actual length of the received
data */
if(len > copylen) {
return copylen;
} else {
return len;
}
}
/*-----------------------------------------------------------------------------------*/
int
lwip_read(int s, void *mem, int len)
{
return lwip_recv(s, mem, len, 0);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recv(int s, void *mem, int len, unsigned int flags)
{
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_send(int s, void *data, int size, unsigned int flags)
{
struct lwip_socket *sock;
struct netbuf *buf;
err_t err;
DEBUGF(SOCKETS_DEBUG, ("send: socket %d, size %d\n", s, size));
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
switch(netconn_type(sock->conn)) {
case NETCONN_UDP:
/* create a buffer */
buf = netbuf_new();
if(buf == NULL) {
/* errno = ENOBUFS; */
return -1;
}
/* make the buffer point to the data that should
be sent */
netbuf_ref(buf, data, size);
/* send the data */
err = netconn_send(sock->conn, buf);
/* deallocated the buffer */
netbuf_delete(buf);
break;
case NETCONN_TCP:
err = netconn_write(sock->conn, data, size, NETCONN_COPY);
break;
default:
err = ERR_ARG;
break;
}
if(err != ERR_OK) {
/* errno = ... */
return -1;
}
return size;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, int tolen)
{
struct lwip_socket *sock;
struct ip_addr remote_addr, *addr;
u16_t remote_port, port;
int ret;
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
/* get the peer if currently connected */
netconn_peer(sock->conn, &addr, &port);
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)to)->sin_port;
netconn_connect(sock->conn, &remote_addr, remote_port);
ret = lwip_send(s, data, size, flags);
/* reset the remote address and port number
of the connection */
netconn_connect(sock->conn, addr, port);
return ret;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_socket(int domain, int type, int protocol)
{
struct netconn *conn;
int i;
/* create a netconn */
switch(type) {
case SOCK_DGRAM:
conn = netconn_new(NETCONN_UDP);
break;
case SOCK_STREAM:
conn = netconn_new(NETCONN_TCP);
break;
default:
/* errno = ... */
return -1;
}
if(conn == NULL) {
DEBUGF(SOCKETS_DEBUG, ("socket: could not create netconn.\n"));
/* errno = ENOBUFS; */
return -1;
}
i = alloc_socket(conn);
if(i == -1) {
/* errno = ENOBUFS; */
netconn_delete(conn);
}
return i;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_write(int s, void *data, int size)
{
struct lwip_socket *sock;
err_t err;
DEBUGF(SOCKETS_DEBUG, ("write: socket %d, size %d\n", s, size));
sock = get_socket(s);
if(sock == NULL) {
return -1;
}
switch(netconn_type(sock->conn)) {
case NETCONN_UDP:
return lwip_send(s, data, size, 0);
case NETCONN_TCP:
err = netconn_write(sock->conn, data, size, NETCONN_COPY);
break;
default:
err = ERR_ARG;
break;
}
if(err != ERR_OK) {
/* errno = ... */
return -1;
}
return size;
}
/*-----------------------------------------------------------------------------------*/

137
src/api/tcpip.c Normal file
View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 2001, 2002 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/debug.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/pbuf.h"
#include "lwip/ip.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/tcpip.h"
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
/*-----------------------------------------------------------------------------------*/
static void
tcpip_tcp_timer(void *arg)
{
tcp_tmr();
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
ip_init();
udp_init();
tcp_init();
sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL);
if(tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
while(1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg);
switch(msg->type) {
case TCPIP_MSG_API:
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", msg));
api_msg_input(msg->msg.apimsg);
break;
case TCPIP_MSG_INPUT:
DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", msg));
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
break;
default:
break;
}
memp_freep(MEMP_TCPIP_MSG, msg);
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
pbuf_free(p);
return ERR_MEM;
}
msg->type = TCPIP_MSG_INPUT;
msg->msg.inp.p = p;
msg->msg.inp.netif = inp;
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg *msg;
msg = memp_mallocp(MEMP_TCPIP_MSG);
if(msg == NULL) {
memp_free(MEMP_API_MSG, apimsg);
return;
}
msg->type = TCPIP_MSG_API;
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(void (* initfunc)(void *), void *arg)
{
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
mbox = sys_mbox_new();
sys_thread_new((void *)tcpip_thread, NULL);
}
/*-----------------------------------------------------------------------------------*/