Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Add Timeout to "GetPublicAddress"  (Read 25045 times)

0 Members and 2 Guests are viewing this topic.

zac

  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Add Timeout to "GetPublicAddress"
« on: January 18, 2009, 01:22:45 am »
Problem:
The server at whatismyip.org is sometimes not responsive or does not answer our requests (for unknown reasons, though I only do a request once, when (re)starting the program).

Possible solution/workaround:
Add a way to pass a timeout value. If the connection to the server can not be created successfully, return an invalid IP.

Since you are using the HTTP class to connect by now, I would suggest to add a timeout in the HTTP/FTP class too. It is supported by the underlying sockets, so it shouldn't be to hard to implement...

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Add Timeout to "GetPublicAddress"
« Reply #1 on: January 18, 2009, 12:44:00 pm »
It's done.

Thank you for your feedback :)
Laurent Gomila - SFML developer

zac

  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Add Timeout to "GetPublicAddress"
« Reply #2 on: January 18, 2009, 12:59:06 pm »
Hey, that was really fast. Thanks.

zac

  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Add Timeout to "GetPublicAddress"
« Reply #3 on: January 18, 2009, 04:29:06 pm »
Hm, it does not really seem to work:
http://www.sfml-dev.org/forum/viewtopic.php?t=933

If I remove the timeout-parameter, it works.
I think this is related to a bug I posted, but there was no answer up to now - the return values of "Connect" are wrong. When its given a timeout, Connect returns 3 instead of Socket::Done, even if the connection has been built properly.

See:
http://www.sfml-dev.org/forum/viewtopic.php?t=883

I'm currently walking through the implementation of connect, but I don't see where in the connect call this bug arises.

There is at least one little bug:
If the connection is immediately successfull (Connect with timeout), you are not resetting the Blocking Mode to "true".
This might trigger a lot of funny bugs (especially with the loopback - it is very fast and so not unlikely the connection works "immediately").

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Add Timeout to "GetPublicAddress"
« Reply #4 on: January 18, 2009, 07:04:49 pm »
I've replied to both of your posts. Basically, everything works fine for me.

Regarding the potential bug in Connect, I don't remember why but at the time I implemented it, I knew it was not necessary. I should have left a comment :)
Laurent Gomila - SFML developer

zac

  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Add Timeout to "GetPublicAddress"
« Reply #5 on: January 18, 2009, 08:21:02 pm »
Yes, there is one thing I first considered a bug, which isn't, because there is an immediate return if the socket is non-blocking. But this one definitely is. If you try to connect with a blocking socket with timeout, and the connection is successfull on the first "connect" call, you will end up with a Non-Blocking socket.
Maybe this is simply not possible, connect succeeding on the first time, (who knows? I don't see any reason why it can't be possible), or it just appears on loopback or something like this...

You could replace:
Code: [Select]

 bool IsBlocking = myIsBlocking;
 if(IsBlocking)
        SetBlocking(false);
       
        if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0)

        {

            // We got instantly connected! (it may no happen a lot...)

            return Socket::Done;

        }


by:
Code: [Select]

bool IsBlocking = myIsBlocking;

        if(IsBlocking)
        SetBlocking(false);
       
        if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0)

        {

            // We got instantly connected! (it may no happen a lot...)
            if(IsBlocking)
            SetBlocking(true);
           

            return Socket::Done;

        }


I will do some bug research with the SocketTCP connect code... I will tell you if I know more about the return value thingy.

zac

  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Add Timeout to "GetPublicAddress"
« Reply #6 on: January 18, 2009, 08:46:18 pm »
I GOT it.
Please add:
Code: [Select]

#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
    case EAGAIN: return Socket::NotReady;
#endif
#if defined(EINPROGRESS) && EINPROGRESS != EWOULDBLOCK && EINPROGRESS != EAGAIN
case EINPROGRESS: return Socket::NotReady;
#endif

to the switch-case in the Linux "SocketHelper.cpp" SocketHelper::GetErrorStatus()!
The error values are sometimes the same, but obviously not always.
connect sets errno to EINPROGRESS, in my case.
See:
http://linux.die.net/man/2/connect

The precompiler statements just make sure there are no double values in the switch case.

This also explains why it works perfectly on windows ;) ;)

Together with this one, all the other bugs vanished. Everything is working fine with these changes.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Add Timeout to "GetPublicAddress"
« Reply #7 on: January 18, 2009, 11:31:40 pm »
Ahah!

Great job, I just applied the fix :)
Laurent Gomila - SFML developer