I have an application which uses Wininet on the main thread to make both sync and async calls. A single root internet handle is opened with flag - INTERNET_FLAG_ASYNC
. This handle is used for all calls.To implement sync network calls, we simply wait in an infinite while loop until the request completes. Intermittently we see that we do not get any response from the Wininet.
Some code snippets/pseudo code below which show what we are trying to do.
// struct Context{
bool resultReady;
}
// Callback function registered with Wininet to know about the progress of ongoing call
static void CALLBACK StatusCallBack (
IN HINTERNET hInternet,
IN DWORD_PTR dwContext,
IN DWORD dwInternetStatus,
IN LPVOID lpvStatusInformation OPTIONAL,
IN DWORD dwStatusInformationLength )
{
Context* cxt = (Context *)dwContext;
switch (dwInternetStatus) {
// other cases ...
case INTERNET_STATUS_REQUEST_COMPLETE :
cxt->resultReady = true; break;
}
}
// Open root internet handle
HINTERNET root_hnd = InternetOpenA(agentname, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
// Set status callback
InternetSetStatusCallback(root_hnd, StatusCallBack );
// Open connect handle
Context connect_cxt = {};
HINTERNET connect_hnd = InternetConnectA(root_hnd, hostname, NULL, NULL, INTERNET_SERVICE_HTTP, 0, &connect_cxt);
// Open HTTP request handle
Context http_cxt= {};
DWORD flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
HINTERNET http_hnd = HttpOpenRequestA(connect_hnd, verb, objectname, HTTP_VERSIONA, NULL, NULL, flags, &http_cxt);
HttpSendRequestA(file, NULL, 0, additionalOptions, optionsLen);
while(http_cxt.resultReady == false) {
Sleep(10);
}
This is only a snippet of what we are doing. We have error handling at each step and synchronization mechanism also in place. For making calls to same hostname, we reuse the internet connect handle as well, but open a new http request handle everytime.
Upon debugging, we found that if multiple async calls are in place to the same server, Wininet queues up the calls and doesn't actually send the request unless the previous ones are finished : http://webdebug.net/2013/01/wininet-connection-limit/
We fixed this issue by increasing allowed connection limit, and failing calls at initiation itself in case limit still exceeded. However, we are still seeing the same symptoms sometimes even in cases when only a single async call is made to a server (in parallel other calls might be in progress to other servers). Once, we do a send request, we do not get any response at all in our registered callback function.
I want to know if Wininet needs the thread on which the handles are opened to be freed up in order for it to send us something in progress callbacks ? Also, is there any other connection limit which we might be missing ?