0

Using Embarcadero C++ Builder 2010, I'm trying to detect specific web server devices connected to a network.

I'm interrogating those devices by calling a CGI function using TIdHTTP and analyzing the answer on a range of IP address.

I am using IdHTTP->ConnectTimeout and IdHTTP->ReadTimeout parameters to throws an exception if there's no connection by the time the timeout elapses. This should happen when TIdHTTP is interrogating an unexpected devices, in this case I release IdHTTP by calling IdHTTP->Free().

It works fine on Windows 7, but on Windows XP the timeout doesn't apply, so it can take up to 10 minutes before IdHTTP.get() stop.

By removing those two parameters the app work a bit faster on Windows XP but still take to long compare to the timeout than I am expecting.

I found this related subject without real solutions: Indy 10 + SSL = works in Windows 7, does not work on XP

This is a part of the source code:

        #include "winsock2.h"

        String url = "http://" + anIpAddress + "/myCGIFunction.cgi";
        TMemoryStream *XML = new TMemoryStream;
        AnsiString answer="";

        p_IdHTTP = new TIdHTTP(NULL);
        try
        {
                p_IdHTTP->ConnectTimeout = 2000;

                p_IdHTTP->Get(url,XML);

                XML->Position = 0;
            answer=ReadStringFromStream(XML);

                p_IdHTTP->Free();
         }
         catch (...)
         {
            p_IdHTTP->Free();
         }

My questions are: Why does IdHTTP->ConnectTimeout isn't working on Windows XP? And do you have any idea to replace this parameter to release/destroyed the IdHTTP after a specific time?

Update:

    void __fastcall Func::MyFunc()
    {
                AnsiString anIpAddress= "20.20.20.11";
                String url = "http://" + anIpAddress + "/myCGIFunction.cgi";
                TMemoryStream *XML = new TMemoryStream;
                AnsiString answer="";

                p_IdHTTP = new TIdHTTP(NULL);
                try
                {
                        p_SSLHandler=new TIdSSLIOHandlerSocketOpenSSL(p_IdHTTP);
                p_SSLHandler->SSLOptions->Method= sslvSSLv23;

                p_IdHTTP->ConnectTimeout = 2000;
                p_IdHTTP->ReadTimeout=400;
                p_IdHTTP->IOHandler=p_SSLHandler;

                p_IdHTTP->OnConnected= IdHTTPConnected;
                p_IdHTTP->OnStatus= IdHTTPStatus;

                p_IdHTTP->Get(url,XML);
                        XML->Position = 0;
                    answer=ReadStringFromStream(XML);

                        p_IdHTTP->Free();
                 }
                 catch (...)
                 {
                    p_IdHTTP->Free();
                 }
   } 


void __fastcall Func::IdHTTPStatus(TObject *Sender, TIdStatus const AStatus, String const AStatusText){

    String msgtest = ipAddress ;

    switch (AStatus){
        case  (hsResolving):
            msgtest+= " resolving...";

            break;
        case  (hsConnecting):
            msgtest+= "  connecting...";
            break;
        case  (hsConnected):
            msgtest+= "  connected...";
            break;
        case  (hsDisconnecting):
            msgtest+= "  disconnecting...";
            break;
        case  (hsDisconnected):
            msgtest+= "  disconnected...";
            break;
        case  (hsStatusText):
            msgtest+= "  hsStatusText: " + AStatusText;
            break;
        default:
            msgtest+= " Other status ";
            break;
    }
    aListBox->Items->Add(msgtest);
    Application->ProcessMessages();
}

void __fastcall Func::IdHTTPConnected(TObject *Sender){
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;

setsockopt((unsigned int) p_IdHTTP->Socket->Binding, SOL_SOCKET,    
                           SO_RCVTIMEO, (char *)&timeout, sizeof(timeout) );

    setsockopt ((unsigned int) p_IdHTTP->Socket->Binding, SOL_SOCKET, SO_SNDTIMEO,
                 (char *)&timeout, sizeof(timeout));

}

Community
  • 1
  • 1
durje
  • 135
  • 1
  • 2
  • 10
  • Did you read the entire discussion in the [other question](http://stackoverflow.com/questions/15363043), including the chat? What does the `OnStatus` event report in your situation? It is important to pay attention to that event when troubleshooting issues like this since it tells you what stage Indy is getting stuck at. – Remy Lebeau Dec 02 '13 at 23:36
  • @RemyLebeau :Thanks for your reply, Yes I read the entire discussion including the chat, but to be honest I am not sure to understand all of it. On some IP address (where i have an aclual divice connected) it seems to work well i got "hsConnecting" and "hsStatusText" but for IP with a macAddress but without a webInterface, OnStatus doesn't trigger – durje Dec 03 '13 at 16:18
  • @RemyLebeau Do you know a way to detect that there is no web interface on an IP/MAC url before i actually call IdHTTP->Get(url,XML) to avoid the problem? Thanks in advance – durje Dec 03 '13 at 16:21
  • what text messages does `hsStatusText` report? What value(s) are you actually putting into `anIpAddress` when `ConnectTimeout` fails? You cannot connect to a MAC address, only to an IP address or a hostname that resolves to an IP address. As the other discussion mentions, if you don't specify an IP, Indy has to resolve the IP, and `ConnectTimeout` does not apply to that step. That is why I'm trying to determine what step you are actually getting stuck at. – Remy Lebeau Dec 03 '13 at 16:39
  • @RemyLebeau : hsStatusText report "Chunk Started" for an IP corresponding to a valid device (For example when anIpAddress="20.20.20.16" and a device that I am looking at, has 20.20.20.16 as an IP address) But when I am doing the same on an other IP , where the machine/PC have a MAC address but no web interface, for example "20.20.20.91" then IdHTTPStatus and IdHTTPConnected are never trigger, and MyFunc() take ages to finish without considering the timeout. – durje Dec 04 '13 at 09:44
  • `Chunk Started` means that `TIdHTTP` has successfully connected to an HTTP server, sent an HTTP request to it, and is receiving a valid HTTP response that is using the `chunked` transfer encoding. You should be getting an `hsResolving` status event if you do not specify an IP address, and you should always be getting an `hsConnecting` status event before it tries to actually establish the connection. If you are not getting any `OnStatus` events at all, then something is wrong with your setup. `ConnectTimeout` only applies after `hsConnecting` has been triggered first. – Remy Lebeau Dec 04 '13 at 20:28
  • The only way I can think of `TIdHTTP.OnStatus` not being triggered for `hsConnecting` is if you assigned your own `IOHandler` object to the `TIdHTTP.IOHandler` but did not assign a handler to the `IOHandler.OnStatus` event. If you let `TIdHTTP` create its own `IOHandler` internally (default behavior), it assigns the `TIdHTTP.OnStatus` handler to the `IOHandler.OnStatus` event. – Remy Lebeau Dec 04 '13 at 20:30
  • @RemyLebeau : See my update above, this is all that I am doing, so I assigned my own IOHandler to the TIdHTTP.IOHandler (p_IdHTTP->IOHandler=p_SSLHandler;) but I am not sure to assign a handler to the IOHandler.OnStatus event, how should i do such a thing? p_SSLHandler->OnStatus=...; ? – durje Dec 05 '13 at 15:56
  • you can assign the `TIdIOHandler::OnStatus` event the exact same way you are assigning the `TIdHTTP:OnStatus` event. However, you are not accessing an HTTPS url so you do not need the `SSLIOHandler` in the first place. If you get rid of the `SSLIOHandler`, `TIdHTTP` will create its own `IOHandler` for you, and the `TIdHTTP::OnStatus` event will work. Also, you need to use the `delete` operator instead of calling `Free()`. – Remy Lebeau Dec 05 '13 at 16:19
  • Thanks @RemyLebeau there is some improvement, so now I still get: { "hsConnecting", "hsConnected", hsStatusText="Chunk Started" } OnStatus event, and OnConnected trigger aswell on an IP corresponding to a valid device. The new thing is that now I get an "hsConnecting" OnStatus event on unvalide device but nothing else, no IdHTTP->OnConnected event. So on XP it still take ages to finish without considering the timeout. – durje Dec 06 '13 at 09:52
  • Also I put IdHTTP1.Free because it was one the Delphi code in the other question, I tried to use the delete operator and it need a "UnicodeString AURL" in argument should I put my url String? I didn't find any example online! And I can't find any Indy documentation for C++ only for Delphi. – durje Dec 06 '13 at 09:55
  • @RemyLebeau any more help please? – durje Dec 16 '13 at 09:39
  • After you get the `hsConnecting` status event, the only slowdowns I can think of are: 1) time to create the worker thread that calls `connect ()` while the `ConnectTimeout` is active; 2) if `select()` deadlocks unexpectedly while waiting for the `ConnectTimeout` to elapse; 3) if `connect()` does not exit when the socket is closed if the `ConnectTimeout` elapses; 4) if you are using `TIdAntiFreeze` and a message handler deadlocks while `ConnectTimeout` is still active. – Remy Lebeau Dec 16 '13 at 17:06
  • As for `Free()` vs `delete`, I was referring to C++'s `delete` operator, ie `delete IdHTTP1`, not the `TIdHTTP::Delete()` method, ie: `IdHTTP1->Delete(URL)`. – Remy Lebeau Dec 16 '13 at 17:09

0 Answers0