Пример #1
0
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( );
}
Пример #2
0
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( );
}
Пример #3
0
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( );
}
Пример #4
0
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( );
}
Пример #5
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( );
}