/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts (for this thread) are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_mbox_fetch(sys_mbox_t mbox, void **msg) { u32_t time_needed; struct sys_timeouts *timeouts; struct sys_timeo *tmptimeout; sys_timeout_handler h; void *arg; again: timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { UNLOCK_TCPIP_CORE(); time_needed = sys_arch_mbox_fetch(mbox, msg, 0); LOCK_TCPIP_CORE(); } else { if (timeouts->next->time > 0) { UNLOCK_TCPIP_CORE(); time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); LOCK_TCPIP_CORE(); } else { time_needed = SYS_ARCH_TIMEOUT; } if (time_needed == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message could be fetched. We should now call the timeout handler and deallocate the memory allocated for the timeout. */ tmptimeout = timeouts->next; timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (h != NULL) { LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\r\n", *(void**)&h, arg)); h(arg); } /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < timeouts->next->time) { timeouts->next->time -= time_needed; } else { timeouts->next->time = 0; } } } }
/** * Sends a message to TCPIP thread to call a function. Caller thread blocks on * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, * this has to be done by the user. * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way * with least runtime overhead. * * @param fn function to be called from TCPIP thread * @param apimsg argument to API function * @param sem semaphore to wait on * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) { #if LWIP_TCPIP_CORE_LOCKING LWIP_UNUSED_ARG(sem); LOCK_TCPIP_CORE(); fn(apimsg); UNLOCK_TCPIP_CORE(); return ERR_OK; #else /* LWIP_TCPIP_CORE_LOCKING */ TCPIP_MSG_VAR_DECLARE(msg); LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(sem, 0); TCPIP_MSG_VAR_FREE(msg); return ERR_OK; #endif /* LWIP_TCPIP_CORE_LOCKING */ }
/** * Send some data on a TCP pcb contained in a netconn * Called from netconn_write * * @param msg the api_msg_msg pointing to the connection */ void do_write(struct api_msg_msg *msg) { if (!ERR_IS_FATAL(msg->conn->err)) { if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) { #if LWIP_TCP msg->conn->state = NETCONN_WRITE; /* set all the variables used by do_writemore */ LWIP_ASSERT("already writing", msg->conn->write_msg == NULL && msg->conn->write_offset == 0); msg->conn->write_msg = msg; msg->conn->write_offset = 0; #if LWIP_TCPIP_CORE_LOCKING msg->conn->write_delayed = 0; if (do_writemore(msg->conn) != ERR_OK) { LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); UNLOCK_TCPIP_CORE(); sys_arch_sem_wait(msg->conn->op_completed, 0); LOCK_TCPIP_CORE(); LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); } #else do_writemore(msg->conn); #endif /* for both cases: if do_writemore was called, don't ACK the APIMSG! */ return; #endif /* LWIP_TCP */ #if (LWIP_UDP || LWIP_RAW) } else { msg->conn->err = ERR_VAL; #endif /* (LWIP_UDP || LWIP_RAW) */ } } TCPIP_APIMSG_ACK(msg); }
/** * 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 */ err_t tcpip_pppos_input(struct pbuf *p, struct netif *inp) { #if LWIP_TCPIP_CORE_LOCKING_INPUT err_t ret; LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_pppos_input: PACKET %p/%p\n", (void *)p, (void *)inp)); LOCK_TCPIP_CORE(); ret = pppos_input_sys(p, inp); UNLOCK_TCPIP_CORE(); return ret; #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ struct tcpip_msg *msg; if (!sys_mbox_valid_val(mbox)) { return ERR_VAL; } msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_INPKT_PPPOS; msg->msg.inp.p = p; msg->msg.inp.netif = inp; if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_INPKT, msg); return ERR_MEM; } return ERR_OK; #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ }
/** * Pass a received packet to tcpip_thread for input processing * * @param p the received packet * @param inp the network interface on which the packet was received * @param input_fn input function to call */ err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) { #if LWIP_TCPIP_CORE_LOCKING_INPUT err_t ret; LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); LOCK_TCPIP_CORE(); ret = input_fn(p, inp); UNLOCK_TCPIP_CORE(); return ret; #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ struct tcpip_msg *msg; LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_INPKT; msg->msg.inp.p = p; msg->msg.inp.netif = inp; msg->msg.inp.input_fn = input_fn; if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_INPKT, msg); return ERR_MEM; } return ERR_OK; #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ }
/** * Call the lower part of a pppapi_* function * This function has exclusive access to lwIP core code by locking it * before the function is called. * * @param pppapimsg a struct containing the function to call and its parameters * @return ERR_OK (only for compatibility fo tcpip_pppapi()) */ err_t tcpip_pppapi_lock(struct pppapi_msg* pppapimsg) { LOCK_TCPIP_CORE(); pppapimsg->function(&(pppapimsg->msg)); UNLOCK_TCPIP_CORE(); return pppapimsg->msg.err; }
/** * 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()) */ err_t tcpip_netifapi_lock(struct netifapi_msg* netifapimsg) { LOCK_TCPIP_CORE(); netifapimsg->function(&(netifapimsg->msg)); UNLOCK_TCPIP_CORE(); return netifapimsg->msg.err; }
/** * 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()) */ static err_t tcpip_netifapi_lock(tcpip_callback_fn fn, struct netifapi_msg* netifapimsg) { LOCK_TCPIP_CORE(); fn(netifapimsg); UNLOCK_TCPIP_CORE(); return netifapimsg->err; }
/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg) { u32_t time_needed; struct sys_timeo *tmptimeout; sys_timeout_handler handler; void *arg; struct sys_timeo **timeo = &next_timeout[timeo_assigned]; again: if (!(*timeo)) { time_needed = sys_arch_mbox_fetch(mbox, msg, 0); } else { if ((*timeo)->time > 0) { time_needed = sys_arch_mbox_fetch(mbox, msg, (*timeo)->time); } else { time_needed = SYS_ARCH_TIMEOUT; } if (time_needed == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message could be fetched. We should now call the timeout handler and deallocate the memory allocated for the timeout. */ tmptimeout = *timeo; *timeo = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); handler(arg); UNLOCK_TCPIP_CORE(); } LWIP_TCPIP_THREAD_ALIVE(); /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < (*timeo)->time) { (*timeo)->time -= time_needed; } else { (*timeo)->time = 0; } } } }
/** * Call the lower part of a netconn_* function * This function has exclusive access to lwIP core code by locking it * before the function is called. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK (only for compatibility fo tcpip_apimsg()) */ err_t tcpip_apimsg_lock(struct api_msg *apimsg) { LOCK_TCPIP_CORE(); apimsg->function(&(apimsg->msg)); UNLOCK_TCPIP_CORE(); return ERR_OK; }
void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) { #if LWIP_TCPIP_CORE_LOCKING LOCK_TCPIP_CORE(); fn(arg); UNLOCK_TCPIP_CORE(); #else tcpip_callback_with_block(fn, arg, 1); #endif }
static #endif /* !NO_SYS */ void sys_check_timeouts(void) { if (next_timeout) { struct sys_timeo *tmptimeout; u32_t diff; sys_timeout_handler handler; void *arg; u8_t had_one; u32_t now; now = sys_now(); /* this cares for wraparounds */ diff = now - timeouts_last_time; do { PBUF_CHECK_FREE_OOSEQ(); had_one = 0; tmptimeout = next_timeout; if (tmptimeout && (tmptimeout->time <= diff)) { /* timeout has expired */ had_one = 1; timeouts_last_time += tmptimeout->time; diff -= tmptimeout->time; next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { #if !NO_SYS /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); #endif /* !NO_SYS */ handler(arg); #if !NO_SYS UNLOCK_TCPIP_CORE(); #endif /* !NO_SYS */ } LWIP_TCPIP_THREAD_ALIVE(); } /* repeat until all expired timers have been called */ } while (had_one); } }
/** * Call the lower part of a netconn_* function * This function has exclusive access to lwIP core code by locking it * before the function is called. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK (only for compatibility fo tcpip_apimsg()) */ err_t tcpip_apimsg_lock(struct api_msg *apimsg) { #ifdef LWIP_DEBUG /* catch functions that don't set err */ apimsg->msg.err = ERR_VAL; #endif LOCK_TCPIP_CORE(); apimsg->function(&(apimsg->msg)); UNLOCK_TCPIP_CORE(); return apimsg->msg.err; }
/** * Send some data on a TCP pcb contained in a netconn * Called from netconn_write * * @param msg the api_msg_msg pointing to the connection */ void do_write(struct api_msg_msg *msg) { if (ERR_IS_FATAL(msg->conn->last_err)) { msg->err = msg->conn->last_err; } else { if (msg->conn->type == NETCONN_TCP) { #if LWIP_TCP if (msg->conn->state != NETCONN_NONE) { /* netconn is connecting, closing or in blocking write */ msg->err = ERR_INPROGRESS; } else if (msg->conn->pcb.tcp != NULL) { msg->conn->state = NETCONN_WRITE; /* set all the variables used by do_writemore */ LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && msg->conn->write_offset == 0); LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); msg->conn->current_msg = msg; msg->conn->write_offset = 0; #if LWIP_TCPIP_CORE_LOCKING msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; if (do_writemore(msg->conn) != ERR_OK) { LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); UNLOCK_TCPIP_CORE(); sys_arch_sem_wait(&msg->conn->op_completed, 0); LOCK_TCPIP_CORE(); LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); } #else /* LWIP_TCPIP_CORE_LOCKING */ do_writemore(msg->conn); #endif /* LWIP_TCPIP_CORE_LOCKING */ /* for both cases: if do_writemore was called, don't ACK the APIMSG since do_writemore ACKs it! */ return; } else { msg->err = ERR_CONN; } #else /* LWIP_TCP */ msg->err = ERR_VAL; #endif /* LWIP_TCP */ #if (LWIP_UDP || LWIP_RAW) } else { msg->err = ERR_VAL; #endif /* (LWIP_UDP || LWIP_RAW) */ } } TCPIP_APIMSG_ACK(msg); }
/** * Synchronously calls function in TCPIP thread and waits for its completion. * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or * LWIP_NETCONN_SEM_PER_THREAD. * If not, a semaphore is created and destroyed on every call which is usually * an expensive/slow operation. * @param fn Function to call * @param call Call parameters * @return Return value from tcpip_api_call_fn */ err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) { #if LWIP_TCPIP_CORE_LOCKING err_t err; LOCK_TCPIP_CORE(); err = fn(call); UNLOCK_TCPIP_CORE(); return err; #else /* LWIP_TCPIP_CORE_LOCKING */ TCPIP_MSG_VAR_DECLARE(msg); #if !LWIP_NETCONN_SEM_PER_THREAD err_t err = sys_sem_new(&call->sem, 0); if (err != ERR_OK) { return err; } #endif /* LWIP_NETCONN_SEM_PER_THREAD */ LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; #if LWIP_NETCONN_SEM_PER_THREAD TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); #else /* LWIP_NETCONN_SEM_PER_THREAD */ TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; #endif /* LWIP_NETCONN_SEM_PER_THREAD */ sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); TCPIP_MSG_VAR_FREE(msg); #if !LWIP_NETCONN_SEM_PER_THREAD sys_sem_free(&call->sem); #endif /* LWIP_NETCONN_SEM_PER_THREAD */ return call->err; #endif /* LWIP_TCPIP_CORE_LOCKING */ }
/** * 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 */ err_t tcpip_input(struct pbuf *p, struct netif *inp) { #if LWIP_TCPIP_CORE_LOCKING_INPUT err_t ret; LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp)); LOCK_TCPIP_CORE(); #if LWIP_ETHERNET if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { ret = ethernet_input(p, inp); } else #endif /* LWIP_ETHERNET */ { ret = ip_input(p, inp); } UNLOCK_TCPIP_CORE(); return ret; #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ struct tcpip_msg *msg; if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); if (msg == NULL) { return ERR_MEM; } msg->type = TCPIP_MSG_INPKT; #ifdef __ADSPBLACKFIN__ msg->flags = 0; #endif msg->msg.inp.p = p; msg->msg.inp.netif = inp; if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_INPKT, msg); return ERR_MEM; } return ERR_OK; } return ERR_VAL; #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ }
/********************************************************************************************************* ** 函数名称: __rtSafeRun ** 功能描述: 安全的运行一个回调函数, 不能破坏协议栈 ** 输 入 : pfuncHook 执行函数 ** pvArg0...5 参数 ** 输 出 : 执行结果 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __rtSafeRun (FUNCPTR pfuncHook, PVOID pvArg0, PVOID pvArg1, PVOID pvArg2, PVOID pvArg3, PVOID pvArg4, PVOID pvArg5) { #if LWIP_TCPIP_CORE_LOCKING < 1 #error sylixos need LWIP_TCPIP_CORE_LOCKING > 0 #endif /* LWIP_TCPIP_CORE_LOCKING */ INT iError; if (sys_mutex_valid(&lock_tcpip_core)) { LOCK_TCPIP_CORE(); iError = pfuncHook(pvArg0, pvArg1, pvArg2, pvArg3, pvArg4, pvArg5); UNLOCK_TCPIP_CORE(); } else { iError = pfuncHook(pvArg0, pvArg1, pvArg2, pvArg3, pvArg4, pvArg5); } return (iError); }
/** * 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) { struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } LOCK_TCPIP_CORE(); while (1) { /* MAIN Loop */ UNLOCK_TCPIP_CORE(); LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ TCPIP_MBOX_FETCH(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); if (msg == NULL) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); LWIP_ASSERT("tcpip_thread: invalid message", 0); continue; } switch (msg->type) { #if !LWIP_TCPIP_CORE_LOCKING case TCPIP_MSG_API: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); msg->msg.api_msg.function(msg->msg.api_msg.msg); break; case TCPIP_MSG_API_CALL: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); sys_sem_signal(msg->msg.api_call.sem); break; #endif /* !LWIP_TCPIP_CORE_LOCKING */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT case TCPIP_MSG_INPKT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); memp_free(MEMP_TCPIP_MSG_INPKT, msg); break; #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS case TCPIP_MSG_TIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_UNTIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_CALLBACK_STATIC: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); break; #ifdef LWIP_NETIF_DRV case TCPIP_MSG_DRV: LWIP_DEBUGF(NETIF_DEBUG, ("tcpip_thread: DRV %p\n", (void *)msg)); msg->msg.drv.drv_fn(msg->msg.drv.netif, msg->msg.drv.event); memp_free(MEMP_NETIF_DRV_MSG, msg); break; #endif default: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); LWIP_ASSERT("tcpip_thread: invalid message", 0); break; } } }
/********************************************************************************************************* ** 函数名称: __tshellArp ** 功能描述: 系统命令 "arp" ** 输 入 : iArgC 参数个数 ** ppcArgV 参数表 ** 输 出 : 0 ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __tshellArp (INT iArgC, PCHAR *ppcArgV) { if (iArgC < 2) { fprintf(stderr, "argments error!\n"); return (-ERROR_TSHELL_EPARAM); } if (lib_strcmp(ppcArgV[1], "-a") == 0) { /* 显示 arp 表 */ INT iFd; CHAR cBuffer[512]; ssize_t sstNum; iFd = open("/proc/net/arp", O_RDONLY); if (iFd < 0) { fprintf(stderr, "can not open /proc/net/arp : %s\n", lib_strerror(errno)); return (PX_ERROR); } do { sstNum = read(iFd, cBuffer, sizeof(cBuffer)); if (sstNum > 0) { write(STDOUT_FILENO, cBuffer, (size_t)sstNum); } } while (sstNum > 0); close(iFd); return (ERROR_NONE); } else if (lib_strcmp(ppcArgV[1], "-s") == 0) { /* 加入一个静态转换关系 */ INT i; INT iTemp[6]; ip_addr_t ipaddr; struct eth_addr ethaddr; err_t err; if (iArgC != 4) { fprintf(stderr, "argments error!\n"); return (-ERROR_TSHELL_EPARAM); } ipaddr.addr = ipaddr_addr(ppcArgV[2]); if (ipaddr.addr == IPADDR_NONE) { fprintf(stderr, "bad inet address : %s\n", ppcArgV[2]); return (-ERROR_TSHELL_EPARAM); } if (sscanf(ppcArgV[3], "%02x:%02x:%02x:%02x:%02x:%02x", &iTemp[0], &iTemp[1], &iTemp[2], &iTemp[3], &iTemp[4], &iTemp[5]) != 6) { fprintf(stderr, "bad physical address : %s\n", ppcArgV[3]); return (-ERROR_TSHELL_EPARAM); } for (i = 0; i < 6; i++) { ethaddr.addr[i] = (u8_t)iTemp[i]; } LOCK_TCPIP_CORE(); err = etharp_add_static_entry(&ipaddr, ðaddr); UNLOCK_TCPIP_CORE(); return (err ? PX_ERROR : ERROR_NONE); } else if (lib_strcmp(ppcArgV[1], "-d") == 0) { /* 删除一个静态转换关系 */ ip_addr_t ipaddr; err_t err; if (iArgC != 3) { /* 删除全部转换关系 */ struct netif *netif; LWIP_NETIF_LOCK(); for (netif = netif_list; netif != LW_NULL; netif = netif->next) { if (netif->flags & NETIF_FLAG_ETHARP) { netifapi_netif_common(netif, etharp_cleanup_netif, LW_NULL); } } LWIP_NETIF_UNLOCK(); return (ERROR_NONE); } ipaddr.addr = ipaddr_addr(ppcArgV[2]); if (ipaddr.addr == IPADDR_NONE) { fprintf(stderr, "bad inet address : %s\n", ppcArgV[2]); return (-ERROR_TSHELL_EPARAM); } LOCK_TCPIP_CORE(); err = etharp_remove_static_entry(&ipaddr); UNLOCK_TCPIP_CORE(); return (err ? PX_ERROR : ERROR_NONE); } else { fprintf(stderr, "argments error!\n"); return (-ERROR_TSHELL_EPARAM); } }
/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) { printf("sys_timeouts_mbox_fetch()\n"); u32_t time_needed; struct sys_timeo *tmptimeout; sys_timeout_handler handler; void *arg; again: if (!next_timeout) { printf("No Timeout, sys_arch_mbox_fetch(mbox, msg, 0)\n"); time_needed = sys_arch_mbox_fetch(mbox, msg, 0); } else { if (next_timeout->time > 0) { //printf("Have timeout, fetching with timeout of %i\n", next_timeout->time); time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); } else { //printf("No time! timing out!\n"); time_needed = SYS_ARCH_TIMEOUT; } //printf("time_needed: %i (timeout=%i)\n", time_needed, SYS_ARCH_TIMEOUT); if (time_needed == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message could be fetched. We should now call the timeout handler and deallocate the memory allocated for the timeout. */ tmptimeout = next_timeout; next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); handler(arg); UNLOCK_TCPIP_CORE(); } LWIP_TCPIP_THREAD_ALIVE(); /* We try again to fetch a message from the mbox. */ //printf("Starting over, we didnt get a message\n"); goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < next_timeout->time) { next_timeout->time -= time_needed; } else { next_timeout->time = 0; } } } }
/** * 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) { struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } LOCK_TCPIP_CORE(); while (1) { /* MAIN Loop */ UNLOCK_TCPIP_CORE(); LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ sys_timeouts_mbox_fetch(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); switch (msg->type) { #if LWIP_NETCONN case TCPIP_MSG_API: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); break; #endif /* LWIP_NETCONN */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT case TCPIP_MSG_INPKT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); #if LWIP_ETHERNET if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); } else #endif /* LWIP_ETHERNET */ { ip_input(msg->msg.inp.p, msg->msg.inp.netif); } memp_free(MEMP_TCPIP_MSG_INPKT, msg); break; #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ #if LWIP_NETIF_API case TCPIP_MSG_NETIFAPI: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); break; #endif /* LWIP_NETIF_API */ case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); memp_free(MEMP_TCPIP_MSG_API, msg); break; #if LWIP_TCPIP_TIMEOUT case TCPIP_MSG_TIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_UNTIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; #endif /* LWIP_TCPIP_TIMEOUT */ default: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); LWIP_ASSERT("tcpip_thread: invalid message", 0); break; } } }
/********************************************************************************************************* ** 函数名称: __inetPing6Prepare ** 功能描述: 构造 ping 包 ** 输 入 : icmp6hdrEcho 数据 ** pip6addrDest 目标 IP ** iDataSize 数据大小 ** pcNetif 网络接口名 (NULL 表示自动确定接口) ** pusSeqRecv 需要判断的 seq ** 输 出 : ERROR ** 全局变量: ** 调用模块: *********************************************************************************************************/ static INT __inetPing6Prepare (struct icmp6_echo_hdr *icmp6hdrEcho, struct ip6_addr *pip6addrDest, INT iDataSize, CPCHAR pcNetif, UINT16 *pusSeqRecv) { static u16_t usSeqNum = 1; REGISTER INT i; #if CHECKSUM_GEN_ICMP6 INT iError; struct ip6_addr ip6addrSrc; struct pbuf pbuf; struct netif *netif; #endif /* CHECKSUM_GEN_ICMP6 */ SYS_ARCH_DECL_PROTECT(x); icmp6hdrEcho->type = ICMP6_TYPE_EREQ; icmp6hdrEcho->code = 0; *pusSeqRecv = usSeqNum; icmp6hdrEcho->chksum = 0; icmp6hdrEcho->id = 0xAFAF; /* ID */ icmp6hdrEcho->seqno = htons(usSeqNum); /* * 填充数据 */ for(i = 0; i < iDataSize; i++) { ((PCHAR)icmp6hdrEcho)[sizeof(struct icmp6_echo_hdr) + i] = (CHAR)(i % 256); } #if CHECKSUM_GEN_ICMP6 LOCK_TCPIP_CORE(); if (pcNetif) { netif = netif_find((PCHAR)pcNetif); if (netif == LW_NULL) { UNLOCK_TCPIP_CORE(); fprintf(stderr, "Invalid interface.\n"); return (PX_ERROR); } } else { netif = LW_NULL; } iError = __inetPing6FindSrc(netif, pip6addrDest, &ip6addrSrc); UNLOCK_TCPIP_CORE(); if (iError == -1) { fprintf(stderr, "You must determine net interface.\n"); return (PX_ERROR); } else if (iError == -2) { fprintf(stderr, "Unreachable destination.\n"); return (PX_ERROR); } pbuf.next = LW_NULL; pbuf.payload = (void *)icmp6hdrEcho; pbuf.tot_len = (u16_t)(iDataSize + sizeof(struct icmp6_echo_hdr)); pbuf.len = pbuf.tot_len; pbuf.type = PBUF_ROM; pbuf.flags = 0; pbuf.ref = 1; icmp6hdrEcho->chksum = ip6_chksum_pseudo(&pbuf, IP6_NEXTH_ICMP6, pbuf.tot_len, &ip6addrSrc, pip6addrDest); #endif /* CHECKSUM_GEN_ICMP6 */ SYS_ARCH_PROTECT(x); usSeqNum++; SYS_ARCH_UNPROTECT(x); return (ERROR_NONE); }