void system_monitor_thread_main( wiced_thread_arg_t arg ) { UNUSED_PARAMETER(arg); memset(system_monitors, 0, sizeof(system_monitors)); if (wiced_rtos_init_semaphore(&system_monitor_thread_semaphore) != WICED_SUCCESS) { wiced_assert("semaphore init failed", 0); } /* - Can watch threads * Each thread can set a counter that is decremented every event. * Once any timer == 0, the watchdog is no longer kicked * * - Can watch packet buffer status * If no RX packets are available, take timestamp (T). If (current time - T) > X seconds, stop kicking watchdog. * X can be 10 second default. Time will be set to zero once RX buffer is freed * * - Can watch bus data credits * If no credits are available, take timestamp (B). If (current time - B) > X seconds, stop kicking watchdog. * This will be dependent on if WLAN is up. Timer will be set to 0 if credits become available. */ while (1) { int a; uint32_t current_time = host_rtos_get_time(); for (a = 0; a < MAXIMUM_NUMBER_OF_SYSTEM_MONITORS; ++a) { if (system_monitors[a] != NULL) { if ((current_time - system_monitors[a]->last_update) > system_monitors[a]->longest_permitted_delay) { /* A system monitor update period has been missed and hence explicitly resetting the MCU rather than waiting for the watchdog to bite */ wiced_framework_reboot(); } } } wiced_watchdog_kick(); wiced_rtos_get_semaphore(&system_monitor_thread_semaphore, DEFAULT_SYSTEM_MONITOR_PERIOD); } /* Should never get here */ wiced_rtos_deinit_semaphore(&system_monitor_thread_semaphore); WICED_END_OF_CURRENT_THREAD( ); }
static void tcp_server_thread_main(uint32_t arg) { tcp_server_handle_t* server = (tcp_server_handle_t*) arg; while ( quit != WICED_TRUE ) { wiced_packet_t* temp_packet = NULL; /* Wait for a connection */ wiced_result_t result = wiced_tcp_accept( &server->socket ); #ifdef TCP_KEEPALIVE_ENABLED result = wiced_tcp_enable_keepalive(&server->socket, TCP_SERVER_KEEP_ALIVE_INTERVAL, TCP_SERVER_KEEP_ALIVE_PROBES, TCP_SERVER_KEEP_ALIVE_TIME ); if( result != WICED_SUCCESS ) { WPRINT_APP_INFO(("Keep alive initialization failed \n")); } #endif /* TCP_KEEPALIVE_ENABLED */ if ( result == WICED_SUCCESS ) { /* Receive the query from the TCP client */ if (wiced_tcp_receive( &server->socket, &temp_packet, WICED_WAIT_FOREVER ) == WICED_SUCCESS) { /* Process the client request */ tcp_server_process( server, temp_packet ); /* Delete the packet, we're done with it */ wiced_packet_delete( temp_packet ); #ifdef TCP_KEEPALIVE_ENABLED WPRINT_APP_INFO(("Waiting for data on a socket\n")); /* Check keepalive: wait to see whether the keepalive protocol has commenced */ /* This is achieved by waiting forever for a packet to be received on the TCP connection*/ if (wiced_tcp_receive( &server->socket, &temp_packet, WICED_WAIT_FOREVER ) == WICED_SUCCESS) { tcp_server_process( server, temp_packet ); /* Release the packet, we don't need it any more */ wiced_packet_delete( temp_packet ); } else { WPRINT_APP_INFO(("Connection has been dropped by networking stack\n\n")); } #endif /* TCP_KEEPALIVE_ENABLED */ } else { /* Send failed or connection has been lost, close the existing connection and */ /* get ready to accept the next one */ wiced_tcp_disconnect( &server->socket ); } } } WPRINT_APP_INFO(("Disconnect\n")); wiced_tcp_disconnect( &server->socket ); WICED_END_OF_CURRENT_THREAD( ); }
static void p2p_thread_main( uint32_t arg ) { p2p_workspace_t* workspace = (p2p_workspace_t*)arg; wwd_result_t result; p2p_message_t message; uint8_t last_printed_discovered_device = 0; BESL_INFO(("P2P discovery enabled. Advertised as '%s'\n", workspace->p2p_name)); workspace->p2p_result = BESL_IN_PROGRESS; while ( workspace->p2p_current_state != P2P_STATE_COMPLETE && workspace->p2p_current_state != P2P_STATE_ABORTED ) { host_rtos_pop_from_queue(&p2p_message_queue, &message, WICED_NEVER_TIMEOUT); switch(message.type) { case P2P_EVENT_SCAN_COMPLETE: p2p_discover(workspace); break; case P2P_EVENT_DISCOVERY_COMPLETE: if ( workspace->p2p_current_state == P2P_STATE_NEGOTIATING ) { p2p_discover(workspace); break; } /* Otherwise fall through */ case P2P_EVENT_START_REQUESTED: if (workspace->p2p_current_state != P2P_STATE_NEGOTIATING) { workspace->p2p_current_state = P2P_STATE_SCANNING; } result = p2p_set_discovery_state( P2P_DISCOVERY_STATE_SEARCH ); result = p2p_scan( ); break; case P2P_EVENT_PACKET_TO_BE_SENT: result = wwd_sdpcm_send_iovar( SDPCM_SET, (wiced_buffer_t) message.data, NULL, WICED_STA_INTERFACE ); if (result != WWD_SUCCESS) { /* Packet has been lost.. Maybe. Don't think we can recover it though */ } break; case P2P_EVENT_NEGOTIATION_COMPLETE: BESL_INFO( ("P2P negotiation complete...\n") ); workspace->p2p_current_state = P2P_STATE_COMPLETE; break; case P2P_EVENT_STOP_REQUESTED: workspace->p2p_current_state = P2P_STATE_ABORTED; break; case P2P_EVENT_NEW_DEVICE_DISCOVERED: printf( "Found P2P device: %s\r\n", workspace->discovered_devices[last_printed_discovered_device].device_name); ++last_printed_discovered_device; break; default: break; } } /* Remove P2P event handler */ result = wwd_management_set_event_handler( p2p_events, NULL, workspace, workspace->p2p_interface ); wiced_assert("", result == WWD_SUCCESS); /* Remove the unused WPS and P2P IEs */ wps_host_remove_vendor_ie( workspace->p2p_interface, workspace->wps_probe_ie, workspace->wps_probe_ie_length, VENDOR_IE_PROBE_REQUEST ); wps_host_remove_vendor_ie( workspace->p2p_interface, workspace->wps_probe_ie, workspace->wps_probe_ie_length, VENDOR_IE_PROBE_RESPONSE ); p2p_host_remove_vendor_ie( workspace->p2p_interface, workspace->p2p_probe_request_ie, workspace->p2p_probe_request_ie_length, VENDOR_IE_PROBE_REQUEST); p2p_host_remove_vendor_ie( workspace->p2p_interface, workspace->p2p_probe_response_ie, workspace->p2p_probe_response_ie_length, VENDOR_IE_PROBE_RESPONSE); wiced_buffer_t buffer; uint32_t* data; /* Bring down the P2P interface */ data = wwd_sdpcm_get_iovar_buffer(&buffer, sizeof(wiced_mac_t), IOVAR_STR_P2P_IFDEL ); memcpy(data, &workspace->device_info.mac_address, sizeof(wiced_mac_t)); result = wwd_sdpcm_send_iovar(SDPCM_SET, buffer, NULL, WICED_STA_INTERFACE); wiced_assert("", result == WWD_SUCCESS); if (workspace->p2p_current_state == P2P_STATE_COMPLETE) { wps_agent_t* wps_agent = besl_host_malloc( "p2p", sizeof(wps_agent_t) ); if ( wps_agent == NULL ) { goto return_with_error; } memset( wps_agent, 0, sizeof(wps_agent_t) ); if ( workspace->i_am_group_owner == 0 ) { p2p_run_as_client( workspace, wps_agent ); } else { p2p_run_as_go( workspace, wps_agent ); } besl_host_free(wps_agent); } return_with_error: WICED_END_OF_CURRENT_THREAD( ); }
static void ota_server_thread_main(uint32_t arg) { ota_server_t* server = (ota_server_t*) arg; uint32_t total_body_size = 0; int i = 0; server->reboot_required = WICED_FALSE; while ( server->quit != WICED_TRUE ) { wiced_packet_t* temp_packet = NULL; /* Wait for a connection */ wiced_result_t result = wiced_tcp_accept( &server->socket ); if ( result == WICED_SUCCESS ) { for(;;) { if ( wiced_tcp_receive( &server->socket, &temp_packet, WICED_WAIT_FOREVER ) == WICED_SUCCESS ) { char* request_string; uint16_t request_length; uint16_t available_data_length; if( server->state == READING_HEADER ) { uint8_t temp = 0; wiced_result_t result = WICED_ERROR; if ( temp_packet == NULL ) { goto disconnect; } init_request(server); server->request.request_packets[server->request.current_packet_index] = temp_packet; wiced_packet_get_data(temp_packet, 0, (uint8_t**)&request_string, &request_length, &available_data_length); /* Check that this is a GET or POST request, abort everything else */ if ( ( strstr( request_string, "GET" ) == 0 ) && ( strstr( request_string, "POST") == 0 ) ) { result = WICED_ERROR; wiced_packet_delete(temp_packet); goto disconnect; } /* Get header pointer and header size */ server->request.header_ptr = (uint8_t*)request_string; server->request.header_size = ( (char*)strstr( (char*)request_string, crlfcrlf ) + strlen( crlfcrlf ) ) - (char*)request_string; if( server->request.header_size == strlen( crlfcrlf ) ) { goto disconnect; } /* Get content length */ server->request.content_length = 0; if( strstr( request_string, "Content-Length") != NULL ) { uint8_t* content_length_value = (uint8_t*)strstr( request_string, "Content-Length") + strlen("Content-Length:"); server->request.content_length = atoi((const char*)content_length_value); } temp = request_string[ server->request.header_size ]; request_string[ server->request.header_size ] ='\0'; request_string[ server->request.header_size ] = temp; /* Get request type and the url */ result = get_http_request_type_and_url( (uint8_t*)request_string, request_length, &server->request); if ( result == WICED_ERROR ) { goto disconnect; } server->state = READING_BODY; } if( server->state == READING_BODY ) { http_body_chunk_t* current_body_chunk = &server->request.body_chunks[server->request.current_packet_index]; if( server->request.current_packet_index != 0 ) { server->request.request_packets[server->request.current_packet_index] = temp_packet; } wiced_packet_get_data(temp_packet, 0, (uint8_t**)&request_string, &request_length, &available_data_length); if( server->request.current_packet_index == 0 ) { current_body_chunk->data = server->request.header_ptr + server->request.header_size; current_body_chunk->size = ( request_string + request_length ) - (char*)current_body_chunk->data; } else { current_body_chunk->data = (uint8_t*)request_string; current_body_chunk->size = request_length; } /* calculate total combined size of all body chunks which belongs to this message */ total_body_size = 0; for( i = 0; i < ( server->request.current_packet_index + 1 ) ; i++ ) { total_body_size+= server->request.body_chunks[i].size; } server->request.current_packet_index++; /* Check whether the combined size of the previous chunks and the current one is equal to the content length received in the first packet */ if( total_body_size == server->request.content_length ) { ota_server_process_request( server, &server->socket ); /* Delete all packets belonging to the message */ for( i = 0; i < server->request.current_packet_index; i++ ) { wiced_packet_delete(server->request.request_packets[i]); } server->state = READING_HEADER; break; } } } else { goto disconnect; } } } disconnect: wiced_tcp_disconnect( &server->socket ); } wiced_tcp_delete_socket( &server->socket ); if( server->reboot_required == WICED_TRUE ) { /* Give some for the response to be sent properly */ wiced_rtos_delay_milliseconds(2000); /* Perform a reboot!!! */ wiced_framework_reboot(); } WICED_END_OF_CURRENT_THREAD( ); }
/** * 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( ); }