mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2026-05-20 23:26:56 +08:00
Initial revision
This commit is contained in:
639
src/api/api_lib.c
Normal file
639
src/api/api_lib.c
Normal 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
544
src/api/api_msg.c
Normal 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
59
src/api/err.c
Normal 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
441
src/api/sockets.c
Normal 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
137
src/api/tcpip.c
Normal 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);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user