/** * Start UDP transfer. */ static int udp_start(struct ttcp* ttcp) { ttcp->udp_end_marker_left = 5; ttcp->upcb = udp_new(); if (ttcp->upcb == NULL) { printk("TTCP [%p]: could not allocate pcb\n", ttcp); return -1; } if (ttcp->mode == TTCP_MODE_TRANSMIT) { if (udp_connect(ttcp->upcb, &ttcp->addr, ttcp->port) != ERR_OK) { printk("TTCP [%p]: udp connect failed\n", ttcp); return -1; } udp_send_data(ttcp); } else { udp_recv(ttcp->upcb, udp_recv_cb, ttcp); } return 0; }
/** * @brief Processes TFTP write request * @param to: pointer on the receive IP address * @param to_port: receive port number * @retval none */ static int IAP_tftp_process_write(struct udp_pcb *upcb, struct ip_addr *to, int to_port) { tftp_connection_args *args = NULL; /* This function is called from a callback, * therefore interrupts are disabled, * therefore we can use regular malloc */ args = mem_malloc(sizeof *args); if (!args) { IAP_tftp_cleanup_wr(upcb, args); return 0; } args->op = TFTP_WRQ; args->to_ip.addr = to->addr; args->to_port = to_port; /* the block # used as a positive response to a WRQ is _always_ 0!!! (see RFC1350) */ args->block = 0; args->tot_bytes = 0; /* set callback for receives on this UDP PCB (Protocol Control Block) */ udp_recv(upcb, IAP_wrq_recv_callback, args); total_count =0; /* init flash */ FLASH_If_Init(); /* erase user flash area */ FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS); Flash_Write_Address = USER_FLASH_FIRST_PAGE_ADDRESS; /* initiate the write transaction by sending the first ack */ IAP_tftp_send_ack_packet(upcb, to, to_port, args->block); #ifdef USE_LCD LCD_DisplayStringLine(Line9, (char*)"State: Programming.."); #endif return 0; }
/*..........................................................................*/ QState LwIPMgr_initial(LwIPMgr *me, QEvt const *e) { uint8_t macaddr[NETIF_MAX_HWADDR_LEN]; (void)e; /* suppress the compiler warning about unused parameter */ /* Configure the hardware MAC address for the Ethernet Controller */ macaddr[0] = MAC_ADDR0; macaddr[1] = MAC_ADDR1; macaddr[2] = MAC_ADDR2; macaddr[3] = MAC_ADDR3; macaddr[4] = MAC_ADDR4; macaddr[5] = MAC_ADDR5; /* initialize the Ethernet Driver */ me->netif = eth_driver_init((QActive *)me, macaddr); me->ip_addr = 0x00000000U; /* initialize to impossible value */ /* initialize the lwIP applications... */ httpd_init(); /* initialize the simple HTTP-Deamon (web server) */ http_set_ssi_handler(&ssi_handler, ssi_tags, Q_DIM(ssi_tags)); http_set_cgi_handlers(cgi_handlers, Q_DIM(cgi_handlers)); me->upcb = udp_new(); udp_bind(me->upcb, IP_ADDR_ANY, 777U); /* use port 777 for UDP */ udp_recv(me->upcb, &udp_rx_handler, me); QS_OBJ_DICTIONARY(&l_lwIPMgr); QS_OBJ_DICTIONARY(&l_lwIPMgr.te_LWIP_SLOW_TICK); QS_FUN_DICTIONARY(&QHsm_top); QS_FUN_DICTIONARY(&LwIPMgr_initial); QS_FUN_DICTIONARY(&LwIPMgr_running); QS_SIG_DICTIONARY(SEND_UDP_SIG, (QActive *)me); QS_SIG_DICTIONARY(LWIP_SLOW_TICK_SIG, (QActive *)me); QS_SIG_DICTIONARY(LWIP_RX_READY_SIG, (QActive *)me); QS_SIG_DICTIONARY(LWIP_TX_READY_SIG, (QActive *)me); QS_SIG_DICTIONARY(LWIP_RX_OVERRUN_SIG,(QActive *)me); return Q_TRAN(&LwIPMgr_connecting); }
/** * @brief Creates and initializes a UDP PCB for TFTP receive operation * @param none * @retval none */ void IAP_tftpd_init(void) { err_t err; unsigned port = 69; /* 69 is the port used for TFTP protocol initial transaction */ /* create a new UDP PCB structure */ UDPpcb = udp_new(); if (!UDPpcb) { /* Error creating PCB. Out of Memory */ return ; } /* Bind this PCB to port 69 */ err = udp_bind(UDPpcb, IP_ADDR_ANY, port); if (err == ERR_OK) { /* Initialize receive callback function */ udp_recv(UDPpcb, IAP_tftp_recv_callback, NULL); } }
/** * Initialize this module. * Send out request instantly or after SNTP_STARTUP_DELAY. */ void sntp_init(int tz) { LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE,"Sntp initializing TZ: GMT%s%02d...\n",tz > 0 ? "+" : "",tz); ets_uart_printf("Sntp initializing...\n"); sntp_tz = tz; if (sntp_pcb == NULL) { os_timer_setfn(&ntp_timer,ntp_time_update,NULL); SNTP_RESET_RETRY_TIMEOUT(); sntp_pcb = udp_new(); LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); if (sntp_pcb != NULL) { udp_recv(sntp_pcb, sntp_recv, NULL); #if SNTP_STARTUP_DELAY sys_timeout((u32_t)SNTP_STARTUP_DELAY, sntp_request, NULL); #else sntp_request(NULL); #endif } } }
/** * @brief Initialize the server application. * @param None * @retval None */ void udp_echoserver_init(void) { struct udp_pcb *upcb; err_t err; /* Create a new UDP control block */ upcb = udp_new(); if (upcb) { /* Bind the upcb to the UDP_PORT port */ /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */ err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT); if(err == ERR_OK) { /* Set a receive callback for the upcb */ udp_recv(upcb, udp_echoserver_receive_callback, NULL); } } }
static socket_error_t lwipv4_socket_create(struct socket *sock, const socket_address_family_t af, const socket_proto_family_t pf, socket_api_handler_t const handler) { switch (af) { case SOCKET_AF_INET4: break; default: return SOCKET_ERROR_BAD_FAMILY; } if (sock == NULL || handler == NULL) return SOCKET_ERROR_NULL_PTR; switch (pf) { case SOCKET_DGRAM: { struct udp_pcb *udp = udp_new(); if (udp == NULL) return SOCKET_ERROR_BAD_ALLOC; sock->stack = SOCKET_STACK_LWIP_IPV4; sock->impl = (void *)udp; udp_recv((struct udp_pcb *)sock->impl, irqUDPRecv, (void *)sock); break; } case SOCKET_STREAM: { struct tcp_pcb *tcp = tcp_new(); if (tcp == NULL) return SOCKET_ERROR_BAD_ALLOC; sock->impl = (void *)tcp; sock->stack = SOCKET_STACK_LWIP_IPV4; tcp_arg(tcp, (void*) sock); tcp_err(tcp, tcp_error_handler); break; } default: return SOCKET_ERROR_BAD_FAMILY; } sock->family = pf; sock->handler = (void*)handler; sock->rxBufChain = NULL; return SOCKET_ERROR_NONE; }
void udp_echo_init(void) { struct udp_pcb * pcb; // get new pcb pcb = udp_new(); if (pcb == NULL) { LWIP_DEBUGF(UDP_DEBUG, ("udp_new failed!\n")); return; } // bind to any IP address on port 7 if (udp_bind(pcb, IP_ADDR_ANY, 7) != ERR_OK) { LWIP_DEBUGF(UDP_DEBUG, ("udp_bind failed!\n")); return; } printf("UDP bind to PORT:7 OK!\r\n"); // set udp_echo_recv() as callback function // for received packets udp_recv(pcb, udp_echo_recv, NULL); }
/** * @brief processes tftp write operation * @param upcb: pointer on upd pcb * @param to: pointer on remote IP address * @param to_port: pointer on remote udp port * @param FileName: pointer on filename to be written * @retval error code */ int tftp_process_write(struct udp_pcb *upcb, struct ip_addr *to, int to_port, char *FileName) { tftp_connection_args *args = NULL; /* Can not create file */ if (f_open(&file_CR, (const TCHAR*)FileName, FA_CREATE_ALWAYS|FA_WRITE) != FR_OK) { tftp_send_error_message(upcb, to, to_port, TFTP_ERR_NOTDEFINED); tftp_cleanup_wr(upcb, args); return 0; } args = mem_malloc(sizeof *args); if (!args) { tftp_send_error_message(upcb, to, to_port, TFTP_ERR_NOTDEFINED); tftp_cleanup_wr(upcb, args); return 0; } args->op = TFTP_WRQ; args->to_ip.addr = to->addr; args->to_port = to_port; /* the block # used as a positive response to a WRQ is _always_ 0!!! (see RFC1350) */ args->block = 0; args->tot_bytes = 0; /* set callback for receives on this UDP PCB */ udp_recv(upcb, wrq_recv_callback, args); /* initiate the write transaction by sending the first ack */ tftp_send_ack_packet(upcb, to, to_port, args->block); return 0; }
/** * @brief Creates and initializes a UDP PCB for TFTP receive operation * @param none * @retval none */ void IAP_tftpd_init(void) { err_t err; unsigned port = 69; /* 69 is the port used for TFTP protocol initial transaction */ /* create a new UDP PCB structure */ UDPpcb = udp_new(); if (!UDPpcb) { udp_lcd_y += UPDATE_WORD_SIZE + UPDATE_ROW_DISTANCE; lcd_font24(udp_lcd_x,udp_lcd_y,COLOR_POINT,COLOR_BACK,"> ÒÔÌ«ÍøÉý¼¶³ö´íÁË¡£´íÎó´úÂ룺9",UPDATE_FONT); UDP_AddUpdateError(); /* Error creating PCB. Out of Memory */ // #ifdef USE_LCD // LCD_SetTextColor(Red); // LCD_DisplayStringLine(Line9, (uint8_t*)"Can not create pcb"); // #endif return ; } /* Bind this PCB to port 69 */ err = udp_bind(UDPpcb, IP_ADDR_ANY, port); if (err == ERR_OK) { /* Initialize receive callback function */ udp_recv(UDPpcb, IAP_tftp_recv_callback, NULL); } else { udp_lcd_y += UPDATE_WORD_SIZE + UPDATE_ROW_DISTANCE; lcd_font24(udp_lcd_x,udp_lcd_y,COLOR_POINT,COLOR_BACK,"> ÒÔÌ«ÍøÉý¼¶³ö´íÁË¡£´íÎó´úÂ룺10",UPDATE_FONT); UDP_AddUpdateError(); // #ifdef USE_LCD // LCD_SetTextColor(Red); // LCD_DisplayStringLine(Line9, (uint8_t*)"Can not bind pcb"); // #endif } }
struct udp_pcb* rpc_new_udp(const struct ip_addr *server, int remote_port, enum port_type local_port) { struct udp_pcb* ret; static int root_port = -1; struct ip_addr s = *server; ret = udp_new(); assert(ret); udp_recv(ret, my_recv, NULL); if(local_port == PORT_ROOT){ if(root_port >= ROOT_PORT_MAX || root_port < ROOT_PORT_MIN){ root_port = ROOT_PORT_MIN; debug("Recycling ports\n"); } udp_bind(ret, IP_ADDR_ANY, root_port++); }else{ /* let lwip decide for itself */ } udp_connect(ret, &s, remote_port); return ret; }
/** * Function: buildNTPUDPConnection * Description: 向远程的主机建立UDP连接 * @param ipaddr 远程主机的IP地址 * @return 创建连接的返回的状态信息 **/ static err_t buildNTPUDPConnection(ip_addr_t* ipaddr){ err_t err_status; ntp_udp_client = udp_new(); if( !ntp_udp_client){ printf("create udp pcb failed\n\r"); return ERR_VAL; } /* 先绑定udp链接 */ err_status = udp_bind(ntp_udp_client,IP_ADDR_ANY,1233); //绑定任意地址和1233端口 if(err_status != ERR_OK){ //绑定失败 printf("ntp udp bind failed\n\r"); return ERR_VAL; } err_status = udp_connect(ntp_udp_client,ipaddr,123); //与远程NTP服务器建立连接 if(err_status != ERR_OK){ //创建连接失败 printf("ntp udp create connect failed\n\r"); return ERR_VAL; } //UDP PCB收到数据时的回调函数 udp_recv(ntp_udp_client,get_ntp_time,NULL); return ERR_OK; }
void tftpd_init(void) { err_t err; unsigned port = 69; /* create a new UDP PCB structure */ UDPpcb = udp_new(); if (!UDPpcb) { /* Error creating PCB. Out of Memory */ return; } /* Bind this PCB to port 69 */ err = udp_bind(UDPpcb, IP_ADDR_ANY, port); if (err != ERR_OK) { /* Unable to bind to port */ return; } /* TFTP server start */ udp_recv(UDPpcb, recv_callback_tftp, NULL); }
static void send_ntp_req(void) { struct pbuf * p; //Once here, we should have the NTP server's IP address in memory already err_t result = dns_gethostbyname(dns_hostname, &ntp_server_ip, send_ntp_req, NULL); if (result != ERR_OK) return; //Allocate a pbuf for this packet... use PBUF_ROM since payload is permanently stored in ROM p=pbuf_alloc(PBUF_TRANSPORT, 60, PBUF_ROM); //Only continue if the allocation actually "took" if (p != NULL) { //We should have the server's IP now. //Create a UDP PCB for handling this connection. ntp_pcb = udp_new(); if (ntp_pcb == NULL) { pbuf_free(p); return; } //Register a callback for this pcb - just make it our NTP receive function. udp_recv(ntp_pcb, recv_ntp_resp, NULL); //Populate the NTP request. p->payload = (void*)ntp_request_payload; p->len = 60; p->tot_len = 60; //Send the request. udp_sendto(ntp_pcb, p, &ntp_server_ip, 123); //We no longer need the pbuf pbuf_free(p); } }
void udp_echo_init(void) { struct udp_pcb *pcb; /* get new pcb */ pcb = udp_new(); if (pcb == NULL) { LWIP_DEBUGF(UDP_DEBUG, ("udp_new failed!\r\n")); return; } /* bind to any IP address on port 7 */ if (udp_bind(pcb, IP_ADDR_ANY, 7) != ERR_OK) { LWIP_DEBUGF(UDP_DEBUG, ("udp_bind failed!\r\n")); return; } /* set udp_echo_recv() as callback function */ /* for received packets */ udp_recv(pcb, udp_echo_recv, NULL); }
/** * @brief Connect to UDP echo server * @param None * @retval None */ void udp_echoclient_connect(void) { struct ip_addr DestIPaddr; err_t err; /* Create a new UDP control block */ upcb = udp_new(); if (upcb!=NULL) { /*assign destination IP address */ IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 ); /* configure destination IP address and port */ err= udp_connect(upcb, &DestIPaddr, UDP_SERVER_PORT); if (err == ERR_OK) { /* Set a receive callback for the upcb */ udp_recv(upcb, udp_receive_callback, NULL); } } }
/** * Starts SNMP Agent. * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. */ void snmp_init(void) { struct snmp_msg_pstat *msg_ps; u8_t i; snmp1_pcb = udp_new(); if (snmp1_pcb != NULL) { udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT); udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT); } msg_ps = &msg_input_list[0]; for (i=0; i<SNMP_CONCURRENT_REQUESTS; i++) { msg_ps->state = SNMP_MSG_EMPTY; msg_ps->error_index = 0; msg_ps->error_status = SNMP_ES_NOERROR; msg_ps++; } trap_msg.pcb = snmp1_pcb; /* The coldstart trap will only be output if our outgoing interface is up & configured */ snmp_coldstart_trap(); }
void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info) { os_memset(&msg_dhcps, 0, sizeof(dhcps_msg)); pcb_dhcps = udp_new(); if (pcb_dhcps == NULL || info ==NULL) { #if DEBUGSOO > 0 os_printf("dhcps_start(): could not obtain pcb\n"); #endif } IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255); server_address = info->ip; wifi_softap_init_dhcps_lease(server_address.addr); client_address_plus.addr = dhcps_lease.start_ip.addr; udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT); udp_recv(pcb_dhcps, handle_dhcp, NULL); #if DHCPS_DEBUG os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n"); #endif }
void udpecho_raw_init(void) { udpecho_raw_pcb = udp_new(); if (udpecho_raw_pcb != NULL) { err_t err; err = udp_bind(udpecho_raw_pcb, IP_ADDR_ANY, 7); if (err == ERR_OK) { udp_recv(udpecho_raw_pcb, udpecho_raw_recv, NULL); } else { /* abort? output diagnostic? */ } } else { /* abort? output diagnostic? */ } }
/*..........................................................................*/ struct udp_pcb *server_init(u16_t port) { struct udp_pcb *pcb; err_t err; pcb = udp_new(); if (!pcb) { // iprintf("Error creating PCB. Out of Memory\n\r"); return NULL; } err = udp_bind(pcb, IP_ADDR_ANY, port); if (err != ERR_OK) { // iprintf("Unable to bind to port %d: err = %d\n\r", port, err); return NULL; } udp_recv(pcb, server_recv_callback, NULL); return pcb; }
static void udp_receiver(struct udp_pcb *upcb, struct ip_addr *listen_ip, uint16_t listen_port) { printf("U: Going in UDP_RECEIVER mode\n"); // Bind to specified port errval_t r = udp_bind(upcb, listen_ip, listen_port); if (err_is_fail(r)) { DEBUG_ERR(r, "udp_bind:"); } lwip_benchmark_control(connection_type, BMS_START_REQUEST, iterations, rdtsc()); udp_recv(upcb, udp_recv_handler, 0 /*client data, arg in callback*/); while (true) { r = event_dispatch(ws); if (err_is_fail(r)) { DEBUG_ERR(r, "in event_dispatch"); break; } } } // end function: udp_receiver
/** Ensure DHCP PCB is allocated and bound */ static err_t dhcp6_inc_pcb_refcount(void) { if (dhcp6_pcb_refcount == 0) { LWIP_ASSERT("dhcp6_inc_pcb_refcount(): memory leak", dhcp6_pcb == NULL); /* allocate UDP PCB */ dhcp6_pcb = udp_new_ip6(); if (dhcp6_pcb == NULL) { return ERR_MEM; } ip_set_option(dhcp6_pcb, SOF_BROADCAST); /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ udp_bind(dhcp6_pcb, IP6_ADDR_ANY, DHCP6_CLIENT_PORT); udp_recv(dhcp6_pcb, dhcp6_recv, NULL); } dhcp6_pcb_refcount++; return ERR_OK; }
/** * Receive callback function for UDP netconns. * Posts the packet to conn->recvmbox or deletes it on memory error. * * @see udp.h (struct udp_pcb.recv) for parameters */ static void recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) { struct netbuf *buf; struct netconn *conn; u16_t len; #if LWIP_SO_RCVBUF int recv_avail; #endif /* LWIP_SO_RCVBUF */ LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_udp must have an argument", arg != NULL); conn = (struct netconn *)arg; LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); #if LWIP_SO_RCVBUF SYS_ARCH_GET(conn->recv_avail, recv_avail); if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { #else /* LWIP_SO_RCVBUF */ if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { #endif /* LWIP_SO_RCVBUF */ pbuf_free(p); return; } buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); if (buf == NULL) { pbuf_free(p); return; } else { buf->p = p; buf->ptr = p; ip_addr_set(&buf->addr, addr); buf->port = port; #if LWIP_NETBUF_RECVINFO { const struct ip_hdr* iphdr = ip_current_header(); /* get the UDP header - always in the first pbuf, ensured by udp_input */ const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr)); #if LWIP_CHECKSUM_ON_COPY buf->flags = NETBUF_FLAG_DESTADDR; #endif /* LWIP_CHECKSUM_ON_COPY */ ip_addr_set(&buf->toaddr, ip_current_dest_addr()); buf->toport_chksum = udphdr->dest; } #endif /* LWIP_NETBUF_RECVINFO */ } len = p->tot_len; if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return; } else { #if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); #endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } } #endif /* LWIP_UDP */ #if LWIP_TCP /** * Receive callback function for TCP netconns. * Posts the packet to conn->recvmbox, but doesn't delete it on errors. * * @see tcp.h (struct tcp_pcb.recv) for parameters and return value */ static err_t recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct netconn *conn; u16_t len; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); conn = (struct netconn *)arg; LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); if (conn == NULL) { return ERR_VAL; } if (!sys_mbox_valid(&conn->recvmbox)) { /* recvmbox already deleted */ if (p != NULL) { tcp_recved(pcb, p->tot_len); pbuf_free(p); } return ERR_OK; } /* Unlike for UDP or RAW pcbs, don't check for available space using recv_avail since that could break the connection (data is already ACKed) */ /* don't overwrite fatal errors! */ NETCONN_SET_SAFE_ERR(conn, err); if (p != NULL) { len = p->tot_len; } else { len = 0; } if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ return ERR_MEM; } else { #if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); #endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } return ERR_OK; } /** * Poll callback function for TCP netconns. * Wakes up an application thread that waits for a connection to close * or data to be sent. The application thread then takes the * appropriate action to go on. * * Signals the conn->sem. * netconn_close waits for conn->sem if closing failed. * * @see tcp.h (struct tcp_pcb.poll) for parameters and return value */ static err_t poll_tcp(void *arg, struct tcp_pcb *pcb) { struct netconn *conn = (struct netconn *)arg; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("conn != NULL", (conn != NULL)); if (conn->state == NETCONN_WRITE) { do_writemore(conn); } else if (conn->state == NETCONN_CLOSE) { do_close_internal(conn); } /* @todo: implement connect timeout here? */ /* Did a nonblocking write fail before? Then check available write-space. */ if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { /* If the queued byte- or pbuf-count drops below the configured low-water limit, let select mark this pcb as writable again. */ if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); } } return ERR_OK; } /** * Sent callback function for TCP netconns. * Signals the conn->sem and calls API_EVENT. * netconn_write waits for conn->sem if send buffer is low. * * @see tcp.h (struct tcp_pcb.sent) for parameters and return value */ static err_t sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) { struct netconn *conn = (struct netconn *)arg; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("conn != NULL", (conn != NULL)); if (conn->state == NETCONN_WRITE) { do_writemore(conn); } else if (conn->state == NETCONN_CLOSE) { do_close_internal(conn); } if (conn) { /* If the queued byte- or pbuf-count drops below the configured low-water limit, let select mark this pcb as writable again. */ if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); } } return ERR_OK; } /** * Error callback function for TCP netconns. * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. * The application thread has then to decide what to do. * * @see tcp.h (struct tcp_pcb.err) for parameters */ static void err_tcp(void *arg, err_t err) { struct netconn *conn; enum netconn_state old_state; SYS_ARCH_DECL_PROTECT(lev); conn = (struct netconn *)arg; LWIP_ASSERT("conn != NULL", (conn != NULL)); conn->pcb.tcp = NULL; /* no check since this is always fatal! */ SYS_ARCH_PROTECT(lev); conn->last_err = err; SYS_ARCH_UNPROTECT(lev); /* reset conn->state now before waking up other threads */ old_state = conn->state; conn->state = NETCONN_NONE; /* Notify the user layer about a connection error. Used to signal select. */ API_EVENT(conn, NETCONN_EVT_ERROR, 0); /* Try to release selects pending on 'read' or 'write', too. They will get an error if they actually try to read or write. */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); /* pass NULL-message to recvmbox to wake up pending recv */ if (sys_mbox_valid(&conn->recvmbox)) { /* use trypost to prevent deadlock */ sys_mbox_trypost(&conn->recvmbox, NULL); } /* pass NULL-message to acceptmbox to wake up pending accept */ if (sys_mbox_valid(&conn->acceptmbox)) { /* use trypost to preven deadlock */ sys_mbox_trypost(&conn->acceptmbox, NULL); } if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || (old_state == NETCONN_CONNECT)) { /* calling do_writemore/do_close_internal is not necessary since the pcb has already been deleted! */ int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); SET_NONBLOCKING_CONNECT(conn, 0); if (!was_nonblocking_connect) { /* set error return code */ LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); conn->current_msg->err = err; conn->current_msg = NULL; /* wake up the waiting task */ sys_sem_signal(&conn->op_completed); } } else { LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); } } /** * Setup a tcp_pcb with the correct callback function pointers * and their arguments. * * @param conn the TCP netconn to setup */ static void setup_tcp(struct netconn *conn) { struct tcp_pcb *pcb; pcb = conn->pcb.tcp; tcp_arg(pcb, conn); tcp_recv(pcb, recv_tcp); tcp_sent(pcb, sent_tcp); tcp_poll(pcb, poll_tcp, 4); tcp_err(pcb, err_tcp); } /** * Accept callback function for TCP netconns. * Allocates a new netconn and posts that to conn->acceptmbox. * * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value */ static err_t accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) { struct netconn *newconn; struct netconn *conn = (struct netconn *)arg; LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); if (!sys_mbox_valid(&conn->acceptmbox)) { LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); return ERR_VAL; } /* We have to set the callback here even though * the new socket is unknown. conn->socket is marked as -1. */ newconn = netconn_alloc(conn->type, conn->callback); if (newconn == NULL) { return ERR_MEM; } newconn->pcb.tcp = newpcb; setup_tcp(newconn); /* no protection: when creating the pcb, the netconn is not yet known to the application thread */ newconn->last_err = err; if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { /* When returning != ERR_OK, the pcb is aborted in tcp_process(), so do nothing here! */ /* remove all references to this netconn from the pcb */ struct tcp_pcb* pcb = newconn->pcb.tcp; tcp_arg(pcb, NULL); tcp_recv(pcb, NULL); tcp_sent(pcb, NULL); tcp_poll(pcb, NULL, 4); tcp_err(pcb, NULL); /* remove reference from to the pcb from this netconn */ newconn->pcb.tcp = NULL; /* no need to drain since we know the recvmbox is empty. */ sys_mbox_free(&newconn->recvmbox); sys_mbox_set_invalid(&newconn->recvmbox); netconn_free(newconn); return ERR_MEM; } else { /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); } return ERR_OK; } #endif /* LWIP_TCP */ /** * Create a new pcb of a specific type. * Called from do_newconn(). * * @param msg the api_msg_msg describing the connection type * @return msg->conn->err, but the return value is currently ignored */ static void pcb_new(struct api_msg_msg *msg) { LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); /* Allocate a PCB for this connection */ switch(NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.n.proto); if(msg->conn->pcb.raw == NULL) { msg->err = ERR_MEM; break; } raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->err = ERR_MEM; break; } #if LWIP_UDPLITE if (msg->conn->type==NETCONN_UDPLITE) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); } #endif /* LWIP_UDPLITE */ if (msg->conn->type==NETCONN_UDPNOCHKSUM) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->err = ERR_MEM; break; } setup_tcp(msg->conn); break; #endif /* LWIP_TCP */ default: /* Unsupported netconn type, e.g. protocol disabled */ msg->err = ERR_VAL; break; } }
/*------------------------------------------------------------------------- Description: This function is used to start DHCP Server for a network interface. Arguments: Netif: Pointer to the Lwip network interface. Return Value: The DHCP Server error code: DHCPS_ERR_SUCCESS - No error DHCPS_ERR_MEM - Out of memory DHCPS_ERR_LINKDOWN - The NI is inactive Note: The dhcp server must be started after the network interface was actived. -------------------------------------------------------------------------*/ INT32 DHCPS_Start(struct netif *Netif) { INT32U Val, Mask, tmp, i; PDHCP_CLIENT pClient; /* Check the network interface is active now. */ if(netif_is_up(Netif) == 0) { return DHCPS_ERR_LINKDOWN; } memset(&DhcpServer, 0, sizeof(DhcpServer)); /* Calculate the start ip address of the server's ip pool. */ Val = ntohl(Netif->ip_addr.addr); Mask = ntohl(Netif->netmask.addr); tmp = (Val & (~Mask)); tmp = ((tmp + 1) % (~Mask)) ? ((tmp + 1) % (~Mask)) : 1; Val = htonl((Val & Mask) | tmp); /* Configure the DHCP Server. */ ip_addr_set(&DhcpServer.ServerIpAddr, &Netif->ip_addr); ip_addr_set(&DhcpServer.StartIpAddr, (struct ip_addr *)&Val); ip_addr_set(&DhcpServer.SubnetMask, &Netif->netmask); ip_addr_set(&DhcpServer.GateWay, &Netif->ip_addr); ip_addr_set(&DhcpServer.Dns1, &Netif->ip_addr); ip_addr_set(&DhcpServer.Dns1, &Netif->ip_addr); /* Set the default lease time - 2 hours. */ DhcpServer.LeaseTime = DHCP_DEFAULT_LEASE_TIME; /* Initialize the free DHCP clients. */ for(i = 0; i < DHCPS_HISTORY_CLIENT_NUM; i++) { pClient = &DhcpServer.Clients[i]; /* Set the initial client state is "IDLE". */ pClient->State = DHCP_CLIENT_STATE_IDLE; /* Set the ip address to the client. */ Val = ntohl(DhcpServer.StartIpAddr.addr); tmp = (Val & (~Mask)); tmp = ((tmp + i) % (~Mask)) ? ((tmp + i) % (~Mask)) : 1; Val = htonl((Val & Mask) | tmp); ip_addr_set(&pClient->IpAddr, (struct ip_addr *)&Val); /* Set the default lease time. */ pClient->Lease = DHCP_DEFAULT_LEASE_TIME; } /* Allocate a UDP PCB. */ DhcpServer.Socket = udp_new(); if(DhcpServer.Socket == NULL) { return DHCPS_ERR_MEM; } /* Set up local and remote port for the pcb. */ udp_bind(DhcpServer.Socket, IP_ADDR_ANY, DHCP_SERVER_UDP_PORT); /* Set up the recv callback and argument. */ udp_recv(DhcpServer.Socket, DHCPS_RecvCb, Netif); /* Start the DHCP Server tick timer. */ sys_timeout(DHCP_TICK_TIME, _DhcpTickHandle, NULL); /* Enable the DHCP Server. */ DhcpServer.Enable = 1; return DHCPS_ERR_SUCCESS; }
/** * New proxied UDP conversation created. * Global callback for udp_proxy_accept(). */ static void pxudp_pcb_accept(void *arg, struct udp_pcb *newpcb, struct pbuf *p, ip_addr_t *addr, u16_t port) { struct pxudp *pxudp; ipX_addr_t dst_addr; int mapping; int sdom; SOCKET sock; LWIP_ASSERT1(newpcb != NULL); LWIP_ASSERT1(p != NULL); LWIP_UNUSED_ARG(arg); mapping = pxremap_outbound_ipX(PCB_ISIPV6(newpcb), &dst_addr, &newpcb->local_ip); if (mapping != PXREMAP_MAPPED && pxudp_ttl_expired(p)) { udp_remove(newpcb); return; } pxudp = pxudp_allocate(); if (pxudp == NULL) { DPRINTF(("pxudp_allocate: failed\n")); udp_remove(newpcb); pbuf_free(p); return; } sdom = PCB_ISIPV6(newpcb) ? PF_INET6 : PF_INET; pxudp->is_mapped = (mapping == PXREMAP_MAPPED); #if 0 /* XXX: DNS IPv6->IPv4 remapping hack */ if (pxudp->is_mapped && newpcb->local_port == 53 && PCB_ISIPV6(newpcb)) { /* * "Remap" DNS over IPv6 to IPv4 since Ubuntu dnsmasq does not * listen on IPv6. */ sdom = PF_INET; ipX_addr_set_loopback(0, &dst_addr); } #endif /* DNS IPv6->IPv4 remapping hack */ sock = proxy_connected_socket(sdom, SOCK_DGRAM, &dst_addr, newpcb->local_port); if (sock == INVALID_SOCKET) { udp_remove(newpcb); pbuf_free(p); return; } pxudp->sock = sock; pxudp->pcb = newpcb; udp_recv(newpcb, pxudp_pcb_recv, pxudp); pxudp->pmhdl.callback = pxudp_pmgr_pump; pxudp_chan_send(POLLMGR_CHAN_PXUDP_ADD, pxudp); /* dispatch directly instead of calling pxudp_pcb_recv() */ pxudp_pcb_forward_outbound(pxudp, p, addr, port); }
int test_net_udp(void) { struct timeval timeout; socket_udp *s1, *s2; char buf1[BUFSIZE], buf2[BUFSIZE]; const char *hname; int rc, i; #ifndef WIN32 /* "BSD" bug test that appears in this function uses fork and * exec, that are not present on WIN32. Since the original * bug has not been seen on Win32 it's probably not worth * converting to use CreateProcess() */ int status_parent, status_child; #endif /* WIN32 */ srand48(time(NULL)); /**********************************************************************/ /* The first test is to loopback a packet to ourselves... */ printf ("Testing UDP/IP networking (IPv4 loopback) ................................ "); fflush(stdout); s1 = udp_init("127.0.0.1", 5004, 5004, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } randomize(buf1, BUFSIZE); randomize(buf2, BUFSIZE); if (udp_send(s1, buf1, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot send packet"); goto abort_loopback; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_loopback; } if (rc == 0) { printf("FAIL\n"); printf(" No data waiting\n"); goto abort_loopback; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_loopback; } if (udp_recv(s1, buf2, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Receive failed"); goto abort_loopback; } if (memcmp(buf1, buf2, BUFSIZE) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_loopback; } printf("Ok\n"); abort_loopback: hname = udp_host_addr(s1); /* we need this for the unicast test... */ udp_exit(s1); /**********************************************************************/ /* Now we send a packet to ourselves via our real network address... */ printf ("Testing UDP/IP networking (IPv4 unicast) ................................. "); fflush(stdout); s1 = udp_init(hname, 5004, 5005, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } s2 = udp_init(hname, 5005, 5004, 1); if (s2 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } randomize(buf1, BUFSIZE); randomize(buf2, BUFSIZE); if (udp_send(s1, buf1, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot send"); goto abort_unicast; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); udp_fd_set(s2); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_unicast; } if (rc == 0) { printf("FAIL\n"); printf(" No data waiting (no route to %s?)\n", hname); goto abort_unicast; } if (!udp_fd_isset(s2)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_unicast; } if (udp_recv(s2, buf2, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot receive"); goto abort_unicast; } if (memcmp(buf1, buf2, BUFSIZE) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_unicast; } printf("Ok\n"); abort_unicast: udp_exit(s1); udp_exit(s2); /**********************************************************************/ /* Loopback a packet to ourselves via multicast... */ printf ("Testing UDP/IP networking (IPv4 multicast) ............................... "); fflush(stdout); s1 = udp_init("224.2.0.1", 5004, 5004, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } randomize(buf1, BUFSIZE); randomize(buf2, BUFSIZE); if (udp_send(s1, buf1, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot send"); goto abort_multicast; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_multicast; } if (rc == 0) { printf("FAIL\n"); printf(" No data waiting (no multicast loopback route?)\n"); goto abort_multicast; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_multicast; } if (udp_recv(s1, buf2, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot receive"); goto abort_multicast; } if (memcmp(buf1, buf2, BUFSIZE) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_multicast; } printf("Ok\n"); abort_multicast: udp_exit(s1); /**********************************************************************/ /* Loopback a packet to ourselves via multicast, checking lengths... */ printf ("Testing UDP/IP networking (IPv4 length check) ............................ "); fflush(stdout); s1 = udp_init("224.2.0.1", 5004, 5004, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } for (i = 1; i < BUFSIZE; i++) { randomize(buf1, i); randomize(buf2, i); if (udp_send(s1, buf1, i) < 0) { printf("FAIL\n"); perror(" Cannot send"); goto abort_length; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_length; } if (rc == 0) { printf("FAIL\n"); printf (" No data waiting (no multicast loopback route?)\n"); goto abort_length; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_length; } if (udp_recv(s1, buf2, BUFSIZE) != i) { printf("FAIL\n"); perror(" Cannot receive"); goto abort_length; } if (memcmp(buf1, buf2, i) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_length; } } printf("Ok\n"); abort_length: udp_exit(s1); #ifdef HAVE_IPv6 /**********************************************************************/ /* The first test is to loopback a packet to ourselves... */ printf ("Testing UDP/IP networking (IPv6 loopback) ................................ "); fflush(stdout); s1 = udp_init("::1", 5004, 5004, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } randomize(buf1, BUFSIZE); randomize(buf2, BUFSIZE); if (udp_send(s1, buf1, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot send"); goto abort_loopback_ipv6; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_loopback_ipv6; } if (rc == 0) { printf("FAIL\n"); printf(" No data waiting\n"); goto abort_loopback_ipv6; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_loopback_ipv6; } if (udp_recv(s1, buf2, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot receive"); goto abort_loopback_ipv6; } if (memcmp(buf1, buf2, BUFSIZE) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_loopback_ipv6; } printf("Ok\n"); abort_loopback_ipv6: udp_exit(s1); /**********************************************************************/ /* Loopback a packet to ourselves via multicast. The address is the */ /* SAP address, but we use a different port. */ printf ("Testing UDP/IP networking (IPv6 multicast) ............................... "); fflush(stdout); s1 = udp_init("ff01::2:7ffe", 5004, 5004, 1); if (s1 == NULL) { printf("FAIL\n"); printf(" Cannot initialize socket\n"); return 1; } randomize(buf1, BUFSIZE); randomize(buf2, BUFSIZE); if (udp_send(s1, buf1, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot send"); goto abort_multicast_ipv6; } timeout.tv_sec = 1; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Select failed"); goto abort_multicast_ipv6; } if (rc == 0) { printf("FAIL\n"); printf(" No data waiting (no multicast loopback route?)\n"); goto abort_multicast_ipv6; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" No data on file descriptor\n"); goto abort_multicast_ipv6; } if (udp_recv(s1, buf2, BUFSIZE) < 0) { printf("FAIL\n"); perror(" Cannot receive"); goto abort_multicast_ipv6; } if (memcmp(buf1, buf2, BUFSIZE) != 0) { printf("FAIL\n"); printf(" Buffer corrupt\n"); goto abort_multicast_ipv6; } hname = udp_host_addr(s1); /* we need this for the unicast test... */ printf("Ok\n"); abort_multicast_ipv6: udp_exit(s1); #else printf ("Testing UDP/IP networking (IPv6 loopback) ................................ --\n"); printf ("Testing UDP/IP networking (IPv6 unicast) ................................. --\n"); printf ("Testing UDP/IP networking (IPv6 multicast) ............................... --\n"); #endif /**********************************************************************/ #ifdef WIN32 printf ("Testing UDP/IP networking (FreeBSD bug) .................................. --\n"); #else printf ("Testing UDP/IP networking (FreeBSD bug) .................................. "); fflush(stdout); status_parent = 0; randomize(buf1, 64); s1 = udp_init("224.2.0.1", 5004, 5004, 1); if (s1 == NULL) { printf("fail (parent): cannot initialize socket\n"); return 1; } rc = fork(); if (rc == -1) { printf("fail: cannot fork\n"); goto abort_bsd; } else if (rc == 0) { /* child */ s2 = udp_init("224.2.0.1", 5004, 5004, 1); if (s2 == NULL) { printf("FAIL\n"); printf(" Child cannot initialize socket\n"); exit(0); } if (udp_send(s2, buf1, 64) < 0) { printf("FAIL\n"); perror(" Child cannot send"); exit(0); } timeout.tv_sec = 10; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s2); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Child select"); exit(0); } if (rc == 0) { printf("FAIL\n"); printf (" Child: no data waiting (no multicast loopback route?)\n"); exit(0); } if (!udp_fd_isset(s2)) { printf("FAIL\n"); printf(" Child: no data on file descriptor\n"); exit(0); } rc = udp_recv(s2, buf2, BUFSIZE); if (rc < 0) { printf("FAIL\n"); perror(" Child cannot receive"); exit(0); } if (rc != 64) { printf("FAIL\n"); printf(" Child: read size incorrect (%d != %d)\n", rc, 64); exit(0); } if (memcmp(buf1, buf2, 64) != 0) { printf("FAIL\n"); printf(" Child: buffer corrupt\n"); exit(0); } udp_exit(s2); exit(1); } else { /* parent */ timeout.tv_sec = 10; timeout.tv_usec = 0; udp_fd_zero(); udp_fd_set(s1); rc = udp_select(&timeout); if (rc < 0) { printf("FAIL\n"); perror(" Parent select"); goto abort_bsd; } if (rc == 0) { printf("FAIL\n"); printf (" Parent: no data waiting (no multicast loopback route?)\n"); goto abort_bsd; } if (!udp_fd_isset(s1)) { printf("FAIL\n"); printf(" Parent: no data on file descriptor\n"); goto abort_bsd; } rc = udp_recv(s1, buf2, BUFSIZE); if (rc < 0) { printf("FAIL\n"); perror(" Parent cannot receive"); goto abort_bsd; } if (rc != 64) { printf("FAIL\n"); printf(" Parent: read size incorrect (%d != %d)\n", rc, 64); goto abort_bsd; } if (memcmp(buf1, buf2, 64) != 0) { printf("FAIL\n"); printf(" Parent: buffer corrupt\n"); goto abort_bsd; } status_parent = 1; } abort_bsd: wait(&status_child); if (status_parent && status_child) { printf("Ok\n"); } udp_exit(s1); #endif /* WIN32 */ return 0; }
static void do_connect(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp == NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */ raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: msg->conn->pcb.udp = udp_new(); if (msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; sys_mbox_post(msg->conn->mbox, NULL); return; } udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDPNOCHKSUM: msg->conn->pcb.udp = udp_new(); if (msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; sys_mbox_post(msg->conn->mbox, NULL); return; } udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); if (msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; sys_mbox_post(msg->conn->mbox, NULL); return; } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if (msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; sys_mbox_post(msg->conn->mbox, NULL); return; } #endif default: break; } } switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); sys_mbox_post(msg->conn->mbox, NULL); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); sys_mbox_post(msg->conn->mbox, NULL); break; #endif #if LWIP_TCP case NETCONN_TCP: /* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/ setup_tcp(msg->conn); tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port, do_connected); /*tcp_output(msg->conn->pcb.tcp);*/ #endif default: break; } }
static void do_bind(struct api_msg_msg *msg) { if (msg->conn->pcb.tcp == NULL) { switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */ raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: msg->conn->pcb.udp = udp_new(); udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDPNOCHKSUM: msg->conn->pcb.udp = udp_new(); udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); setup_tcp(msg->conn); #endif /* LWIP_TCP */ default: break; } } switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: /* FALLTHROUGH */ case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); #endif /* LWIP_TCP */ default: break; } sys_mbox_post(msg->conn->mbox, NULL); }
static void do_newconn(struct api_msg_msg *msg) { if(msg->conn->pcb.tcp != NULL) { /* This "new" connection already has a PCB allocated. */ /* Is this an error condition? Should it be deleted? We currently just are happy and return. */ sys_mbox_post(msg->conn->mbox, NULL); return; } msg->conn->err = ERR_OK; /* Allocate a PCB for this connection */ switch(msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */ raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break; #endif #if LWIP_UDP case NETCONN_UDPLITE: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; } udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDPNOCHKSUM: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; } udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; break; } setup_tcp(msg->conn); break; #endif } sys_mbox_post(msg->conn->mbox, NULL); }
/** * Receive callback function for RAW netconns. * Doesn't 'eat' the packet, only references it and sends it to * conn->recvmbox * * @see raw.h (struct raw_pcb.recv) for parameters and return value */ static u8_t recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr) { struct pbuf *q; struct netbuf *buf; struct netconn *conn; #if LWIP_SO_RCVBUF int recv_avail; #endif /* LWIP_SO_RCVBUF */ LWIP_UNUSED_ARG(addr); conn = arg; #if LWIP_SO_RCVBUF SYS_ARCH_GET(conn->recv_avail, recv_avail); if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) && ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) { #else /* LWIP_SO_RCVBUF */ if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) { #endif /* LWIP_SO_RCVBUF */ /* copy the whole packet into new pbufs */ q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); if(q != NULL) { if (pbuf_copy(q, p) != ERR_OK) { pbuf_free(q); q = NULL; } } if(q != NULL) { buf = memp_malloc(MEMP_NETBUF); if (buf == NULL) { pbuf_free(q); return 0; } buf->p = q; buf->ptr = q; buf->addr = &(((struct ip_hdr*)(q->payload))->src); buf->port = pcb->protocol; if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return 0; } else { SYS_ARCH_INC(conn->recv_avail, q->tot_len); /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len); } } } return 0; /* do not eat the packet */ } #endif /* LWIP_RAW*/ #if LWIP_UDP /** * Receive callback function for UDP netconns. * Posts the packet to conn->recvmbox or deletes it on memory error. * * @see udp.h (struct udp_pcb.recv) for parameters */ static void recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port) { struct netbuf *buf; struct netconn *conn; #if LWIP_SO_RCVBUF int recv_avail; #endif /* LWIP_SO_RCVBUF */ LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_udp must have an argument", arg != NULL); conn = arg; LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); #if LWIP_SO_RCVBUF SYS_ARCH_GET(conn->recv_avail, recv_avail); if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) || ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { #else /* LWIP_SO_RCVBUF */ if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { #endif /* LWIP_SO_RCVBUF */ pbuf_free(p); return; } buf = memp_malloc(MEMP_NETBUF); if (buf == NULL) { pbuf_free(p); return; } else { buf->p = p; buf->ptr = p; buf->addr = addr; buf->port = port; #if LWIP_NETBUF_RECVINFO { const struct ip_hdr* iphdr = ip_current_header(); /* get the UDP header - always in the first pbuf, ensured by udp_input */ const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr)); buf->toaddr = (struct ip_addr*)&iphdr->dest; buf->toport = udphdr->dest; } #endif /* LWIP_NETBUF_RECVINFO */ } if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return; } else { SYS_ARCH_INC(conn->recv_avail, p->tot_len); /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); } } #endif /* LWIP_UDP */ #if LWIP_TCP /** * Receive callback function for TCP netconns. * Posts the packet to conn->recvmbox, but doesn't delete it on errors. * * @see tcp.h (struct tcp_pcb.recv) for parameters and return value */ static err_t recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct netconn *conn; u16_t len; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); conn = arg; LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { return ERR_VAL; } conn->err = err; if (p != NULL) { len = p->tot_len; SYS_ARCH_INC(conn->recv_avail, len); } else { len = 0; } if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) { return ERR_MEM; } else { /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } return ERR_OK; } /** * Poll callback function for TCP netconns. * Wakes up an application thread that waits for a connection to close * or data to be sent. The application thread then takes the * appropriate action to go on. * * Signals the conn->sem. * netconn_close waits for conn->sem if closing failed. * * @see tcp.h (struct tcp_pcb.poll) for parameters and return value */ static err_t poll_tcp(void *arg, struct tcp_pcb *pcb) { struct netconn *conn = arg; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("conn != NULL", (conn != NULL)); if (conn->state == NETCONN_WRITE) { do_writemore(conn); } else if (conn->state == NETCONN_CLOSE) { do_close_internal(conn); } return ERR_OK; } /** * Sent callback function for TCP netconns. * Signals the conn->sem and calls API_EVENT. * netconn_write waits for conn->sem if send buffer is low. * * @see tcp.h (struct tcp_pcb.sent) for parameters and return value */ static err_t sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) { struct netconn *conn = arg; LWIP_UNUSED_ARG(pcb); LWIP_ASSERT("conn != NULL", (conn != NULL)); if (conn->state == NETCONN_WRITE) { LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); do_writemore(conn); } else if (conn->state == NETCONN_CLOSE) { do_close_internal(conn); } if (conn) { if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) { API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); } } return ERR_OK; } /** * Error callback function for TCP netconns. * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. * The application thread has then to decide what to do. * * @see tcp.h (struct tcp_pcb.err) for parameters */ static void err_tcp(void *arg, err_t err) { struct netconn *conn; conn = arg; LWIP_ASSERT("conn != NULL", (conn != NULL)); conn->pcb.tcp = NULL; conn->err = err; if (conn->recvmbox != SYS_MBOX_NULL) { /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); sys_mbox_post(conn->recvmbox, NULL); } if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) { conn->state = NETCONN_NONE; sys_sem_signal(conn->op_completed); } if (conn->acceptmbox != SYS_MBOX_NULL) { /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); sys_mbox_post(conn->acceptmbox, NULL); } if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) { /* calling do_writemore/do_close_internal is not necessary since the pcb has already been deleted! */ conn->state = NETCONN_NONE; /* wake up the waiting task */ sys_sem_signal(conn->op_completed); } } /** * Setup a tcp_pcb with the correct callback function pointers * and their arguments. * * @param conn the TCP netconn to setup */ static void setup_tcp(struct netconn *conn) { struct tcp_pcb *pcb; pcb = conn->pcb.tcp; tcp_arg(pcb, conn); tcp_recv(pcb, recv_tcp); tcp_sent(pcb, sent_tcp); tcp_poll(pcb, poll_tcp, 4); tcp_err(pcb, err_tcp); } /** * Accept callback function for TCP netconns. * Allocates a new netconn and posts that to conn->acceptmbox. * * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value */ static err_t accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) { struct netconn *newconn; struct netconn *conn; #if API_MSG_DEBUG #if TCP_DEBUG tcp_debug_print_state(newpcb->state); #endif /* TCP_DEBUG */ #endif /* API_MSG_DEBUG */ conn = (struct netconn *)arg; LWIP_ERROR("accept_function: invalid conn->acceptmbox", conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;); /* We have to set the callback here even though * the new socket is unknown. conn->socket is marked as -1. */ newconn = netconn_alloc(conn->type, conn->callback); if (newconn == NULL) { return ERR_MEM; } newconn->pcb.tcp = newpcb; setup_tcp(newconn); newconn->err = err; if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) { /* When returning != ERR_OK, the connection is aborted in tcp_process(), so do nothing here! */ newconn->pcb.tcp = NULL; netconn_free(newconn); return ERR_MEM; } else { /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); } return ERR_OK; } #endif /* LWIP_TCP */ /** * Create a new pcb of a specific type. * Called from do_newconn(). * * @param msg the api_msg_msg describing the connection type * @return msg->conn->err, but the return value is currently ignored */ static err_t pcb_new(struct api_msg_msg *msg) { msg->conn->err = ERR_OK; LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); /* Allocate a PCB for this connection */ switch(NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: msg->conn->pcb.raw = raw_new(msg->msg.n.proto); if(msg->conn->pcb.raw == NULL) { msg->conn->err = ERR_MEM; break; } raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: msg->conn->pcb.udp = udp_new(); if(msg->conn->pcb.udp == NULL) { msg->conn->err = ERR_MEM; break; } #if LWIP_UDPLITE if (msg->conn->type==NETCONN_UDPLITE) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); } #endif /* LWIP_UDPLITE */ if (msg->conn->type==NETCONN_UDPNOCHKSUM) { udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); } udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; break; } setup_tcp(msg->conn); break; #endif /* LWIP_TCP */ default: /* Unsupported netconn type, e.g. protocol disabled */ msg->conn->err = ERR_VAL; break; } return msg->conn->err; }