tcpip.c revision 7c90a188b164765cebe27fa754d68a4321ded83e
/**
* @file
* Sequential API Main thread module
*
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* 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.
*
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#if !NO_SYS /* don't build if not configured for use in lwipopts.h */
/* global variables */
static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg;
static sys_mbox_t mbox;
/** The global semaphore to lock the stack. */
#endif /* LWIP_TCPIP_CORE_LOCKING */
/**
* The main lwIP thread. This thread has exclusive access to lwIP core functions
* (unless access to them is not locked). Other threads communicate with this
* thread using message boxes.
*
* It also starts all the timers to make sure they are running in the right
* thread context.
*
* @param arg unused argument
*/
static void
tcpip_thread(void *arg)
{
if (tcpip_init_done != NULL) {
}
while (1) { /* MAIN Loop */
/* wait for a message, timeouts are processed while waiting */
#if LWIP_NETCONN
case TCPIP_MSG_API:
break;
#endif /* LWIP_NETCONN */
case TCPIP_MSG_INPKT:
#if LWIP_ETHERNET
} else
#endif /* LWIP_ETHERNET */
#if LWIP_IPV6
} else
#endif /* LWIP_IPV6 */
{
}
break;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
#if LWIP_NETIF_API
case TCPIP_MSG_NETIFAPI:
break;
#endif /* LWIP_NETIF_API */
case TCPIP_MSG_TIMEOUT:
break;
case TCPIP_MSG_UNTIMEOUT:
break;
#endif /* LWIP_TCPIP_TIMEOUT */
case TCPIP_MSG_CALLBACK:
break;
break;
#ifdef VBOX
}
goto terminate;
#endif
default:
LWIP_ASSERT("tcpip_thread: invalid message", 0);
break;
}
}
#ifdef VBOX
/* XXX: TODO: lwip cleanup? */
#endif
}
/**
* Pass a received packet to tcpip_thread for input processing
*
* @param p the received packet, p->payload pointing to the Ethernet header or
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
* NETIF_FLAG_ETHERNET flags)
* @param inp the network interface on which the packet was received
*/
{
#if LWIP_ETHERNET
} else
#endif /* LWIP_ETHERNET */
{
}
return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
if (!sys_mbox_valid(&mbox)) {
return ERR_VAL;
}
return ERR_MEM;
}
return ERR_MEM;
}
return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
/**
* Call a specific function in the thread context of
* tcpip_thread for easy access synchronization.
* A function called in that way may access lwIP core code
* without fearing concurrent access.
*
* @param f the function to call
* @param ctx parameter passed to f
* @param block 1 to block until the request is posted, 0 to non-blocking mode
* @return ERR_OK if the function was called, another err_t if not
*/
{
if (sys_mbox_valid(&mbox)) {
return ERR_MEM;
}
if (block) {
} else {
return ERR_MEM;
}
}
return ERR_OK;
}
return ERR_VAL;
}
/**
* call sys_timeout in tcpip_thread
*
* @param msec time in milliseconds for timeout
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
{
if (sys_mbox_valid(&mbox)) {
return ERR_MEM;
}
return ERR_OK;
}
return ERR_VAL;
}
/**
* call sys_untimeout in tcpip_thread
*
* @param msec time in milliseconds for timeout
* @param h function to be called on timeout
* @param arg argument to pass to timeout function h
* @return ERR_MEM on memory error, ERR_OK otherwise
*/
{
if (sys_mbox_valid(&mbox)) {
return ERR_MEM;
}
return ERR_OK;
}
return ERR_VAL;
}
#endif /* LWIP_TCPIP_TIMEOUT */
#if LWIP_NETCONN
/**
* Call the lower part of a netconn_* function
* This function is then running in the thread context
* of tcpip_thread and has exclusive access to lwIP core code.
*
* @param apimsg a struct containing the function to call and its parameters
* @return ERR_OK if the function was called, another err_t if not
*/
{
#ifdef LWIP_DEBUG
/* catch functions that don't set err */
#endif
if (sys_mbox_valid(&mbox)) {
}
return ERR_VAL;
}
#endif /* LWIP_NETCONN */
#if LWIP_NETIF_API
/**
* Much like tcpip_apimsg, but calls the lower part of a netifapi_*
* function.
*
* @param netifapimsg a struct containing the function to call and its parameters
* @return error code given back by the function that was called
*/
{
if (sys_mbox_valid(&mbox)) {
return err;
}
}
return ERR_VAL;
}
#else /* !LWIP_TCPIP_CORE_LOCKING */
/**
* Call the lower part of a netifapi_* function
* This function has exclusive access to lwIP core code by locking it
* before the function is called.
*
* @param netifapimsg a struct containing the function to call and its parameters
* @return ERR_OK (only for compatibility fo tcpip_netifapi())
*/
{
}
#endif /* !LWIP_TCPIP_CORE_LOCKING */
#endif /* LWIP_NETIF_API */
/**
* Allocate a structure for a static callback message and initialize it.
* This is intended to be used to send "static" messages from interrupt context.
*
* @param function the function to call
* @param ctx parameter passed to function
* @return a struct pointer to pass to tcpip_trycallback().
*/
{
return NULL;
}
return (struct tcpip_callback_msg*)msg;
}
/**
* Free a callback message allocated by tcpip_callbackmsg_new().
*
* @param msg the message to free
*/
{
}
/**
* Try to post a callback-message to the tcpip_thread mbox
* This is intended to be used to send "static" messages from interrupt context.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost() return code
*/
{
if (!sys_mbox_valid(&mbox)) {
return ERR_VAL;
}
}
/**
* Post a callback-message to the tcpip_thread mbox.
*
* This is used to send "static" messages. Not necessarily "from
* interrupt context" - avoiding unnecessary malloc() is always good.
*
* To prevent confusion and to provide API symmetry there's a
* counterpart macro tcpip_trycallbackmsg() that aliases
* tcpip_trycallback() above.
*
* @param msg pointer to the message to post
* @return sys_mbox_trypost() return code
*/
{
if (!sys_mbox_valid(&mbox)) {
return ERR_VAL;
}
return ERR_OK;
}
/**
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
void
{
lwip_init();
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
/**
* Simple callback function used with tcpip_callback to free a pbuf
* (pbuf_free has a wrong signature for tcpip_callback)
*
* @param p The pbuf (chain) to be dereferenced.
*/
static void
pbuf_free_int(void *p)
{
pbuf_free(q);
}
/**
* A simple wrapper function that allows you to free a pbuf from interrupt context.
*
* @param p The pbuf (chain) to be dereferenced.
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
pbuf_free_callback(struct pbuf *p)
{
return tcpip_callback_with_block(pbuf_free_int, p, 0);
}
/**
* A simple wrapper function that allows you to free heap memory from
* interrupt context.
*
* @param m the heap memory to free
* @return ERR_OK if callback could be enqueued, an err_t if not
*/
mem_free_callback(void *m)
{
return tcpip_callback_with_block(mem_free, m, 0);
}
#endif /* !NO_SYS */