wiced_result_t process_received_udp_packet() { wiced_packet_t* packet; char* rx_data; static uint16_t rx_data_length; uint16_t available_data_length; static wiced_ip_address_t udp_src_ip_addr; static uint16_t udp_src_port; wiced_result_t result = wiced_udp_receive( &udp_socket, &packet, RX_WAIT_TIMEOUT ); if ( ( result == WICED_ERROR ) || ( result == WICED_TIMEOUT ) ) { return result; } wiced_udp_packet_get_info( packet, &udp_src_ip_addr, &udp_src_port ); wiced_packet_get_data( packet, 0, (uint8_t**) &rx_data, &rx_data_length, &available_data_length ); uint32_t data_len = MIN(rx_data_length, BUFFER_SIZE-(48)); write_ws2812(0, data_len, rx_data); // WPRINT_APP_INFO ( ("UDP Rx: \"%.2x\" from IP %u.%u.%u.%u:%d\n", *rx_data, // (unsigned char) ( ( GET_IPV4_ADDRESS(udp_src_ip_addr) >> 24 ) & 0xff ), // (unsigned char) ( ( GET_IPV4_ADDRESS(udp_src_ip_addr) >> 16 ) & 0xff ), // (unsigned char) ( ( GET_IPV4_ADDRESS(udp_src_ip_addr) >> 8 ) & 0xff ), // (unsigned char) ( ( GET_IPV4_ADDRESS(udp_src_ip_addr) >> 0 ) & 0xff ), // udp_src_port ) ); wiced_packet_delete( packet ); return WICED_SUCCESS; }
sock_result_t socket_receivefrom(sock_handle_t sd, void* buffer, socklen_t bufLen, uint32_t flags, sockaddr_t* addr, socklen_t* addrsize) { socket_t* socket = from_handle(sd); volatile wiced_result_t result = WICED_INVALID_SOCKET; uint16_t read_len = 0; if (is_open(socket) && is_udp(socket)) { std::lock_guard<socket_t> lk(*socket); wiced_packet_t* packet = NULL; // UDP receive timeout changed to 0 sec so as not to block if ((result=wiced_udp_receive(udp(socket), &packet, WICED_NO_WAIT))==WICED_SUCCESS) { wiced_ip_address_t wiced_ip_addr; uint16_t port; if ((result=wiced_udp_packet_get_info(packet, &wiced_ip_addr, &port))==WICED_SUCCESS) { uint32_t ipv4 = GET_IPV4_ADDRESS(wiced_ip_addr); addr->sa_data[0] = (port>>8) & 0xFF; addr->sa_data[1] = port & 0xFF; addr->sa_data[2] = (ipv4 >> 24) & 0xFF; addr->sa_data[3] = (ipv4 >> 16) & 0xFF; addr->sa_data[4] = (ipv4 >> 8) & 0xFF; addr->sa_data[5] = ipv4 & 0xFF; result=read_packet(packet, (uint8_t*)buffer, bufLen, &read_len); }
/* * Function: wilddog_receive * Description: wilddog receive function, it use the interface in wiced platform. * Input: socketId: The socket id. * addr: The pointer of Wilddog_Address_T * buf: The pointer of the send buffer * bufLen: The length of the send buffer. * timeout: The max timeout in recv process. * Output: N/A * Return: If success, return the number of bytes received; else return -1. */ int wilddog_receive ( int socketId, Wilddog_Address_T* addr_in, void* buf, s32 bufLen, s32 timeout ) { wiced_udp_socket_t* socket = (wiced_udp_socket_t*) socketId; wiced_packet_t* receive = NULL; u16 totalLeft = 0; u16 total = 0; uint16_t pos = 0; uint8_t* rxData; uint16_t fragLeft = 0; wiced_ip_address_t recieve_ip_addr; uint16_t receive_port; wiced_result_t result; result = wiced_udp_receive( socket, &receive, timeout ); if ( result == WICED_SUCCESS ) { if(NULL == receive) { wilddog_debug_level(WD_DEBUG_ERROR, "receive is NULL!"); return -1; } wiced_udp_packet_get_info( receive, &recieve_ip_addr, &receive_port ); if ( !recieve_ip_addr.ip.v4 == MAKE_IPV4_ADDRESS(addr_in->ip[0], \ addr_in->ip[1], addr_in->ip[2], addr_in->ip[3]) ) { wilddog_debug_level(WD_DEBUG_ERROR, "addr error!\n" ); wiced_packet_delete( receive ); return -1; } do { if ( wiced_packet_get_data( receive, 0, (uint8_t**) &rxData, \ &fragLeft, &totalLeft ) != WICED_SUCCESS ) { wilddog_debug_level(WD_DEBUG_ERROR, \ "get data from packet error \r\n" ); wiced_packet_delete( receive ); return -1; } else { if ( pos + fragLeft > bufLen ) { /* too large, drop*/ wiced_packet_delete( receive ); wilddog_debug_level(WD_DEBUG_ERROR, \ "too large receive end , get %d bytes\n", pos ); return 0; } if ( total == 0 ) { /*only get first data, next fragment's total is wrong*/ total = totalLeft; } memcpy( (uint8_t *) ( buf + pos ), rxData, fragLeft ); pos += fragLeft; fragLeft = 0; } if ( pos == total ) { /*end*/ #if WILDDOG_SELFTEST { performtest_getWaitSessionQueryTime(); performtest_getWaitRecvTime(); } #endif wilddog_debug_level(WD_DEBUG_LOG, "received %d data!", pos); wiced_packet_delete( receive ); return pos; } else if ( pos < total ) { /*get next fragment*/ wilddog_debug_level(WD_DEBUG_LOG, "more than one packet!"); if ( WICED_SUCCESS != _packet_get_next_fragment( receive, \ &receive ) ) { wilddog_debug_level(WD_DEBUG_ERROR, \ "get next fragment err! %d lost!", total); if(receive) wiced_packet_delete( receive ); return -1; } if ( NULL == receive ) { wilddog_debug_level(WD_DEBUG_ERROR, \ "get next fragment err! %d lost!", total); return -1; } } else { wiced_packet_delete( receive ); return -1; } } while ( pos < total ); } else { wilddog_debug_level(WD_DEBUG_LOG, "result = %d",result); } /*if(receive) wiced_packet_delete( receive );*/ return 0; }
/** * Implements a very simple DHCP server. * * Server will always offer next available address to a DISCOVER command * Server will NAK any REQUEST command which is not requesting the next available address * Server will ACK any REQUEST command which is for the next available address, and then increment the next available address * * @param my_addr : local IP address for binding of server port. */ static void dhcp_thread( uint32_t thread_input ) { wiced_packet_t* received_packet; wiced_packet_t* transmit_packet; wiced_ip_address_t local_ip_address; wiced_ip_address_t netmask; uint32_t next_available_ip_addr; uint32_t ip_mask; uint32_t subnet; uint32_t netmask_htobe; char* option_ptr; wiced_dhcp_server_t* server = (wiced_dhcp_server_t*)thread_input; uint8_t subnet_mask_option_buff[] = { 1, 4, 0, 0, 0, 0 }; uint8_t server_ip_addr_option_buff[] = { 54, 4, 0, 0, 0, 0 }; uint32_t* server_ip_addr_ptr = (uint32_t*)&server_ip_addr_option_buff[2]; uint8_t wpad_option_buff[ 2 + sizeof(WPAD_SAMPLE_URL)-1 ] = { 252, sizeof(WPAD_SAMPLE_URL)-1 }; /* Save local IP address to be sent in DHCP packets */ wiced_ip_get_ipv4_address(server->interface, &local_ip_address); *server_ip_addr_ptr = htobe32( GET_IPV4_ADDRESS( local_ip_address ) ); /* Save the current netmask to be sent in DHCP packets as the 'subnet mask option' */ wiced_ip_get_netmask(server->interface, &netmask); netmask_htobe = htobe32( GET_IPV4_ADDRESS(netmask) ); memcpy(&subnet_mask_option_buff[2], &netmask_htobe, 4); /* Calculate the first available IP address which will be served - based on the netmask and the local IP */ ip_mask = ~( GET_IPV4_ADDRESS( netmask ) ); subnet = GET_IPV4_ADDRESS( local_ip_address ) & GET_IPV4_ADDRESS( netmask ); next_available_ip_addr = subnet | ( ( GET_IPV4_ADDRESS( local_ip_address ) + 1 ) & ip_mask ); /* Prepare the Web proxy auto discovery URL */ memcpy(&wpad_option_buff[2], WPAD_SAMPLE_URL, sizeof(WPAD_SAMPLE_URL)-1); ipv4_to_string( (char*)&wpad_option_buff[2 + 7], *server_ip_addr_ptr); /* Initialise the server quit flag */ server->quit = WICED_FALSE; /* Loop endlessly */ while ( server->quit == WICED_FALSE ) { uint16_t data_length; uint16_t available_data_length; dhcp_header_t* request_header; /* Sleep until data is received from socket. */ if ( wiced_udp_receive( &server->socket, &received_packet, WICED_WAIT_FOREVER ) != WICED_SUCCESS ) { continue; } /* Get a pointer to the data in the packet */ wiced_packet_get_data( received_packet, 0, (uint8_t**) &request_header, &data_length, &available_data_length ); /* Check DHCP command */ switch ( request_header->options[2] ) { case DHCPDISCOVER: { dhcp_header_t* reply_header; uint16_t available_space; wiced_mac_t client_mac_address; wiced_ip_address_t client_ip_address; uint32_t temp; /* Create reply packet */ if ( wiced_packet_create_udp( &server->socket, sizeof(dhcp_header_t), &transmit_packet, (uint8_t**) &reply_header, &available_space ) != WICED_SUCCESS ) { /* Cannot reply - release incoming packet */ wiced_packet_delete( received_packet ); break; } /* Copy in the DHCP header content from the received discover packet into the reply packet */ memcpy( reply_header, request_header, sizeof(dhcp_header_t) - sizeof(reply_header->options) ); /* Finished with the received discover packet - release it */ wiced_packet_delete( received_packet ); /* Now construct the OFFER response */ reply_header->opcode = BOOTP_OP_REPLY; /* Clear the DHCP options list */ memset( &reply_header->options, 0, sizeof( reply_header->options ) ); /* Record client MAC address */ memcpy( &client_mac_address, request_header->client_hardware_addr, sizeof( client_mac_address ) ); /* Check whether device is already cached */ if ( get_client_ip_address_from_cache( &client_mac_address, &client_ip_address ) != WICED_SUCCESS ) { /* Address not found in cache. Use next available IP address */ client_ip_address.version = WICED_IPV4; client_ip_address.ip.v4 = next_available_ip_addr; } /* Create the IP address for the Offer */ temp = htonl(client_ip_address.ip.v4); memcpy( reply_header->your_ip_addr, &temp, sizeof( temp ) ); /* Copy the magic DHCP number */ memcpy( reply_header->magic, dhcp_magic_cookie, 4 ); /* Add options */ option_ptr = (char *) &reply_header->options; option_ptr = MEMCAT( option_ptr, dhcp_offer_option_buff, 3 ); /* DHCP message type */ option_ptr = MEMCAT( option_ptr, server_ip_addr_option_buff, 6 ); /* Server identifier */ option_ptr = MEMCAT( option_ptr, lease_time_option_buff, 6 ); /* Lease Time */ option_ptr = MEMCAT( option_ptr, subnet_mask_option_buff, 6 ); /* Subnet Mask */ option_ptr = (char*)MEMCAT( option_ptr, wpad_option_buff, sizeof(wpad_option_buff) ); /* Web proxy auto discovery URL */ /* Copy the local IP into the Router & DNS server Options */ memcpy( option_ptr, server_ip_addr_option_buff, 6 ); /* Router (gateway) */ option_ptr[0] = 3; /* Router id */ option_ptr += 6; memcpy( option_ptr, server_ip_addr_option_buff, 6 ); /* DNS server */ option_ptr[0] = 6; /* DNS server id */ option_ptr += 6; option_ptr = MEMCAT( option_ptr, mtu_option_buff, 4 ); /* Interface MTU */ option_ptr[0] = (char) 0xff; /* end options */ option_ptr++; /* Send OFFER reply packet */ wiced_packet_set_data_end( transmit_packet, (uint8_t*) option_ptr ); if ( wiced_udp_send( &server->socket, WICED_IP_BROADCAST, IPPORT_DHCPC, transmit_packet ) != WICED_SUCCESS ) { wiced_packet_delete( transmit_packet ); } } break; case DHCPREQUEST: { /* REQUEST command - send back ACK or NAK */ uint32_t temp; uint32_t* server_id_req; dhcp_header_t* reply_header; uint16_t available_space; wiced_mac_t client_mac_address; wiced_ip_address_t given_ip_address; wiced_ip_address_t requested_ip_address; wiced_bool_t next_avail_ip_address_used = WICED_FALSE; /* Check that the REQUEST is for this server */ server_id_req = (uint32_t*) find_option( request_header, 54 ); if ( ( server_id_req != NULL ) && ( GET_IPV4_ADDRESS( local_ip_address ) != htobe32(*server_id_req) ) ) { break; /* Server ID does not match local IP address */ } /* Create reply packet */ if ( wiced_packet_create_udp( &server->socket, sizeof(dhcp_header_t), &transmit_packet, (uint8_t**) &reply_header, &available_space ) != WICED_SUCCESS ) { /* Cannot reply - release incoming packet */ wiced_packet_delete( received_packet ); break; } /* Copy in the DHCP header content from the received request packet into the reply packet */ memcpy( reply_header, request_header, sizeof(dhcp_header_t) - sizeof(reply_header->options) ); /* Record client MAC address */ memcpy( &client_mac_address, request_header->client_hardware_addr, sizeof( client_mac_address ) ); /* Locate the requested address in the options and keep requested address */ requested_ip_address.version = WICED_IPV4; requested_ip_address.ip.v4 = ntohl(*(uint32_t*)find_option( request_header, 50 )); /* Delete received packet. We don't need it anymore */ wiced_packet_delete( received_packet ); reply_header->opcode = BOOTP_OP_REPLY; /* Blank options list */ memset( &reply_header->options, 0, sizeof( reply_header->options ) ); /* Copy DHCP magic number into packet */ memcpy( reply_header->magic, dhcp_magic_cookie, 4 ); option_ptr = (char *) &reply_header->options; /* Check if device is cache. If it is, give the previous IP address. Otherwise give the next available IP address */ if ( get_client_ip_address_from_cache( &client_mac_address, &given_ip_address ) != WICED_SUCCESS ) { /* Address not found in cache. Use next available IP address */ next_avail_ip_address_used = WICED_TRUE; given_ip_address.version = WICED_IPV4; given_ip_address.ip.v4 = next_available_ip_addr; } /* Check if the requested IP address matches one we have assigned */ if ( memcmp( &requested_ip_address.ip.v4, &given_ip_address.ip.v4, sizeof( requested_ip_address.ip.v4 ) ) != 0 ) { /* Request is not for the assigned IP - force client to take next available IP by sending NAK */ /* Add appropriate options */ option_ptr = (char*)MEMCAT( option_ptr, dhcp_nak_option_buff, 3 ); /* DHCP message type */ option_ptr = (char*)MEMCAT( option_ptr, server_ip_addr_option_buff, 6 ); /* Server identifier */ memset( reply_header->your_ip_addr, 0, sizeof( reply_header->your_ip_addr ) ); /* Clear IP addr */ } else { /* Request is for next available IP */ /* Add appropriate options */ option_ptr = (char*)MEMCAT( option_ptr, dhcp_ack_option_buff, 3 ); /* DHCP message type */ option_ptr = (char*)MEMCAT( option_ptr, server_ip_addr_option_buff, 6 ); /* Server identifier */ option_ptr = (char*)MEMCAT( option_ptr, lease_time_option_buff, 6 ); /* Lease Time */ option_ptr = (char*)MEMCAT( option_ptr, subnet_mask_option_buff, 6 ); /* Subnet Mask */ option_ptr = (char*)MEMCAT( option_ptr, wpad_option_buff, sizeof(wpad_option_buff) ); /* Web proxy auto discovery URL */ /* Copy the local IP into the Router & DNS server Options */ memcpy( option_ptr, server_ip_addr_option_buff, 6 ); /* Router (gateway) */ option_ptr[0] = 3; /* Router id */ option_ptr += 6; memcpy( option_ptr, server_ip_addr_option_buff, 6 ); /* DNS server */ option_ptr[0] = 6; /* DNS server id */ option_ptr += 6; option_ptr = (char*)MEMCAT( option_ptr, mtu_option_buff, 4 ); /* Interface MTU */ /* Create the IP address for the Offer */ temp = htonl(given_ip_address.ip.v4); memcpy( reply_header->your_ip_addr, &temp, sizeof( temp ) ); /* Increment next available IP address only if not found in cache */ if ( next_avail_ip_address_used == WICED_TRUE ) { do { next_available_ip_addr = subnet | ( ( next_available_ip_addr + 1 ) & ip_mask ); } while ( next_available_ip_addr == GET_IPV4_ADDRESS(local_ip_address) ); } /* Cache client */ add_client_to_cache( &client_mac_address, &given_ip_address ); } option_ptr[0] = (char) 0xff; /* end options */ option_ptr++; /* Send reply packet */ wiced_packet_set_data_end( transmit_packet, (uint8_t*) option_ptr ); if ( wiced_udp_send( &server->socket, WICED_IP_BROADCAST, IPPORT_DHCPC, transmit_packet ) != WICED_SUCCESS ) { wiced_packet_delete( transmit_packet ); } } break; default: /* Unknown packet type - release received packet */ wiced_packet_delete( received_packet ); break; } } /* Server loop has exited due to quit flag */ /* Delete DHCP socket */ wiced_udp_delete_socket( &server->socket ); WICED_END_OF_CURRENT_THREAD( ); }