none
WinHttpSendRequest ends with 12002 (ERROR_HTTP_TIMEOUT) after 21 seconds no matter what timeout options are set

    General discussion

  • Hi,

    I'm trying to configure the the client side WinHTTP connect/send/receive timeout on Windows 7/2008. However they don't seem to take effect.

    Instead WinHttpSendRequest comes back with 12002 always after 21 seconds when trying with a fake IP as destination (not sure how else to simulate).

    It may worth mentioning that I tried both by using WinHttpSetTimeouts and by setting each option individually with WinHttpSetOption with no difference.

    The results of my quick test look like this:

    WinHttpUsageExample.exe "10.20.30.40" 50 (timeout in secs)

    default WINHTTP_OPTION_RESOLVE_TIMEOUT: -1
    default WINHTTP_OPTION_CONNECT_TIMEOUT: 60000
    default WINHTTP_OPTION_SEND_TIMEOUT: 30000
    default WINHTTP_OPTION_RECEIVE_TIMEOUT: 30000
    -------------------------------------------------------------------------------
    current WINHTTP_OPTION_RESOLVE_TIMEOUT: 50000
    current WINHTTP_OPTION_CONNECT_TIMEOUT: 50000
    current WINHTTP_OPTION_SEND_TIMEOUT: 50000
    current WINHTTP_OPTION_RECEIVE_TIMEOUT: 50000
    -------------------------------------------------------------------------------
    Before WinHttpSendRequest time is 16:36:28
    After WinHttpSendRequest time is 16:36:49, errno: 12002
    Error 12002 has occurred.

    Could this be a WinHTTP bug?

    Am I not simulating correctly? How to then?

    Could it be in this case that the ERROR_WINHTTP_TIMEOUT is returned as result of lower tcp level timeout(s) expiration (not mentioned in WinHTTP doc)?

    Pretty much in the dark here. Any help would be highly appreciated.

    Cheers,
    Bogdan


    Also, in case one may be curious, here's the source of my small test program:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <windows.h>
    #include <winhttp.h>
    #include <time.h>

    static wchar_t* charToWChar(const char* text)
    {
        size_t size = strlen(text) + 1;
        wchar_t* wa = new wchar_t[size];
        mbstowcs(wa,text,size);
        return wa;
    }

    int main(int argc, char* argv[])
    {
      DWORD dwSize = 0;
      DWORD dwDownloaded = 0;
      LPSTR pszOutBuffer;
      BOOL  bResults = FALSE;
      HINTERNET  hSession = NULL,
                 hConnect = NULL,
                 hRequest = NULL;

      DWORD timeoutval = 0;
      DWORD size = sizeof(DWORD);
      wchar_t *httpserver = NULL;  
      char timeStr [9];    

      if(argc < 3)
      {
              printf( "usage: WinHttpUsageExample.exe <http server name/address> <winhttp global timeout in seconds>\n");
              return 0;
      }

      // Use WinHttpOpen to obtain a session handle.
      hSession = WinHttpOpen( L"WinHTTP Example/1.0",  
                              WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                              WINHTTP_NO_PROXY_NAME,
                              WINHTTP_NO_PROXY_BYPASS, 0 );

      WinHttpQueryOption(hSession, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeoutval, &size);

      printf("default WINHTTP_OPTION_RESOLVE_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hSession, WINHTTP_OPTION_CONNECT_TIMEOUT, &timeoutval, &size);

      printf("default WINHTTP_OPTION_CONNECT_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hSession, WINHTTP_OPTION_SEND_TIMEOUT, &timeoutval, &size);

      printf("default WINHTTP_OPTION_SEND_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hSession, WINHTTP_OPTION_RECEIVE_TIMEOUT, &timeoutval, &size);

      printf("default WINHTTP_OPTION_RECEIVE_TIMEOUT: %d\n", timeoutval);

      printf( "-------------------------------------------------------------------------------\n");

      timeoutval = atol(argv[2]) * 1000; //convert seconds to milliseconds
      httpserver = charToWChar( argv[1] ); // convert the string type

      /* Use WinHttpSetTimeouts to set a new time-out values (resolve, connect, send, receive) */
      if (!WinHttpSetTimeouts( hSession, timeoutval, timeoutval, timeoutval, timeoutval))
      {
           printf("Error %u in WinHttpSetTimeouts.\n", GetLastError());
      }

      // Specify an HTTP server.
      if( hSession )
        hConnect = WinHttpConnect( hSession, httpserver,
                                   INTERNET_DEFAULT_HTTPS_PORT, 0 );

      // Create an HTTP request handle.
      if( hConnect )
        hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
                                       NULL, WINHTTP_NO_REFERER,
                                       WINHTTP_DEFAULT_ACCEPT_TYPES,
                                       WINHTTP_FLAG_SECURE );

      WinHttpQueryOption(hRequest, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeoutval, &size);

      printf("current WINHTTP_OPTION_RESOLVE_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hRequest, WINHTTP_OPTION_CONNECT_TIMEOUT, &timeoutval, &size);

      printf("current WINHTTP_OPTION_CONNECT_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hRequest, WINHTTP_OPTION_SEND_TIMEOUT, &timeoutval, &size);

      printf("current WINHTTP_OPTION_SEND_TIMEOUT: %d\n", timeoutval);

      WinHttpQueryOption(hRequest, WINHTTP_OPTION_RECEIVE_TIMEOUT, &timeoutval, &size);

      printf("current WINHTTP_OPTION_RECEIVE_TIMEOUT: %d\n", timeoutval);  

      printf( "-------------------------------------------------------------------------------\n");

      _strtime_s( timeStr );
      printf( "Before WinHttpSendRequest time is %s \n", timeStr);  

      // Send a request.
      if( hRequest )
      {
              bResults = WinHttpSendRequest( hRequest,
                                       WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                       WINHTTP_NO_REQUEST_DATA, 0,
                                       0, 0 );
              _strtime_s( timeStr );
              printf( "After WinHttpSendRequest time is %s, errno: %d \n", timeStr, GetLastError( ));
      }
     
      // Receive response
      if( bResults )
      {
            bResults = WinHttpReceiveResponse( hRequest, NULL );
            _strtime_s( timeStr );
            printf( "Afer WinHttpReceiveResponse time is %s, errno: %d \n", timeStr, GetLastError( ));
      }


      // Keep checking for data until there is nothing left.
      if( bResults )
      {
        do
        {
          // Check for available data.
          dwSize = 0;
          if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
            printf( "Error %u in WinHttpQueryDataAvailable.\n",
                    GetLastError( ) );

          // Allocate space for the buffer.
          pszOutBuffer = new char[dwSize+1];
          if( !pszOutBuffer )
          {
            printf( "Out of memory\n" );
            dwSize=0;
          }
          else
          {
            // Read the data.
            ZeroMemory( pszOutBuffer, dwSize+1 );

            if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer,
                                  dwSize, &dwDownloaded ) )
              printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
            else
              printf( "%s", pszOutBuffer );

            // Free the memory allocated to the buffer.
            delete [] pszOutBuffer;
          }
        } while( dwSize > 0 );
      }
     
      // Report any errors.
      if( !bResults )
        printf( "Error %d has occurred.\n", GetLastError( ) );

      // Close any open handles.
      if( hRequest ) WinHttpCloseHandle( hRequest );
      if( hConnect ) WinHttpCloseHandle( hConnect );
      if( hSession ) WinHttpCloseHandle( hSession );
     
      return 0;
    }
    Wednesday, April 23, 2014 10:00 AM

All replies

  • In order to simulate the required timeout, try this workaround: after receiving an early timeout error, subtract the elapsed period from timeout, set the new timeout, and then repeat the operation in a loop.

    Thursday, April 24, 2014 6:22 AM
  • Appreciate your suggestion Viorel, however that workaround applies for the case when the MS configurable timeouts don't work - i. e. an issue with winhttp library, which is what I'm trying to clarify. Is this a known bug? I couldn't find any related info elsewhere.

    Thursday, April 24, 2014 10:29 AM