1 Reply Latest reply on May 17, 2018 2:31 AM by grsr

    multiple requests timeout with http client

    vmore_3321141

      Hello!

       

      I am using the HTTP client library to make 3 different requests. One request is posted continuously. The second and third is sent every minute sequentially (through flags), like: 0 -> 1 -> 2. The same connection sends different requests.

      I use the keep alive header to keep the connection open. Due to some configurations on the sever, I get disconnected roughly every minute so I use a flag to call the http_client_disconnect() and http_request_deinit() APIs and I'm back in business. However I have noticed that sometimes, after a while say 30-40minutes (this is just an estimate) later my requests start bombing. I start getting semaphore timeouts on all of them and things never recover. I am not entirely sure how to debug this problem. I'm not sure if it is related to how I re-initialize my requests. What is the right way to re-initialize the request/connection after getting a disconnect callback? Such a callback might be received while processing any of the 3 requests. My 2nd request is a housekeeping request that is a long json and the 3rd is a http bulk request which can get huge if my queue size gets bigger, so they have a higher semaphore timeout.

      I have provided a snippet of what I'm trying, hope someone can give me some hints to debug this!

       

       

       

      // 1 min timer
      static void housekeeping_callback(void *arg)
      {
          send_packet_type = 1;
      }
      
      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;
              }
      
              switch (send_packet_type) {
                  case 0:
                  {
                      wiced_rtos_pop_from_queue( &whttp_queue, &pop, WICED_NEVER_TIMEOUT );
                      send_packet();
                  }
                  break;
      
                  case 1:
                      send_housekeeping_packet();
                      send_packet_type = 2;
                  break;
                  case 2:
                  {
                      int count = get_queue_size();
                      char *bulk_packet = (char *)malloc(sizeof ( (count) * sizeof(buffer) ) );
                      for (int i = 0; i < count; i++) {
                          wiced_rtos_pop_from_queue( &whttp_queue, &pop, 200 );
                      }
      
                      send_bulk_packet();
      
                      free(bulk_packet);
      
                      send_packet_type = 0;
                  }
                  break;
                  default:
                  break;
              }
          }
      }
      
      // requests 1 and 2 follow same pattern!
      // static void send_housekeeping_packet()
      // static void send_bulk_packet()
      static void send_packet()
      {
          wiced_result_t result;
      
              if (got_disconnected) {
                  http_request_deinit( &requests[0] );
                  http_client_disconnect( &client );
                  wiced_rtos_delay_milliseconds( 50 );
                  got_disconnected = WICED_FALSE;
              }
      
          if ( wiced_network_is_ip_up( WICED_STA_INTERFACE ) == WICED_TRUE && is_connected_http == WICED_FALSE) {
              // 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);
      
          WPRINT_APP_DEBUG( ( "Connecting to %s\n", SERVER_HOST ) );
      
          // 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;
              } else {
                  is_connected_http = WICED_TRUE;
              }
          }
      
          WPRINT_APP_DEBUG( ( "Connected\n" ) );
      
          jsonize_packet(send_packet_buffer);
      
          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 JSON_URL "application/json"
          header[1].field        = HTTP_HEADER_CONTENT_TYPE;
          header[1].field_length = sizeof( HTTP_HEADER_CONTENT_TYPE ) - 1;
          header[1].value        = JSON_URL;
          header[1].value_length = sizeof( JSON_URL ) - 1;
      
          #define CONNECTION "Keep-Alive"
          header[3].field        = HTTP_HEADER_CONNECTION;
          header[3].field_length = sizeof( HTTP_HEADER_CONNECTION ) - 1;
          header[3].value        = CONNECTION;
          header[3].value_length = sizeof(CONNECTION) - 1;
      
          char messageLengthBuffer[10]; // Enough to hold the characters for the Content-Length: header
          sprintf(messageLengthBuffer," %d",strlen(send_packet_buffer)); // 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);
      
          wiced_time_get_time(&start_send_time);
      
          http_request_init( &requests[0], &client, HTTP_POST, request_uris[0], HTTP_1_1 );
          http_request_write_header( &requests[0], &header[0], 4 );
          http_request_write_end_header( &requests[0] );
          http_request_write( &requests[0], (uint8_t*)send_packet_buffer, strlen(send_packet_buffer) );
          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,7000);
      
              if ( result != WICED_SUCCESS )
                  WPRINT_APP_DEBUG( (" POST request timed out \n") );
              else
              {
                  WPRINT_APP_DEBUG( ("\nPOST successful\n") );
              }
          }
      }
      
      
      static void event_handler( http_client_t* client, http_event_t event, http_response_t* response )
      {
          switch( event )
          {
              case HTTP_CONNECTED:
                  break;
      
              case HTTP_DISCONNECTED:
              {
                  got_disconnected = WICED_TRUE;
                  is_connected_http = WICED_FALSE;
                  break;
              }
      
              case HTTP_DATA_RECEIVED:
              {
                  // set semaphore
                  wiced_rtos_set_semaphore(&requestSemaphore);
              break;
              }
              default:
              break;
          }
      }