QSocket problem with transconnect (proxy)?

Thiago Macieira thiagom at wanadoo.fr
Thu Jun 20 12:29:03 BST 2002

Michael Goffioul wrote
>Simon Hausmann wrote:
>> I think this is a bug in transconnect, or rather: A missing feature.
>> What QSocket does is to make the socket non-blocking. Then it issues
>> the first connect(), which immediately returns with EINPROGRESS, as
>> the socket is non-blocking. As the socketnotifier indicates
>> writability, QSocket issues a second connect() (on the same fd) ,
>> which (in the normal case) returns 0, indicating a connection
>> success.
>I don't think that's what happening. As I explained above, the first
>connect attempt establish the connection immediately, this can
>happen even if the socket is non-blocking (for example on a LAN).
>The socketnotifier being enabled, an event is fired, triggering
>QSocket::sn_write() -> QSocket::tryConnection(). The latter again
>tries to establish the connection, but the problem is that now it
>is using d->addr, which contains, it's not the same fd.
>This is the only place in the whole qsocket.cpp file where
>d->addr is used, I couldn't find any place where this might be
>set to something else. No surprise then that it contains
>But trying to connect on fails using transconnect.
>Don't know where's the fault, though.

I think I may have found the bug:
when you call connectToHost(), it creates a QDns to do the lookup and connects 
it to QSocket::tryConnecting(). When that slot gets called, it'll fetch the 
connection lookup results and try to connect to the first (and only the 
first) of the returned values, after placing the socket in non-blocking mode.

What happens is that it expects connect() to return with failure (errno = 
EINPROGRESS). What happens is that the local connection is established 
immediately and the connection then is successful. The QSocket class never 
leaves the QSocket::Connecting state.

By the first time QSocket::sn_write() gets called, it'll see the 
QSocket::connecting state and instead call QSocket::tryConnection(). That's 
an error, because:
a) the socket is already connected
b) d->addr has never got set
    (actually, I couldn't find where it is ever set)

The solution is this:
Index: qsocket.cpp
RCS file: /home/kde/qt-copy/src/network/qsocket.cpp,v
retrieving revision 1.24
diff -u -3 -p -r1.24 qsocket.cpp
--- qsocket.cpp 2002/03/15 19:31:56     1.24
+++ qsocket.cpp 2002/06/20 11:28:09
@@ -358,6 +358,13 @@ void QSocket::tryConnecting()
        // The socket write notifier will fire when the connection succeeds
        if ( d->wsn )
            d->wsn->setEnabled( TRUE );
+       // Actually, the connection has already succeeded (returned TRUE 
+       // -thiago
+       d->state = Connected;
+       emit connected();
+       if ( d->rsn )
+           d->rsn->setEnabled( TRUE );

Note: I haven't tested that

Note 2: I hope you're not developing a KDE application

  Thiago Macieira - UFOT Registry number: 1001
 thiagom at mail.com
   ICQ UIN: 1967141  PGP: will create new keys. Erase the old ones!
     Registered Linux user #65028

More information about the kde-core-devel mailing list