URL::createInputStream suffers from wininet API bug


#1

Hi Jules,

I’ve encountered a problem with the ‘connectionTimeOutMs’ param of the URL::createInputStream under Windows.
This param is completely ignored because of a known bug in the Microsoft wininet API. Therefore the createInputStream function blocks about 30 seconds, if it can’t connect.
I’ve seen that you’re setting:

on line 85 of the juce_win32_Network.cpp, but this hasn’t any effect.
Please check these links, to get a description and workaround for the wininet bug:
http://support.microsoft.com/kb/224318/en-us
http://www.c-bit.org/frame.ms-faq/Q/176420/EN-US/
Although there are comments that this issue is fixed, there are many post on the net, that it still does not work without the mentioned workarounds and it does not work for the juce_win32_Network.cpp.

It would be cool if you could implement the described fix, because it blocks the calling thread for more than 30 seconds, which is really annoying, especially when the user tries to close the app.

It also would be very nice if you could add the option:

int disable = 1; InternetSetOption (sessionHandle, INTERNET_OPTION_DISABLE_AUTODIAL, &disable, sizeof(disable));
(Code was tested - works)
Because I don’t think an app should “force” a user to connect to the internet if he might be disconnected for some good reason.
If you don’t like the idea of disabling autodialup permanently, maybe you could add it as an optional param.

Thanks.


#2

According to the MS article, it’s only a bug in IE5 and earlier. What are you testing it with?


#3

I’m testing with Firefox 3.6 and IE8.
There were several post in other forums where poeple had the same problem with IE7 and IE8.
So I assume this is still not fixed.


#4

Ok, maybe something like this:

[code]class InternetConnectThread : public Thread
{
public:
InternetConnectThread (URL_COMPONENTS& uc_, HINTERNET& connection_, const bool isFtp_)
: Thread (“Internet”), uc (uc_), connection (connection_), isFtp (isFtp_)
{
startThread();
}

~InternetConnectThread()
{
    stopThread (60000);
}

void run()
{
    connection = InternetConnect (sessionHandle, uc.lpszHostName,
                                  uc.nPort, _T(""), _T(""),
                                  isFtp ? INTERNET_SERVICE_FTP
                                        : INTERNET_SERVICE_HTTP,
                                  0, 0);
    notify();
}

juce_UseDebuggingNewOperator

private:
URL_COMPONENTS& uc;
HINTERNET& connection;
const bool isFtp;

InternetConnectThread (const InternetConnectThread&);
InternetConnectThread& operator= (const InternetConnectThread&);

};[/code]

…and then:

[code] const bool isFtp = url.startsWithIgnoreCase (T(“ftp:”));

        HINTERNET connection = 0;

        {
            InternetConnectThread connectThread (uc, connection, isFtp);
            connectThread.wait (timeOutMs);

            if (connection == 0)
            {
                InternetCloseHandle (sessionHandle);
                sessionHandle = 0;
            }
        }

[/code]
?


#5

Cool, I’ll check it later this evening and give you some feedback.
Thanks


#6

I have to correct myself.
It’s not the “InternetConnect” function that is ignoring the timeout.
Actually the problem is, that the “HttpSendRequestEx” ignores any timeouts and if you are connected to some network that has no active internet connection, it blocks about 30 seconds and there is no way to stop the attempts to send requests because calls to InternetCloseHandle don’t have any effect on this. Therefore even a threaded approach wouldn’t do the trick.
There are no problems if the internet connection is active or if you aren’t connected to any network at all e.g. plug off the cable.

Pretty annoying but I can’t think of a workarround for this.
Thanks anyways.


#7

Hmm. Good old microsoft.

Well, I rolled the code that we suggested above into the latest build, with a flag that disables it by default. I guess I’ll leave it disabled!