The Pedigree Project  0.1
tcpip.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
26 /*
27  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
28  * All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without modification,
31  * are permitted provided that the following conditions are met:
32  *
33  * 1. Redistributions of source code must retain the above copyright notice,
34  * this list of conditions and the following disclaimer.
35  * 2. Redistributions in binary form must reproduce the above copyright notice,
36  * this list of conditions and the following disclaimer in the documentation
37  * and/or other materials provided with the distribution.
38  * 3. The name of the author may not be used to endorse or promote products
39  * derived from this software without specific prior written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
44  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
46  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
49  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
50  * OF SUCH DAMAGE.
51  *
52  * This file is part of the lwIP TCP/IP stack.
53  *
54  * Author: Adam Dunkels <adam@sics.se>
55  *
56  */
57 
58 #include "lwip/opt.h"
59 
60 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
61 
62 #include "lwip/priv/tcpip_priv.h"
63 #include "lwip/sys.h"
64 #include "lwip/memp.h"
65 #include "lwip/mem.h"
66 #include "lwip/init.h"
67 #include "lwip/ip.h"
68 #include "lwip/pbuf.h"
69 #include "lwip/etharp.h"
70 #include "netif/ethernet.h"
71 
72 #define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name)
73 #define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name)
74 #define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
75 #define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
76 
77 /* global variables */
78 static tcpip_init_done_fn tcpip_init_done;
79 static void *tcpip_init_done_arg;
80 static sys_mbox_t mbox;
81 
82 #if LWIP_TCPIP_CORE_LOCKING
83 
84 sys_mutex_t lock_tcpip_core;
85 #endif /* LWIP_TCPIP_CORE_LOCKING */
86 
87 #if LWIP_TIMERS
88 /* wait for a message, timeouts are processed while waiting */
89 #define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg)
90 #else /* LWIP_TIMERS */
91 /* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */
92 #define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg)
93 #endif /* LWIP_TIMERS */
94 
105 static void
106 tcpip_thread(void *arg)
107 {
108  struct tcpip_msg *msg;
109  LWIP_UNUSED_ARG(arg);
110 
111  if (tcpip_init_done != NULL) {
112  tcpip_init_done(tcpip_init_done_arg);
113  }
114 
115  LOCK_TCPIP_CORE();
116  while (1) { /* MAIN Loop */
117  UNLOCK_TCPIP_CORE();
119  /* wait for a message, timeouts are processed while waiting */
120  TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
121  LOCK_TCPIP_CORE();
122  if (msg == NULL) {
123  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
124  LWIP_ASSERT("tcpip_thread: invalid message", 0);
125  continue;
126  }
127  switch (msg->type) {
128 #if !LWIP_TCPIP_CORE_LOCKING
129  case TCPIP_MSG_API:
130  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
131  msg->msg.api_msg.function(msg->msg.api_msg.msg);
132  break;
133  case TCPIP_MSG_API_CALL:
134  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
135  msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
136  sys_sem_signal(msg->msg.api_call.sem);
137  break;
138 #endif /* !LWIP_TCPIP_CORE_LOCKING */
139 
140 #if !LWIP_TCPIP_CORE_LOCKING_INPUT
141  case TCPIP_MSG_INPKT:
142  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
143  msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
144  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
145  break;
146 #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
147 
148 #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
149  case TCPIP_MSG_TIMEOUT:
150  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
151  sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
152  memp_free(MEMP_TCPIP_MSG_API, msg);
153  break;
154  case TCPIP_MSG_UNTIMEOUT:
155  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
156  sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
157  memp_free(MEMP_TCPIP_MSG_API, msg);
158  break;
159 #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
160 
161  case TCPIP_MSG_CALLBACK:
162  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
163  msg->msg.cb.function(msg->msg.cb.ctx);
164  memp_free(MEMP_TCPIP_MSG_API, msg);
165  break;
166 
167  case TCPIP_MSG_CALLBACK_STATIC:
168  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
169  msg->msg.cb.function(msg->msg.cb.ctx);
170  break;
171 
172  default:
173  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
174  LWIP_ASSERT("tcpip_thread: invalid message", 0);
175  break;
176  }
177  }
178 }
179 
187 err_t
188 tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
189 {
190 #if LWIP_TCPIP_CORE_LOCKING_INPUT
191  err_t ret;
192  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
193  LOCK_TCPIP_CORE();
194  ret = input_fn(p, inp);
195  UNLOCK_TCPIP_CORE();
196  return ret;
197 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
198  struct tcpip_msg *msg;
199 
200  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
201 
202  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
203  if (msg == NULL) {
204  return ERR_MEM;
205  }
206 
207  msg->type = TCPIP_MSG_INPKT;
208  msg->msg.inp.p = p;
209  msg->msg.inp.netif = inp;
210  msg->msg.inp.input_fn = input_fn;
211  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
212  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
213  return ERR_MEM;
214  }
215  return ERR_OK;
216 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
217 }
218 
230 err_t
231 tcpip_input(struct pbuf *p, struct netif *inp)
232 {
233 #if LWIP_ETHERNET
235  return tcpip_inpkt(p, inp, ethernet_input);
236  } else
237 #endif /* LWIP_ETHERNET */
238  return tcpip_inpkt(p, inp, ip_input);
239 }
240 
252 err_t
253 tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
254 {
255  struct tcpip_msg *msg;
256 
257  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
258 
259  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
260  if (msg == NULL) {
261  return ERR_MEM;
262  }
263 
264  msg->type = TCPIP_MSG_CALLBACK;
265  msg->msg.cb.function = function;
266  msg->msg.cb.ctx = ctx;
267  if (block) {
268  sys_mbox_post(&mbox, msg);
269  } else {
270  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
271  memp_free(MEMP_TCPIP_MSG_API, msg);
272  return ERR_MEM;
273  }
274  }
275  return ERR_OK;
276 }
277 
278 #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
279 
287 err_t
288 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
289 {
290  struct tcpip_msg *msg;
291 
292  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
293 
294  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
295  if (msg == NULL) {
296  return ERR_MEM;
297  }
298 
299  msg->type = TCPIP_MSG_TIMEOUT;
300  msg->msg.tmo.msecs = msecs;
301  msg->msg.tmo.h = h;
302  msg->msg.tmo.arg = arg;
303  sys_mbox_post(&mbox, msg);
304  return ERR_OK;
305 }
306 
314 err_t
315 tcpip_untimeout(sys_timeout_handler h, void *arg)
316 {
317  struct tcpip_msg *msg;
318 
319  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
320 
321  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
322  if (msg == NULL) {
323  return ERR_MEM;
324  }
325 
326  msg->type = TCPIP_MSG_UNTIMEOUT;
327  msg->msg.tmo.h = h;
328  msg->msg.tmo.arg = arg;
329  sys_mbox_post(&mbox, msg);
330  return ERR_OK;
331 }
332 #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
333 
334 
347 err_t
348 tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem)
349 {
350 #if LWIP_TCPIP_CORE_LOCKING
351  LWIP_UNUSED_ARG(sem);
352  LOCK_TCPIP_CORE();
353  fn(apimsg);
354  UNLOCK_TCPIP_CORE();
355  return ERR_OK;
356 #else /* LWIP_TCPIP_CORE_LOCKING */
357  TCPIP_MSG_VAR_DECLARE(msg);
358 
359  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
360  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
361 
362  TCPIP_MSG_VAR_ALLOC(msg);
363  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
364  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
365  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
366  sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
367  sys_arch_sem_wait(sem, 0);
368  TCPIP_MSG_VAR_FREE(msg);
369  return ERR_OK;
370 #endif /* LWIP_TCPIP_CORE_LOCKING */
371 }
372 
383 err_t
384 tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
385 {
386 #if LWIP_TCPIP_CORE_LOCKING
387  err_t err;
388  LOCK_TCPIP_CORE();
389  err = fn(call);
390  UNLOCK_TCPIP_CORE();
391  return err;
392 #else /* LWIP_TCPIP_CORE_LOCKING */
393  TCPIP_MSG_VAR_DECLARE(msg);
394 
395 #if !LWIP_NETCONN_SEM_PER_THREAD
396  err_t err = sys_sem_new(&call->sem, 0);
397  if (err != ERR_OK) {
398  return err;
399  }
400 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
401 
402  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
403 
404  TCPIP_MSG_VAR_ALLOC(msg);
405  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL;
406  TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
407  TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
408 #if LWIP_NETCONN_SEM_PER_THREAD
409  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
410 #else /* LWIP_NETCONN_SEM_PER_THREAD */
411  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
412 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
413  sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
414  sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
415  TCPIP_MSG_VAR_FREE(msg);
416 
417 #if !LWIP_NETCONN_SEM_PER_THREAD
418  sys_sem_free(&call->sem);
419 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
420 
421  return call->err;
422 #endif /* LWIP_TCPIP_CORE_LOCKING */
423 }
424 
433 struct tcpip_callback_msg*
435 {
436  struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
437  if (msg == NULL) {
438  return NULL;
439  }
440  msg->type = TCPIP_MSG_CALLBACK_STATIC;
441  msg->msg.cb.function = function;
442  msg->msg.cb.ctx = ctx;
443  return (struct tcpip_callback_msg*)msg;
444 }
445 
451 void
452 tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
453 {
454  memp_free(MEMP_TCPIP_MSG_API, msg);
455 }
456 
464 err_t
465 tcpip_trycallback(struct tcpip_callback_msg* msg)
466 {
467  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
468  return sys_mbox_trypost(&mbox, msg);
469 }
470 
480 void
481 tcpip_init(tcpip_init_done_fn initfunc, void *arg)
482 {
483  lwip_init();
484 
485  tcpip_init_done = initfunc;
486  tcpip_init_done_arg = arg;
487  if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
488  LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
489  }
490 #if LWIP_TCPIP_CORE_LOCKING
491  if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
492  LWIP_ASSERT("failed to create lock_tcpip_core", 0);
493  }
494 #endif /* LWIP_TCPIP_CORE_LOCKING */
495 
497 }
498 
505 static void
506 pbuf_free_int(void *p)
507 {
508  struct pbuf *q = (struct pbuf *)p;
509  pbuf_free(q);
510 }
511 
518 err_t
520 {
521  return tcpip_callback_with_block(pbuf_free_int, p, 0);
522 }
523 
531 err_t
533 {
534  return tcpip_callback_with_block(mem_free, m, 0);
535 }
536 
537 #endif /* !NO_SYS */
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition: netif.h:181
void sys_sem_free(sys_sem_t *sem)
Definition: sys_arch.cc:113
#define TCPIP_DEBUG
Definition: opt.h:2833
void(* tcpip_init_done_fn)(void *arg)
Definition: tcpip.h:87
void mem_free(void *rmem)
Definition: mem.c:438
void(* tcpip_callback_fn)(void *ctx)
Definition: tcpip.h:89
err_t mem_free_callback(void *m)
Definition: tcpip.c:532
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:253
err_t tcpip_trycallback(struct tcpip_callback_msg *msg)
Definition: tcpip.c:465
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
Definition: sys_arch.cc:157
err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
Definition: tcpip.c:384
err_t pbuf_free_callback(struct pbuf *p)
Definition: tcpip.c:519
void memp_free(memp_t type, void *mem)
Definition: memp.c:488
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
Definition: tcpip.c:188
#define TCPIP_MBOX_SIZE
Definition: opt.h:1585
Definition: err.h:84
void lwip_init(void)
Definition: init.c:356
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.cc:83
#define NETIF_FLAG_ETHERNET
Definition: netif.h:114
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Definition: sys_arch.cc:220
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.cc:232
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:231
Definition: pbuf.h:161
u8_t flags
Definition: netif.h:324
Definition: netif.h:244
void sys_sem_signal(sys_sem_t *sem)
Definition: sys_arch.cc:147
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition: sys_arch.cc:95
#define LWIP_TCPIP_THREAD_ALIVE()
Definition: opt.h:1593
s8_t err_t
Definition: err.h:76
err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
Definition: tcpip.c:348
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
Definition: tcpip.c:481
#define LWIP_DEBUGF(debug, message)
#define TCPIP_THREAD_STACKSIZE
Definition: opt.h:1567
#define NETIF_FLAG_ETHARP
Definition: netif.h:110
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.cc:272
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:327
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
void tcpip_callbackmsg_delete(struct tcpip_callback_msg *msg)
Definition: tcpip.c:452
void * memp_malloc(memp_t type)
Definition: memp.c:404
int sys_sem_valid(sys_sem_t *sem)
Definition: sys_arch.cc:124
#define sys_mbox_valid_val(mbox)
Definition: sys.h:330
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.cc:294
struct tcpip_callback_msg * tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
Definition: tcpip.c:434
#define TCPIP_THREAD_NAME
Definition: opt.h:1558
#define TCPIP_THREAD_PRIO
Definition: opt.h:1576