Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-27678

QAbstractSocket::bind() is not honored

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P2: Important
    • None
    • 5.0.0 Beta 1
    • Network: Sockets
    • None
    • {noformat}
      $ uname -a
      Linux sjinks 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
      $ lsb_release -rd
      Description: Ubuntu 12.10
      Release: 12.10
      {noformat}

    Description

      Sample code:

      #include <QtCore/QCoreApplication>
      #include <QtCore/QDebug>
      #include <QtNetwork/QHostAddress>
      #include <QtNetwork/QTcpSocket>
      #include "sockettester.h"
      
      SocketTester::SocketTester(QObject* parent)
          : QObject(parent), socket(new QTcpSocket())
      {
          QObject::connect(socket, SIGNAL(connected()), this, SLOT(connected()));
          QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
          QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
          QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
          QObject::connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState)));
      }
      
      void SocketTester::run(void)
      {
          this->socket->bind(QHostAddress(QLatin1String("72.251.207.223")), 0);
          this->socket->connectToHost(QLatin1String("aspmx.l.google.com."), 25);
      }
      
      void SocketTester::connected(void)
      {
          qDebug() << "CONNECTED" << this->socket->localAddress() << this->socket->localPort();
      }
      
      void SocketTester::disconnected(void)
      {
          qDebug() << "DISCONNECTED";
          QCoreApplication::quit();
      }
      
      void SocketTester::error(QAbstractSocket::SocketError e)
      {
          qDebug() << "ERROR" << e << this->socket->errorString();
      }
      
      void SocketTester::readyRead(void)
      {
          static int f = 0;
          qDebug() << "READYREAD" << this->socket->readAll();
          if (!f) {
              f = 1;
              this->socket->write("EHLO localhost\r\n");
          }
          else if (1 == f) {
              this->socket->write("QUIT\r\n");
              f = 2;
          }
      }
      
      void SocketTester::stateChanged(QAbstractSocket::SocketState s)
      {
          qDebug() << "STATECHANGED" << s << this->socket->localAddress() << this->socket->localPort();
      }
      

      Output (Qt built in debug mode):

      QTcpSocket::QTcpSocket()
      QAbstractSocketPrivate::resetSocketLayer()
      QAbstractSocketPrivate::initSocketLayer(TcpSocket, IPv4Protocol) success
      QNativeSocketEnginePrivate::nativeBind(72.251.207.223, 0) == true
      QNativeSocketEnginePrivate::fetchConnectionParameters() local == 72.251.207.223:46140, peer == :0, socket == TcpSocket - IPv4Protocol
      STATECHANGED QAbstractSocket::BoundState  QHostAddress( "72.251.207.223" )  46140 
      QAbstractSocket::connectToHost("aspmx.l.google.com.", 25, 3)...
      STATECHANGED QAbstractSocket::HostLookupState  QHostAddress( "" )  0 
      QHostInfo::lookupHost("aspmx.l.google.com.", 0x17d0bb0, _q_startConnecting(QHostInfo))
      QAbstractSocket::connectToHost("aspmx.l.google.com.", 25) == false (connection in progress)
      QAbstractSocketPrivate::canReadNotification()
      QNativeSocketEnginePrivate::nativeBytesAvailable() == 0
      QAbstractSocketPrivate::readFromSocket() about to read 4096 bytes
      QHostInfoAgent::fromName(aspmx.l.google.com.) looking up...
      QNativeSocketEnginePrivate::nativeRead(0x17d2a40 "", 4096) == -1
      QNativeSocketEngine::nativeClose()
      QAbstractSocketPrivate::readFromSocket() got -1 bytes, buffer size = 0
      ERROR QAbstractSocket::NetworkError "Transport endpoint is not connected" 
      QAbstractSocketPrivate::readFromSocket() read failed: Transport endpoint is not connected
      QAbstractSocketPrivate::resetSocketLayer()
      QAbstractSocketPrivate::canReadNotification() disconnecting socket
      QAbstractSocket::disconnectFromHost()
      QAbstractSocket::disconnectFromHost() but we're still connecting
      getaddrinfo node: flags: 32 family: 2 ai_socktype: 1 ai_protocol: 6 ai_addrlen: 16 
      getaddrinfo node: flags: 32 family: 2 ai_socktype: 2 ai_protocol: 17 ai_addrlen: 16 
      getaddrinfo node: flags: 32 family: 2 ai_socktype: 3 ai_protocol: 0 ai_addrlen: 16 
      QHostInfoAgent::fromName(): found 1 entries for "aspmx.l.google.com.": {173.194.65.26}
      QAbstractSocketPrivate::_q_startConnecting(hostInfo == {173.194.65.26})
      STATECHANGED QAbstractSocket::ConnectingState  QHostAddress( "" )  0 
      QAbstractSocketPrivate::_q_connectToNextAddress(), connecting to 173.194.65.26:25, 1 left to try
      QAbstractSocketPrivate::resetSocketLayer()
      QAbstractSocketPrivate::initSocketLayer(TcpSocket, IPv4Protocol) success
      QNativeSocketEnginePrivate::nativeConnect() : 4 
      QNativeSocketEnginePrivate::nativeConnect(173.194.65.26, 25) == false (Connection in progress)
      QNativeSocketEnginePrivate::nativeConnect() : 4 
      QNativeSocketEnginePrivate::nativeConnect(173.194.65.26, 25) == true
      QNativeSocketEnginePrivate::fetchConnectionParameters() local == 78.30.235.66:49951, peer == 173.194.65.26:25, socket == TcpSocket - IPv4Protocol
      QAbstractSocketPrivate::connectionNotification() testing connection
      STATECHANGED QAbstractSocket::ConnectedState  QHostAddress( "78.30.235.66" )  49951 
      CONNECTED  QHostAddress( "78.30.235.66" )  49951 
      QAbstractSocketPrivate::fetchConnectionParameters() connection to 173.194.65.26:25 established
      QAbstractSocket::disconnectFromHost()
      QAbstractSocket::disconnectFromHost() emits stateChanged()(ClosingState)
      STATECHANGED QAbstractSocket::ClosingState  QHostAddress( "78.30.235.66" )  49951 
      QAbstractSocket::disconnectFromHost() disconnecting immediately
      QAbstractSocketPrivate::resetSocketLayer()
      QNativeSocketEngine::nativeClose()
      STATECHANGED QAbstractSocket::UnconnectedState  QHostAddress( "78.30.235.66" )  49951 
      DISCONNECTED 
      QAbstractSocket::disconnectFromHost() disconnected!
      

      A call to QAbstractSocketPrivate::resetSocketLayer() closes the socket and thus the binding is lost. QAbstractSocketPrivate::_q_connectToNextAddress() calls resetSocketLayer() again.

      If we replace

      this->socket->connectToHost(QLatin1String("aspmx.l.google.com."), 25);

      with

      this->socket->connectToHost(QLatin1String("173.194.65.26"), 25);

      the binding will still be lost but the picture will be different ("Transport endpoint is not connected" error will be gone and we will actually be able to connect to the host):

      QAbstractSocket::QAbstractSocket(TcpSocket, QAbstractSocketPrivate == 0x1599ba0, parent == 0x0)
      QTcpSocket::QTcpSocket()
      QAbstractSocketPrivate::resetSocketLayer()
      QAbstractSocketPrivate::initSocketLayer(TcpSocket, IPv4Protocol) success
      QNativeSocketEnginePrivate::nativeBind(72.251.207.223, 0) == true
      QNativeSocketEnginePrivate::fetchConnectionParameters() local == 72.251.207.223:40649, peer == :0, socket == TcpSocket - IPv4Protocol
      STATECHANGED QAbstractSocket::BoundState  QHostAddress( "72.251.207.223" )  40649 
      QAbstractSocket::connectToHost("173.194.65.26", 25, 3)...
      STATECHANGED QAbstractSocket::HostLookupState  QHostAddress( "" )  0 
      QAbstractSocketPrivate::_q_startConnecting(hostInfo == {173.194.65.26})
      STATECHANGED QAbstractSocket::ConnectingState  QHostAddress( "" )  0 
      QAbstractSocketPrivate::_q_connectToNextAddress(), connecting to 173.194.65.26:25, 1 left to try
      QAbstractSocketPrivate::resetSocketLayer()
      QNativeSocketEngine::nativeClose()
      QAbstractSocketPrivate::initSocketLayer(TcpSocket, IPv4Protocol) success
      QNativeSocketEnginePrivate::nativeConnect() : 4 
      QNativeSocketEnginePrivate::nativeConnect(173.194.65.26, 25) == false (Connection in progress)
      QAbstractSocket::connectToHost("173.194.65.26", 25) == false (connection in progress)
      QNativeSocketEnginePrivate::nativeConnect() : 4 
      QNativeSocketEnginePrivate::nativeConnect(173.194.65.26, 25) == true
      QNativeSocketEnginePrivate::fetchConnectionParameters() local == 78.30.235.66:50044, peer == 173.194.65.26:25, socket == TcpSocket - IPv4Protocol
      QAbstractSocketPrivate::connectionNotification() testing connection
      STATECHANGED QAbstractSocket::ConnectedState  QHostAddress( "78.30.235.66" )  50044 
      CONNECTED  QHostAddress( "78.30.235.66" )  50044 
      QAbstractSocketPrivate::fetchConnectionParameters() connection to 173.194.65.26:25 established
      QAbstractSocketPrivate::canWriteNotification() flushing
      QAbstractSocketPrivate::flush() nothing to do: valid ? yes, writeBuffer.isEmpty() ? yes
      QAbstractSocketPrivate::canReadNotification()
      QNativeSocketEnginePrivate::nativeBytesAvailable() == 44
      QAbstractSocketPrivate::readFromSocket() about to read 44 bytes
      QNativeSocketEnginePrivate::nativeRead(0x159b570 "220 mx.google.co...", 44) == 44
      QAbstractSocketPrivate::readFromSocket() got 44 bytes, buffer size = 44
      READYREAD "220 mx.google.com ESMTP n49si4070759eeo.97
      " 
      QAbstractSocket::writeData(0x40352d "EHLO localhost\r\n", 16) == 16
      QAbstractSocketPrivate::canWriteNotification() flushing
      QNativeSocketEnginePrivate::nativeWrite(0x159b588 "EHLO localhost\r\n", 16) == 16
      QAbstractSocketPrivate::flush() 16 bytes written to the network
      QAbstractSocketPrivate::canReadNotification()
      QNativeSocketEnginePrivate::nativeBytesAvailable() == 123
      QAbstractSocketPrivate::readFromSocket() about to read 123 bytes
      QNativeSocketEnginePrivate::nativeRead(0x159b570 "250-mx.google.co...", 123) == 123
      QAbstractSocketPrivate::readFromSocket() got 123 bytes, buffer size = 123
      READYREAD "250-mx.google.com at your service, [78.30.235.66]
      250-SIZE 35882577
      250-8BITMIME
      250-STARTTLS
      250 ENHANCEDSTATUSCODES
      " 
      QAbstractSocket::writeData(0x40353e "QUIT\r\n", 6) == 6
      QAbstractSocketPrivate::canWriteNotification() flushing
      QNativeSocketEnginePrivate::nativeWrite(0x159b588 "QUIT\r\n", 6) == 6
      QAbstractSocketPrivate::flush() 6 bytes written to the network
      QAbstractSocketPrivate::canReadNotification()
      QNativeSocketEnginePrivate::nativeBytesAvailable() == 49
      QAbstractSocketPrivate::readFromSocket() about to read 49 bytes
      QNativeSocketEnginePrivate::nativeRead(0x159b570 "221 2.0.0 closin...", 49) == 49
      QAbstractSocketPrivate::readFromSocket() got 49 bytes, buffer size = 49
      READYREAD "221 2.0.0 closing connection n49si4070759eeo.97
      " 
      QAbstractSocketPrivate::canReadNotification()
      QNativeSocketEnginePrivate::nativeBytesAvailable() == 0
      QAbstractSocketPrivate::readFromSocket() about to read 4096 bytes
      QNativeSocketEnginePrivate::nativeRead(0x159b570 "", 4096) == 0
      QNativeSocketEngine::nativeClose()
      QAbstractSocketPrivate::readFromSocket() got -1 bytes, buffer size = 0
      ERROR QAbstractSocket::RemoteHostClosedError "The remote host closed the connection" 
      QAbstractSocketPrivate::readFromSocket() read failed: The remote host closed the connection
      QAbstractSocketPrivate::resetSocketLayer()
      QAbstractSocketPrivate::canReadNotification() disconnecting socket
      QAbstractSocket::disconnectFromHost()
      QAbstractSocket::disconnectFromHost() emits stateChanged()(ClosingState)
      STATECHANGED QAbstractSocket::ClosingState  QHostAddress( "78.30.235.66" )  50044 
      QAbstractSocket::disconnectFromHost() disconnecting immediately
      QAbstractSocketPrivate::resetSocketLayer()
      STATECHANGED QAbstractSocket::UnconnectedState  QHostAddress( "78.30.235.66" )  50044 
      DISCONNECTED 
      QAbstractSocket::disconnectFromHost() disconnected!
      

      The expected behavior is:

      • when connecting to the host by name:
        • we should not try to read from the not connected socket (resulting in "Transport endpoint is not connected" error)
        • socket binding must be preserved
        • we should eventually be able to connect to the host
      • when connecting to the host by IP:
        • socket binding must be preserved - QAbstractSocketPrivate::_q_connectToNextAddress() probably should not call resetSocketLayer()

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-27678
          # Subject Branch Project Status CR V

          Activity

            People

              kurt.pattyn Kurt Pattyn
              vladimir.kolesnikov Vladimir Kolesnikov
              Votes:
              5 Vote for this issue
              Watchers:
              11 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes