HTTP Connection stuck

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
agmi_3321141
Level 4
Level 4
5 likes given First like received First like given

Hello All!

I hope this is the right place to post this question.

I just got a kit and am trying to scan for BLE packets and send them to a local server on my computer. It's mostly working but my HTTP connection get stuck after a few BLE packets are scanned and sent. My current implementation has a console command tied to a callback function that scans for BLE packets and then opens a connection to the server set up on my laptop.

I haven't had much experience working with HTTP requests, but I have to re-open a connection every time I want to send a packet, since I get a HTTP_DISCONNECTED event after sending a packet. I don't know if this is how it is designed to work. Is there another way of implementing it?

I picked up the HTTP post request implementation from http://www.cypress.com/blog/technical/wiced-http-client and I added a BLE scan callback function to the ble_hello_sensor example in WICED IDE.

After all the packets are scanned, I think that the call http_client_connect is stuck, although it has a timeout, so I'm not sure what's happening there.

Connecting to 10.0.0.59

Connected

Disconnected from 10.0.0.59

device found!

Connecting to 10.0.0.59  <--- Never goes beyond this!

My ble_scan, packet sending code and event handler is like this:

static int hello_sensor_scan_ble( int argc, char *argv[] )

{

        WPRINT_BT_APP_INFO( ("************************\n") );

        WPRINT_BT_APP_INFO( ("Scanning for BLE devices\n") );

        WPRINT_BT_APP_INFO( ("************************\n") );

        // wiced_bt_ble_observe (WICED_TRUE, 2,(wiced_bt_ble_scan_result_cback_t *) hello_sensor_scan_ble_callback);

        wiced_bt_ble_scan(BTM_BLE_SCAN_TYPE_HIGH_DUTY, WICED_TRUE, (wiced_bt_ble_scan_result_cback_t *) hello_sensor_scan_ble_callback);

        return ERR_CMD_OK;

}

static void hello_sensor_scan_ble_callback(wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data)

{

    uint8_t                 adv_data_length;

    uint8_t                 *p_data = NULL;

    uint8_t                 LENGTH = 7;

    char*                   name = "abcdefg";

    switch (p_scan_result->ble_evt_type)

    {

        case BTM_BLE_EVT_CONNECTABLE_ADVERTISEMENT:

            /* Check the contents of the ADV - what's the name? */

            p_data = wiced_bt_ble_check_advertising_data( p_adv_data, BTM_BLE_ADVERT_TYPE_NAME_COMPLETE, &adv_data_length);

            if (adv_data_length != 0) {

                if (( memcmp( p_data, name, LENGTH ) == 0 )) {

                     WPRINT_BT_APP_INFO(("device found!\n"));

                     send_packet();

            }

           

            return;

        default:

            return;

       }

}

static void send_packet(void)

{

wiced_result_t result;

http_client_init( &client, WICED_STA_INTERFACE, event_handler, NULL );

WPRINT_APP_INFO( ( "Connecting to %s\n", SERVER_HOST ) );

/* configure HTTP client parameters */

client_configuration.flag = (http_client_configuration_flags_t)(HTTP_CLIENT_CONFIG_FLAG_SERVER_NAME | HTTP_CLIENT_CONFIG_FLAG_MAX_FRAGMENT_LEN);

client_configuration.server_name = (uint8_t*) SERVER_HOST;

client_configuration.max_fragment_length = TLS_FRAGMENT_LENGTH_1024;

http_client_configure(&client, &client_configuration);

/* if you set hostname, library will make sure subject name in the server certificate is matching with host name you are trying to connect. pass NULL if you don't want to enable this check */

client.peer_cn = (uint8_t*) SERVER_HOST;

if ( ( result = http_client_connect( &client, (const wiced_ip_address_t*)&ip_address, SERVER_PORT, HTTP_NO_SECURITY, CONNECT_TIMEOUT_MS ) ) != WICED_SUCCESS )

{

    WPRINT_APP_INFO( ( "Error: failed to connect to server: %u\n", result) );

    return;

}

WPRINT_APP_INFO( ( "Connected\n" ) );

http_header_field_t header[3];

char messageBody[128];        // Enough to hold the message body

char messageLengthBuffer[10]; // Enough to hold the characters for the Content-Length: header

char *receiverAddress = "192.168.1.255";

char *rssi = "1";

char *senderAddress = "192.168.1.255";

sprintf(messageBody,"&receiverAddress=%s&rssi=%s&senderAddress=%s", receiverAddress, rssi, senderAddress);

header[0].field        = HTTP_HEADER_HOST;

header[0].field_length = sizeof( HTTP_HEADER_HOST ) - 1;

header[0].value        = SERVER_HOST;

header[0].value_length = sizeof( SERVER_HOST ) - 1;

#define MIME_FORM_URL "application/x-www-form-urlencoded"

header[1].field        = HTTP_HEADER_CONTENT_TYPE;

header[1].field_length = sizeof( HTTP_HEADER_CONTENT_TYPE ) - 1;

header[1].value        =  MIME_FORM_URL;

header[1].value_length = sizeof(  MIME_FORM_URL ) - 1;

sprintf(messageLengthBuffer," %d",strlen(messageBody)); // Put the message body into the buffer so that you can strlen it

header[2].field        = HTTP_HEADER_CONTENT_LENGTH;

header[2].field_length = sizeof( HTTP_HEADER_CONTENT_LENGTH ) - 1;

header[2].value        =  messageLengthBuffer;

header[2].value_length = strlen(messageLengthBuffer);

http_request_init( &requests[0], &client, HTTP_POST, request_uris[2], HTTP_1_1 );

http_request_write_header( &requests[0], &header[0], 3 );

http_request_write_end_header( &requests[0] );

http_request_write( &requests[0], (uint8_t*)messageBody, strlen(messageBody) );

result = http_request_flush( &requests[0] );

if ( result != WICED_SUCCESS )

{

    WPRINT_APP_INFO( (" POST request flush failed\n") );

}

else

{

    result = wiced_rtos_get_semaphore(&requestSemaphore,10000);

    if ( result != WICED_SUCCESS )

        WPRINT_APP_INFO( (" POST request timed out \n") );

    else

    {

        WPRINT_APP_INFO( ("\nPOST successful\n") );

    }

}

http_request_deinit( &requests[0] );

http_client_disconnect( &client );

}

static void event_handler( http_client_t* client, http_event_t event, http_response_t* response )

{

    switch( event )

    {

        case HTTP_CONNECTED:

            WPRINT_APP_INFO(( "Connected to %s\n", SERVER_HOST ));

            break;

        case HTTP_DISCONNECTED:

        {

            WPRINT_APP_INFO(( "Disconnected from %s\n", SERVER_HOST ));

            break;

        }

        case HTTP_DATA_RECEIVED:

        {  

             wiced_rtos_set_semaphore(&requestSemaphore);

           

        break;

        }

        default:

        break;

    }

}

}

}

Thanks!

0 Likes
1 Solution

The code looks fine. You can use mallinfo() to check the memory consumed by each function call and then adjust the stack size accordingly. http_client_init() should be called once or http_client_deinit() should be called before initialising the HTTP client again. Regarding the disconnection issue, check if you could see Connection: close in the HTTP response header. This means that the server would close the connection after completing the request.

View solution in original post

4 Replies
GauravS_31
Moderator
Moderator
Moderator
10 questions asked 250 solutions authored 250 sign-ins

1. You are receiving the HTTP_DISCONNECTED event because the function http_client_disconnect( &client ) is called at the end of HTTP POST request. You need not use this function. In our example snip.httpbin_org, we could send two HTTP GET requests in sequence without using the disconnect API.

2. Please avoid using big function calls such as send_packet() inside callback functions. You can either create a separate RTOS thread with appropriate stack memory to send this packet or use a flag variable in the callback function and check this flag in another thread to call send_packet().

Hi grsr​,

Thanks for the advice.

1. I added the http_client_disconnect(&client) line as I thought it was causing the connection to get stuck. Even after commenting out that call, I still see the print "Disconnected from <SERVER_HOST>". Hence my confusion.

2. I was thinking along those lines, so I created a thread that can send messages. This thread pops from a queue that the ble scan function pushes content to. Popped data is then sent via HTTP. Even after this, I observe that after typing my console command multiple times, the connection can get stuck at the same point(Connecting to <ip-address>). Here is my thread:

static void http_send_thread( uint32_t arg )

{

    wiced_result_t result;

    WPRINT_APP_INFO (( "Started httpservice_thread\n" ));

    do

    {

        /*wait for network up*/

        wiced_rtos_delay_milliseconds( 100 );

    } while ( wiced_network_is_ip_up( WICED_STA_INTERFACE ) != WICED_TRUE );

while ( 1 )

    {

        /* check for network link */

        if ( wiced_network_is_ip_up( WICED_STA_INTERFACE ) != WICED_TRUE )

        {

            wiced_rtos_delay_milliseconds( 100 );

            continue;

        }

        WPRINT_APP_DEBUG (("httpservice_thread: Waiting for event \n"));

        uint8_t body[16];

        result = wiced_rtos_pop_from_queue( &http_queue, body, WICED_NEVER_TIMEOUT );

        WPRINT_APP_DEBUG (("httpservice_thread: pop %d \n",result));

        if ( result != WICED_SUCCESS )

        {

            WPRINT_APP_INFO( ("Error in popping\n") );

            continue;

        } else {

            WPRINT_APP_INFO( ("Sucess popping\n") );

        }

        send_packet(body);

    }

}

The queue size is 8 and stack size for the thread is 6 * 1024.

Is there something I can improve upon in this thread function?

0 Likes

I think what was killing the connection was the call:

http_client_init( &client, WICED_STA_INTERFACE, event_handler, NULL );

This should probably be done just once.

0 Likes

The code looks fine. You can use mallinfo() to check the memory consumed by each function call and then adjust the stack size accordingly. http_client_init() should be called once or http_client_deinit() should be called before initialising the HTTP client again. Regarding the disconnection issue, check if you could see Connection: close in the HTTP response header. This means that the server would close the connection after completing the request.