Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
tcpip.c
00001 /** 00002 * @file 00003 * Sequential API Main thread module 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 00041 #if !NO_SYS /* don't build if not configured for use in lwipopts.h */ 00042 00043 #include "lwip/sys.h" 00044 #include "lwip/memp.h" 00045 #include "lwip/pbuf.h" 00046 #include "lwip/ip_frag.h" 00047 #include "lwip/tcp.h" 00048 #include "lwip/autoip.h" 00049 #include "lwip/dhcp.h" 00050 #include "lwip/igmp.h" 00051 #include "lwip/dns.h" 00052 #include "lwip/tcpip.h" 00053 #include "lwip/init.h" 00054 #include "netif/etharp.h" 00055 #include "netif/ppp_oe.h" 00056 00057 /* global variables */ 00058 static void (* tcpip_init_done)(void *arg); 00059 static void *tcpip_init_done_arg; 00060 static sys_mbox_t mbox = SYS_MBOX_NULL; 00061 00062 #if LWIP_TCPIP_CORE_LOCKING 00063 /** The global semaphore to lock the stack. */ 00064 sys_sem_t lock_tcpip_core; 00065 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00066 00067 #if LWIP_TCP 00068 /* global variable that shows if the tcp timer is currently scheduled or not */ 00069 static int tcpip_tcp_timer_active; 00070 00071 /** 00072 * Timer callback function that calls tcp_tmr() and reschedules itself. 00073 * 00074 * @param arg unused argument 00075 */ 00076 static void 00077 tcpip_tcp_timer(void *arg) 00078 { 00079 LWIP_UNUSED_ARG(arg); 00080 00081 /* call TCP timer handler */ 00082 tcp_tmr(); 00083 /* timer still needed? */ 00084 if (tcp_active_pcbs || tcp_tw_pcbs) { 00085 /* restart timer */ 00086 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); 00087 } else { 00088 /* disable timer */ 00089 tcpip_tcp_timer_active = 0; 00090 } 00091 } 00092 00093 #if !NO_SYS 00094 /** 00095 * Called from TCP_REG when registering a new PCB: 00096 * the reason is to have the TCP timer only running when 00097 * there are active (or time-wait) PCBs. 00098 */ 00099 void 00100 tcp_timer_needed(void) 00101 { 00102 /* timer is off but needed again? */ 00103 if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { 00104 /* enable and start timer */ 00105 tcpip_tcp_timer_active = 1; 00106 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); 00107 } 00108 } 00109 #endif /* !NO_SYS */ 00110 #endif /* LWIP_TCP */ 00111 00112 #if IP_REASSEMBLY 00113 /** 00114 * Timer callback function that calls ip_reass_tmr() and reschedules itself. 00115 * 00116 * @param arg unused argument 00117 */ 00118 static void 00119 ip_reass_timer(void *arg) 00120 { 00121 LWIP_UNUSED_ARG(arg); 00122 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); 00123 ip_reass_tmr(); 00124 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); 00125 } 00126 #endif /* IP_REASSEMBLY */ 00127 00128 #if LWIP_ARP 00129 /** 00130 * Timer callback function that calls etharp_tmr() and reschedules itself. 00131 * 00132 * @param arg unused argument 00133 */ 00134 static void 00135 arp_timer(void *arg) 00136 { 00137 LWIP_UNUSED_ARG(arg); 00138 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n")); 00139 etharp_tmr(); 00140 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 00141 } 00142 #endif /* LWIP_ARP */ 00143 00144 #if LWIP_DHCP 00145 /** 00146 * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself. 00147 * 00148 * @param arg unused argument 00149 */ 00150 static void 00151 dhcp_timer_coarse(void *arg) 00152 { 00153 LWIP_UNUSED_ARG(arg); 00154 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n")); 00155 dhcp_coarse_tmr(); 00156 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); 00157 } 00158 00159 /** 00160 * Timer callback function that calls dhcp_fine_tmr() and reschedules itself. 00161 * 00162 * @param arg unused argument 00163 */ 00164 static void 00165 dhcp_timer_fine(void *arg) 00166 { 00167 LWIP_UNUSED_ARG(arg); 00168 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n")); 00169 dhcp_fine_tmr(); 00170 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); 00171 } 00172 #endif /* LWIP_DHCP */ 00173 00174 #if LWIP_AUTOIP 00175 /** 00176 * Timer callback function that calls autoip_tmr() and reschedules itself. 00177 * 00178 * @param arg unused argument 00179 */ 00180 static void 00181 autoip_timer(void *arg) 00182 { 00183 LWIP_UNUSED_ARG(arg); 00184 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n")); 00185 autoip_tmr(); 00186 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); 00187 } 00188 #endif /* LWIP_AUTOIP */ 00189 00190 #if LWIP_IGMP 00191 /** 00192 * Timer callback function that calls igmp_tmr() and reschedules itself. 00193 * 00194 * @param arg unused argument 00195 */ 00196 static void 00197 igmp_timer(void *arg) 00198 { 00199 LWIP_UNUSED_ARG(arg); 00200 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n")); 00201 igmp_tmr(); 00202 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); 00203 } 00204 #endif /* LWIP_IGMP */ 00205 00206 #if LWIP_DNS 00207 /** 00208 * Timer callback function that calls dns_tmr() and reschedules itself. 00209 * 00210 * @param arg unused argument 00211 */ 00212 static void 00213 dns_timer(void *arg) 00214 { 00215 LWIP_UNUSED_ARG(arg); 00216 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n")); 00217 dns_tmr(); 00218 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); 00219 } 00220 #endif /* LWIP_DNS */ 00221 00222 /** 00223 * The main lwIP thread. This thread has exclusive access to lwIP core functions 00224 * (unless access to them is not locked). Other threads communicate with this 00225 * thread using message boxes. 00226 * 00227 * It also starts all the timers to make sure they are running in the right 00228 * thread context. 00229 * 00230 * @param arg unused argument 00231 */ 00232 static void 00233 tcpip_thread(void *arg) 00234 { 00235 struct tcpip_msg *msg; 00236 LWIP_UNUSED_ARG(arg); 00237 00238 #if IP_REASSEMBLY 00239 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL); 00240 #endif /* IP_REASSEMBLY */ 00241 #if LWIP_ARP 00242 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 00243 #endif /* LWIP_ARP */ 00244 #if LWIP_DHCP 00245 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL); 00246 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL); 00247 #endif /* LWIP_DHCP */ 00248 #if LWIP_AUTOIP 00249 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL); 00250 #endif /* LWIP_AUTOIP */ 00251 #if LWIP_IGMP 00252 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL); 00253 #endif /* LWIP_IGMP */ 00254 #if LWIP_DNS 00255 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL); 00256 #endif /* LWIP_DNS */ 00257 00258 if (tcpip_init_done != NULL) { 00259 tcpip_init_done(tcpip_init_done_arg); 00260 } 00261 00262 LOCK_TCPIP_CORE(); 00263 while (1) { /* MAIN Loop */ 00264 sys_mbox_fetch(mbox, (void *)&msg); 00265 switch (msg->type) { 00266 #if LWIP_NETCONN 00267 case TCPIP_MSG_API: 00268 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); 00269 msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); 00270 break; 00271 #endif /* LWIP_NETCONN */ 00272 00273 case TCPIP_MSG_INPKT: 00274 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); 00275 #if LWIP_ARP 00276 if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) { 00277 ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); 00278 } else 00279 #endif /* LWIP_ARP */ 00280 { ip_input(msg->msg.inp.p, msg->msg.inp.netif); 00281 } 00282 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00283 break; 00284 00285 #if LWIP_NETIF_API 00286 case TCPIP_MSG_NETIFAPI: 00287 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); 00288 msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); 00289 break; 00290 #endif /* LWIP_NETIF_API */ 00291 00292 case TCPIP_MSG_CALLBACK: 00293 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); 00294 msg->msg.cb.f(msg->msg.cb.ctx); 00295 memp_free(MEMP_TCPIP_MSG_API, msg); 00296 break; 00297 00298 case TCPIP_MSG_TIMEOUT: 00299 LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); 00300 00301 if(msg->msg.tmo.msecs != 0xffffffff) 00302 sys_timeout (msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); 00303 else 00304 sys_untimeout (msg->msg.tmo.h, msg->msg.tmo.arg); 00305 memp_free(MEMP_TCPIP_MSG_API, msg); 00306 break; 00307 00308 default: 00309 break; 00310 } 00311 } 00312 } 00313 00314 /** 00315 * Pass a received packet to tcpip_thread for input processing 00316 * 00317 * @param p the received packet, p->payload pointing to the Ethernet header or 00318 * to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag) 00319 * @param inp the network interface on which the packet was received 00320 */ 00321 err_t 00322 tcpip_input(struct pbuf *p, struct netif *inp) 00323 { 00324 struct tcpip_msg *msg; 00325 00326 if (mbox != SYS_MBOX_NULL) { 00327 msg = memp_malloc(MEMP_TCPIP_MSG_INPKT); 00328 if (msg == NULL) { 00329 return ERR_MEM; 00330 } 00331 00332 msg->type = TCPIP_MSG_INPKT; 00333 msg->msg.inp.p = p; 00334 msg->msg.inp.netif = inp; 00335 if (sys_mbox_trypost(mbox, msg) != ERR_OK) { 00336 memp_free(MEMP_TCPIP_MSG_INPKT, msg); 00337 return ERR_MEM; 00338 } 00339 return ERR_OK; 00340 } 00341 return ERR_VAL; 00342 } 00343 00344 /** 00345 * Call a specific function in the thread context of 00346 * tcpip_thread for easy access synchronization. 00347 * A function called in that way may access lwIP core code 00348 * without fearing concurrent access. 00349 * 00350 * @param f the function to call 00351 * @param ctx parameter passed to f 00352 * @param block 1 to block until the request is posted, 0 to non-blocking mode 00353 * @return ERR_OK if the function was called, another err_t if not 00354 */ 00355 err_t 00356 tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block) 00357 { 00358 struct tcpip_msg *msg; 00359 00360 if (mbox != SYS_MBOX_NULL) { 00361 msg = memp_malloc(MEMP_TCPIP_MSG_API); 00362 if (msg == NULL) { 00363 return ERR_MEM; 00364 } 00365 00366 msg->type = TCPIP_MSG_CALLBACK; 00367 msg->msg.cb.f = f; 00368 msg->msg.cb.ctx = ctx; 00369 if (block) { 00370 sys_mbox_post(mbox, msg); 00371 } else { 00372 if (sys_mbox_trypost(mbox, msg) != ERR_OK) { 00373 memp_free(MEMP_TCPIP_MSG_API, msg); 00374 return ERR_MEM; 00375 } 00376 } 00377 return ERR_OK; 00378 } 00379 return ERR_VAL; 00380 } 00381 00382 err_t 00383 tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 00384 { 00385 struct tcpip_msg *msg; 00386 00387 if (mbox != SYS_MBOX_NULL) { 00388 msg = memp_malloc(MEMP_TCPIP_MSG_API); 00389 if (msg == NULL) { 00390 return ERR_MEM; 00391 } 00392 00393 msg->type = TCPIP_MSG_TIMEOUT; 00394 msg->msg.tmo.msecs = msecs; 00395 msg->msg.tmo.h = h; 00396 msg->msg.tmo.arg = arg; 00397 sys_mbox_post(mbox, msg); 00398 return ERR_OK; 00399 } 00400 return ERR_VAL; 00401 } 00402 00403 #if LWIP_NETCONN 00404 /** 00405 * Call the lower part of a netconn_* function 00406 * This function is then running in the thread context 00407 * of tcpip_thread and has exclusive access to lwIP core code. 00408 * 00409 * @param apimsg a struct containing the function to call and its parameters 00410 * @return ERR_OK if the function was called, another err_t if not 00411 */ 00412 err_t 00413 tcpip_apimsg(struct api_msg *apimsg) 00414 { 00415 struct tcpip_msg msg; 00416 00417 if (mbox != SYS_MBOX_NULL) { 00418 msg.type = TCPIP_MSG_API; 00419 msg.msg.apimsg = apimsg; 00420 sys_mbox_post(mbox, &msg); 00421 sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); 00422 return ERR_OK; 00423 } 00424 return ERR_VAL; 00425 } 00426 00427 #if LWIP_TCPIP_CORE_LOCKING 00428 /** 00429 * Call the lower part of a netconn_* function 00430 * This function has exclusive access to lwIP core code by locking it 00431 * before the function is called. 00432 * 00433 * @param apimsg a struct containing the function to call and its parameters 00434 * @return ERR_OK (only for compatibility fo tcpip_apimsg()) 00435 */ 00436 err_t 00437 tcpip_apimsg_lock(struct api_msg *apimsg) 00438 { 00439 LOCK_TCPIP_CORE(); 00440 apimsg->function(&(apimsg->msg)); 00441 UNLOCK_TCPIP_CORE(); 00442 return ERR_OK; 00443 00444 } 00445 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00446 #endif /* LWIP_NETCONN */ 00447 00448 #if LWIP_NETIF_API 00449 #if !LWIP_TCPIP_CORE_LOCKING 00450 /** 00451 * Much like tcpip_apimsg, but calls the lower part of a netifapi_* 00452 * function. 00453 * 00454 * @param netifapimsg a struct containing the function to call and its parameters 00455 * @return error code given back by the function that was called 00456 */ 00457 err_t 00458 tcpip_netifapi(struct netifapi_msg* netifapimsg) 00459 { 00460 struct tcpip_msg msg; 00461 00462 if (mbox != SYS_MBOX_NULL) { 00463 netifapimsg->msg.sem = sys_sem_new(0); 00464 if (netifapimsg->msg.sem == SYS_SEM_NULL) { 00465 netifapimsg->msg.err = ERR_MEM; 00466 return netifapimsg->msg.err; 00467 } 00468 00469 msg.type = TCPIP_MSG_NETIFAPI; 00470 msg.msg.netifapimsg = netifapimsg; 00471 sys_mbox_post(mbox, &msg); 00472 sys_sem_wait(netifapimsg->msg.sem); 00473 sys_sem_free(netifapimsg->msg.sem); 00474 return netifapimsg->msg.err; 00475 } 00476 return ERR_VAL; 00477 } 00478 #else /* !LWIP_TCPIP_CORE_LOCKING */ 00479 /** 00480 * Call the lower part of a netifapi_* function 00481 * This function has exclusive access to lwIP core code by locking it 00482 * before the function is called. 00483 * 00484 * @param netifapimsg a struct containing the function to call and its parameters 00485 * @return ERR_OK (only for compatibility fo tcpip_netifapi()) 00486 */ 00487 err_t 00488 tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) 00489 { 00490 LOCK_TCPIP_CORE(); 00491 netifapimsg->function(&(netifapimsg->msg)); 00492 UNLOCK_TCPIP_CORE(); 00493 return netifapimsg->msg.err; 00494 } 00495 #endif /* !LWIP_TCPIP_CORE_LOCKING */ 00496 #endif /* LWIP_NETIF_API */ 00497 00498 /** 00499 * Initialize this module: 00500 * - initialize all sub modules 00501 * - start the tcpip_thread 00502 * 00503 * @param initfunc a function to call when tcpip_thread is running and finished initializing 00504 * @param arg argument to pass to initfunc 00505 */ 00506 void 00507 tcpip_init(void (* initfunc)(void *), void *arg) 00508 { 00509 lwip_init(); 00510 00511 tcpip_init_done = initfunc; 00512 tcpip_init_done_arg = arg; 00513 mbox = sys_mbox_new(TCPIP_MBOX_SIZE); 00514 #if LWIP_TCPIP_CORE_LOCKING 00515 lock_tcpip_core = sys_sem_new(1); 00516 #endif /* LWIP_TCPIP_CORE_LOCKING */ 00517 00518 sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); 00519 } 00520 00521 #endif /* !NO_SYS */
Generated on Tue Jul 12 2022 16:07:20 by
1.7.2
