]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/api/tcpip.c
Changed initialization: many init functions are not needed any more since we now...
[pes-rpp/rpp-lwip.git] / src / api / tcpip.c
1 /**
2  * @file
3  * Sequential API Main thread module
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38
39 #include "lwip/opt.h"
40
41 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */
42
43 #include "lwip/sys.h"
44 #include "lwip/memp.h"
45 #include "lwip/pbuf.h"
46 #include "lwip/ip_frag.h"
47 #include "lwip/tcp.h"
48 #include "lwip/autoip.h"
49 #include "lwip/dhcp.h"
50 #include "lwip/igmp.h"
51 #include "lwip/tcpip.h"
52 #include "lwip/init.h"
53 #include "netif/etharp.h"
54 #include "netif/ppp_oe.h"
55
56 /* global variables */
57 static void (* tcpip_init_done)(void *arg);
58 static void *tcpip_init_done_arg;
59 static sys_mbox_t mbox = SYS_MBOX_NULL;
60
61 #if LWIP_TCPIP_CORE_LOCKING
62 /** The global semaphore to lock the stack. */
63 sys_sem_t lock_tcpip_core;
64 #endif /* LWIP_TCPIP_CORE_LOCKING */
65
66 #if LWIP_TCP
67 /* global variable that shows if the tcp timer is currently scheduled or not */
68 static int tcpip_tcp_timer_active;
69
70 /**
71  * Timer callback function that calls tcp_tmr() and reschedules itself.
72  *
73  * @param arg unused argument
74  */
75 static void
76 tcpip_tcp_timer(void *arg)
77 {
78   LWIP_UNUSED_ARG(arg);
79
80   /* call TCP timer handler */
81   tcp_tmr();
82   /* timer still needed? */
83   if (tcp_active_pcbs || tcp_tw_pcbs) {
84     /* restart timer */
85     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
86   } else {
87     /* disable timer */
88     tcpip_tcp_timer_active = 0;
89   }
90 }
91
92 #if !NO_SYS
93 /**
94  * Called from TCP_REG when registering a new PCB:
95  * the reason is to have the TCP timer only running when
96  * there are active (or time-wait) PCBs.
97  */
98 void
99 tcp_timer_needed(void)
100 {
101   /* timer is off but needed again? */
102   if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
103     /* enable and start timer */
104     tcpip_tcp_timer_active = 1;
105     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
106   }
107 }
108 #endif /* !NO_SYS */
109 #endif /* LWIP_TCP */
110
111 #if IP_REASSEMBLY
112 /**
113  * Timer callback function that calls ip_reass_tmr() and reschedules itself.
114  *
115  * @param arg unused argument
116  */
117 static void
118 ip_reass_timer(void *arg)
119 {
120   LWIP_UNUSED_ARG(arg);
121   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
122   ip_reass_tmr();
123   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
124 }
125 #endif /* IP_REASSEMBLY */
126
127 #if LWIP_ARP
128 /**
129  * Timer callback function that calls etharp_tmr() and reschedules itself.
130  *
131  * @param arg unused argument
132  */
133 static void
134 arp_timer(void *arg)
135 {
136   LWIP_UNUSED_ARG(arg);
137   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
138   etharp_tmr();
139   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
140 }
141 #endif /* LWIP_ARP */
142
143 #if LWIP_DHCP
144 /**
145  * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
146  *
147  * @param arg unused argument
148  */
149 static void
150 dhcp_timer_coarse(void *arg)
151 {
152   LWIP_UNUSED_ARG(arg);
153   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
154   dhcp_coarse_tmr();
155   sys_timeout(DHCP_COARSE_TIMER_SECS*1000, dhcp_timer_coarse, NULL);
156 }
157
158 /**
159  * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
160  *
161  * @param arg unused argument
162  */
163 static void
164 dhcp_timer_fine(void *arg)
165 {
166   LWIP_UNUSED_ARG(arg);
167   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
168   dhcp_fine_tmr();
169   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
170 }
171 #endif /* LWIP_DHCP */
172
173 #if LWIP_AUTOIP
174 /**
175  * Timer callback function that calls autoip_tmr() and reschedules itself.
176  *
177  * @param arg unused argument
178  */
179 static void
180 autoip_timer(void *arg)
181 {
182   LWIP_UNUSED_ARG(arg);
183   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n"));
184   autoip_tmr();
185   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
186 }
187 #endif /* LWIP_AUTOIP */
188
189 #if LWIP_IGMP
190 /**
191  * Timer callback function that calls igmp_tmr() and reschedules itself.
192  *
193  * @param arg unused argument
194  */
195 static void
196 igmp_timer(void *arg)
197 {
198   LWIP_UNUSED_ARG(arg);
199   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
200   igmp_tmr();
201   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
202 }
203 #endif /* LWIP_IGMP */
204
205 /**
206  * The main lwIP thread. This thread has exclusive access to lwIP core functions
207  * (unless access to them is not locked). Other threads communicate with this
208  * thread using message boxes.
209  *
210  * It also starts all the timers to make sure they are running in the right
211  * thread context.
212  *
213  * @param arg unused argument
214  */
215 static void
216 tcpip_thread(void *arg)
217 {
218   struct tcpip_msg *msg;
219   LWIP_UNUSED_ARG(arg);
220
221 #if IP_REASSEMBLY
222   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
223 #endif /* IP_REASSEMBLY */
224 #if LWIP_ARP
225   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
226 #endif /* LWIP_ARP */
227 #if LWIP_DHCP
228   sys_timeout(DHCP_COARSE_TIMER_SECS*1000, dhcp_timer_coarse, NULL);
229   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
230 #endif /* LWIP_DHCP */
231 #if LWIP_AUTOIP
232   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
233 #endif /* LWIP_AUTOIP */
234 #if LWIP_IGMP
235   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
236 #endif /* LWIP_IGMP */
237
238   if (tcpip_init_done != NULL) {
239     tcpip_init_done(tcpip_init_done_arg);
240   }
241
242   LOCK_TCPIP_CORE();
243   while (1) {                          /* MAIN Loop */
244     sys_mbox_fetch(mbox, (void *)&msg);
245     switch (msg->type) {
246 #if LWIP_NETCONN
247     case TCPIP_MSG_API:
248       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
249       msg->msg.apimsg->function(&(msg->msg.apimsg->msg));
250       break;
251 #endif /* LWIP_NETCONN */
252
253     case TCPIP_MSG_INPKT:
254       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
255 #if LWIP_ARP
256       if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
257         ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
258       } else
259 #endif /* LWIP_ARP */
260       { ip_input(msg->msg.inp.p, msg->msg.inp.netif);
261       }
262       memp_free(MEMP_TCPIP_MSG_INPKT, msg);
263       break;
264
265 #if LWIP_NETIF_API
266     case TCPIP_MSG_NETIFAPI:
267       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg));
268       msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg));
269       break;
270 #endif /* LWIP_NETIF_API */
271
272     case TCPIP_MSG_CALLBACK:
273       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
274       msg->msg.cb.f(msg->msg.cb.ctx);
275       memp_free(MEMP_TCPIP_MSG_API, msg);
276       break;
277
278     case TCPIP_MSG_TIMEOUT:
279       LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
280
281       if(msg->msg.tmo.msecs != 0xffffffff)
282         sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
283       else
284         sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg);
285       memp_free(MEMP_TCPIP_MSG_API, msg);
286       break;
287
288     default:
289       break;
290     }
291   }
292 }
293
294 /**
295  * Pass a received packet to tcpip_thread for input processing
296  *
297  * @param p the received packet, p->payload pointing to the Ethernet header or
298  *          to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
299  * @param netif the network interface on which the packet was received
300  */
301 err_t
302 tcpip_input(struct pbuf *p, struct netif *inp)
303 {
304   struct tcpip_msg *msg;
305
306   if (mbox != SYS_MBOX_NULL) {
307     msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
308     if (msg == NULL) {
309       return ERR_MEM;
310     }
311
312     msg->type = TCPIP_MSG_INPKT;
313     msg->msg.inp.p = p;
314     msg->msg.inp.netif = inp;
315     sys_mbox_post(mbox, msg);
316     return ERR_OK;
317   }
318   return ERR_VAL;
319 }
320
321 /**
322  * Call a specific function in the thread context of
323  * tcpip_thread for easy access synchronization.
324  * A function called in that way may access lwIP core code
325  * without fearing concurrent access.
326  *
327  * @param f the function to call
328  * @param ctx parameter passed to f
329  * @return ERR_OK if the function was called, another err_t if not
330  */
331 err_t
332 tcpip_callback(void (*f)(void *ctx), void *ctx)
333 {
334   struct tcpip_msg *msg;
335
336   if (mbox != SYS_MBOX_NULL) {
337     msg = memp_malloc(MEMP_TCPIP_MSG_API);
338     if (msg == NULL) {
339       return ERR_MEM;
340     }
341
342     msg->type = TCPIP_MSG_CALLBACK;
343     msg->msg.cb.f = f;
344     msg->msg.cb.ctx = ctx;
345     sys_mbox_post(mbox, msg);
346     return ERR_OK;
347   }
348   return ERR_VAL;
349 }
350
351 err_t
352 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
353 {
354   struct tcpip_msg *msg;
355
356   if (mbox != SYS_MBOX_NULL) {
357     msg = memp_malloc(MEMP_TCPIP_MSG_API);
358     if (msg == NULL) {
359       return ERR_MEM;
360     }
361
362     msg->type = TCPIP_MSG_TIMEOUT;
363     msg->msg.tmo.msecs = msecs;
364     msg->msg.tmo.h = h;
365     msg->msg.tmo.arg = arg;
366     sys_mbox_post(mbox, msg);
367     return ERR_OK;
368   }
369   return ERR_VAL;
370 }
371
372 #if LWIP_NETCONN
373 /**
374  * Call the lower part of a netconn_* function
375  * This function is then running in the thread context
376  * of tcpip_thread and has exclusive access to lwIP core code.
377  *
378  * @param apimsg a struct containing the function to call and its parameters
379  * @return ERR_OK if the function was called, another err_t if not
380  */
381 err_t
382 tcpip_apimsg(struct api_msg *apimsg)
383 {
384   struct tcpip_msg msg;
385   
386   if (mbox != SYS_MBOX_NULL) {
387     msg.type = TCPIP_MSG_API;
388     msg.msg.apimsg = apimsg;
389     sys_mbox_post(mbox, &msg);
390     sys_arch_mbox_fetch(apimsg->msg.conn->mbox, NULL, 0);
391     return ERR_OK;
392   }
393   return ERR_VAL;
394 }
395
396 #if LWIP_TCPIP_CORE_LOCKING
397 /**
398  * Call the lower part of a netconn_* function
399  * This function has exclusive access to lwIP core code by locking it
400  * before the function is called.
401  *
402  * @param apimsg a struct containing the function to call and its parameters
403  * @return ERR_OK (only for compatibility fo tcpip_apimsg())
404  */
405 err_t
406 tcpip_apimsg_lock(struct api_msg *apimsg)
407 {
408   LOCK_TCPIP_CORE();
409   apimsg->function(&(apimsg->msg));
410   UNLOCK_TCPIP_CORE();
411   return ERR_OK;
412
413 }
414 #endif /* LWIP_TCPIP_CORE_LOCKING */
415 #endif /* LWIP_NETCONN */
416
417 #if LWIP_NETIF_API
418 #if !LWIP_TCPIP_CORE_LOCKING
419 /**
420  * Much like tcpip_apimsg, but calls the lower part of a netifapi_*
421  * function.
422  *
423  * @param netifapimsg a struct containing the function to call and its parameters
424  * @return error code given back by the function that was called
425  */
426 err_t
427 tcpip_netifapi(struct netifapi_msg* netifapimsg)
428 {
429   struct tcpip_msg msg;
430   
431   if (mbox != SYS_MBOX_NULL) {
432     netifapimsg->msg.sem = sys_sem_new(0);
433     if (netifapimsg->msg.sem == SYS_SEM_NULL) {
434       netifapimsg->msg.err = ERR_MEM;
435       return netifapimsg->msg.err;
436     }
437     
438     msg.type = TCPIP_MSG_NETIFAPI;
439     msg.msg.netifapimsg = netifapimsg;
440     sys_mbox_post(mbox, &msg);
441     sys_sem_wait(netifapimsg->msg.sem);
442     sys_sem_free(netifapimsg->msg.sem);
443     return netifapimsg->msg.err;
444   }
445   return ERR_VAL;
446 }
447 #else /* !LWIP_TCPIP_CORE_LOCKING */
448 /**
449  * Call the lower part of a netifapi_* function
450  * This function has exclusive access to lwIP core code by locking it
451  * before the function is called.
452  *
453  * @param netifapimsg a struct containing the function to call and its parameters
454  * @return ERR_OK (only for compatibility fo tcpip_netifapi())
455  */
456 err_t
457 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
458 {
459   LOCK_TCPIP_CORE();  
460   netifapimsg->function(&(netifapimsg->msg));
461   UNLOCK_TCPIP_CORE();
462   return netifapimsg->msg.err;
463 }
464 #endif /* !LWIP_TCPIP_CORE_LOCKING */
465 #endif /* LWIP_NETIF_API */
466
467 /**
468  * Initialize this module:
469  * - initialize all sub modules
470  * - start the tcpip_thread
471  *
472  * @param initfunc a function to call when tcpip_thread is running and finished initializing
473  * @param arg argument to pass to initfunc
474  */
475 void
476 tcpip_init(void (* initfunc)(void *), void *arg)
477 {
478   lwip_init();
479
480   tcpip_init_done = initfunc;
481   tcpip_init_done_arg = arg;
482   mbox = sys_mbox_new();
483 #if LWIP_TCPIP_CORE_LOCKING
484   lock_tcpip_core = sys_sem_new(1);
485 #endif /* LWIP_TCPIP_CORE_LOCKING */
486
487   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
488 }
489
490 #endif /* !NO_SYS */