src/network/socket/qabstractsocket.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   460       readBuffer(QABSTRACTSOCKET_BUFFERSIZE),
   460       readBuffer(QABSTRACTSOCKET_BUFFERSIZE),
   461       writeBuffer(QABSTRACTSOCKET_BUFFERSIZE),
   461       writeBuffer(QABSTRACTSOCKET_BUFFERSIZE),
   462       isBuffered(false),
   462       isBuffered(false),
   463       blockingTimeout(30000),
   463       blockingTimeout(30000),
   464       connectTimer(0),
   464       connectTimer(0),
       
   465       disconnectTimer(0),
   465       connectTimeElapsed(0),
   466       connectTimeElapsed(0),
   466       hostLookupId(-1),
   467       hostLookupId(-1),
   467       socketType(QAbstractSocket::UnknownSocketType),
   468       socketType(QAbstractSocket::UnknownSocketType),
   468       state(QAbstractSocket::UnconnectedState),
   469       state(QAbstractSocket::UnconnectedState),
   469       socketError(QAbstractSocket::UnknownSocketError)
   470       socketError(QAbstractSocket::UnknownSocketError)
   495         socketEngine->disconnect();
   496         socketEngine->disconnect();
   496         delete socketEngine;
   497         delete socketEngine;
   497         socketEngine = 0;
   498         socketEngine = 0;
   498         cachedSocketDescriptor = -1;
   499         cachedSocketDescriptor = -1;
   499     }
   500     }
   500     if (connectTimer) {
   501     if (connectTimer)
   501         connectTimer->stop();
   502         connectTimer->stop();
   502     }
   503     if (disconnectTimer)
       
   504         disconnectTimer->stop();
   503 }
   505 }
   504 
   506 
   505 /*! \internal
   507 /*! \internal
   506 
   508 
   507     Initializes the socket layer to by of type \a type, using the
   509     Initializes the socket layer to by of type \a type, using the
   667     int tmp = writeBuffer.size();
   669     int tmp = writeBuffer.size();
   668     flush();
   670     flush();
   669 
   671 
   670     if (socketEngine) {
   672     if (socketEngine) {
   671 #if defined (Q_OS_WIN)
   673 #if defined (Q_OS_WIN)
   672 	if (!writeBuffer.isEmpty())
   674         if (!writeBuffer.isEmpty())
   673 	    socketEngine->setWriteNotificationEnabled(true);
   675             socketEngine->setWriteNotificationEnabled(true);
   674 #else
   676 #else
   675 	if (writeBuffer.isEmpty())
   677         if (writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0)
   676 	    socketEngine->setWriteNotificationEnabled(false);
   678             socketEngine->setWriteNotificationEnabled(false);
   677 #endif
   679 #endif
   678     }
   680     }
   679 
   681 
   680     return (writeBuffer.size() < tmp);
   682     return (writeBuffer.size() < tmp);
   681 }
   683 }
   708     Emits bytesWritten().
   710     Emits bytesWritten().
   709 */
   711 */
   710 bool QAbstractSocketPrivate::flush()
   712 bool QAbstractSocketPrivate::flush()
   711 {
   713 {
   712     Q_Q(QAbstractSocket);
   714     Q_Q(QAbstractSocket);
   713     if (!socketEngine || !socketEngine->isValid() || writeBuffer.isEmpty()) {
   715     if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty()
       
   716         && socketEngine->bytesToWrite() == 0)) {
   714 #if defined (QABSTRACTSOCKET_DEBUG)
   717 #if defined (QABSTRACTSOCKET_DEBUG)
   715     qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
   718     qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s",
   716            socketEngine->isValid() ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
   719            socketEngine->isValid() ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no");
   717 #endif
   720 #endif
       
   721 
       
   722         // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
       
   723         if (state == QAbstractSocket::ClosingState)
       
   724             q->disconnectFromHost();
       
   725 
   718         return false;
   726         return false;
   719     }
   727     }
   720 
   728 
   721     int nextSize = writeBuffer.nextDataBlockSize();
   729     int nextSize = writeBuffer.nextDataBlockSize();
   722     const char *ptr = writeBuffer.readPointer();
   730     const char *ptr = writeBuffer.readPointer();
   749             emit q->bytesWritten(written);
   757             emit q->bytesWritten(written);
   750             emittedBytesWritten = false;
   758             emittedBytesWritten = false;
   751         }
   759         }
   752     }
   760     }
   753 
   761 
   754     if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled())
   762     if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()
       
   763         && !socketEngine->bytesToWrite())
   755         socketEngine->setWriteNotificationEnabled(false);
   764         socketEngine->setWriteNotificationEnabled(false);
   756     if (state == QAbstractSocket::ClosingState)
   765     if (state == QAbstractSocket::ClosingState)
   757         q->disconnectFromHost();
   766         q->disconnectFromHost();
   758 
   767 
   759     return true;
   768     return true;
  1082         q->setErrorString(QAbstractSocket::tr("Connection timed out"));
  1091         q->setErrorString(QAbstractSocket::tr("Connection timed out"));
  1083         emit q->stateChanged(state);
  1092         emit q->stateChanged(state);
  1084         emit q->error(socketError);
  1093         emit q->error(socketError);
  1085     } else {
  1094     } else {
  1086         _q_connectToNextAddress();
  1095         _q_connectToNextAddress();
       
  1096     }
       
  1097 }
       
  1098 
       
  1099 void QAbstractSocketPrivate::_q_forceDisconnect()
       
  1100 {
       
  1101     Q_Q(QAbstractSocket);
       
  1102     if (socketEngine && socketEngine->isValid() && state == QAbstractSocket::ClosingState) {
       
  1103         socketEngine->close();
       
  1104         q->disconnectFromHost();
  1087     }
  1105     }
  1088 }
  1106 }
  1089 
  1107 
  1090 /*! \internal
  1108 /*! \internal
  1091 
  1109 
  1569 
  1587 
  1570     return true;
  1588     return true;
  1571 }
  1589 }
  1572 
  1590 
  1573 /*!
  1591 /*!
  1574     Sets the option \a option to the value described by \a value.
  1592     \since 4.6
       
  1593     Sets the given \a option to the value described by \a value.
  1575 
  1594 
  1576     \sa socketOption()
  1595     \sa socketOption()
  1577     \since 4.6
       
  1578 */
  1596 */
  1579 void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
  1597 void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
  1580 {
  1598 {
  1581 #ifndef QT_NO_OPENSSL
  1599 #ifndef QT_NO_OPENSSL
  1582     if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
  1600     if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
  1598             break;
  1616             break;
  1599     }
  1617     }
  1600 }
  1618 }
  1601 
  1619 
  1602 /*!
  1620 /*!
       
  1621     \since 4.6
  1603     Returns the value of the \a option option.
  1622     Returns the value of the \a option option.
  1604 
  1623 
  1605     \sa setSocketOption()
  1624     \sa setSocketOption()
  1606     \since 4.6
       
  1607 */
  1625 */
  1608 QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
  1626 QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
  1609 {
  1627 {
  1610 #ifndef QT_NO_OPENSSL
  1628 #ifndef QT_NO_OPENSSL
  1611     if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
  1629     if (QSslSocket *sslSocket = qobject_cast<QSslSocket*>(this)) {
  2345             qDebug("QAbstractSocket::disconnectFromHost() return from delayed close");
  2363             qDebug("QAbstractSocket::disconnectFromHost() return from delayed close");
  2346 #endif
  2364 #endif
  2347         }
  2365         }
  2348 
  2366 
  2349         // Wait for pending data to be written.
  2367         // Wait for pending data to be written.
  2350         if (d->socketEngine && d->socketEngine->isValid() && d->writeBuffer.size() > 0) {
  2368         if (d->socketEngine && d->socketEngine->isValid() && (d->writeBuffer.size() > 0
       
  2369             || d->socketEngine->bytesToWrite() > 0)) {
       
  2370             // hack: when we are waiting for the socket engine to write bytes (only
       
  2371             // possible when using Socks5 or HTTP socket engine), then close
       
  2372             // anyway after 2 seconds. This is to prevent a timeout on Mac, where we
       
  2373             // sometimes just did not get the write notifier from the underlying
       
  2374             // CFSocket and no progress was made.
       
  2375             if (d->writeBuffer.size() == 0 && d->socketEngine->bytesToWrite() > 0) {
       
  2376                 if (!d->disconnectTimer) {
       
  2377                     d->disconnectTimer = new QTimer(this);
       
  2378                     connect(d->disconnectTimer, SIGNAL(timeout()), this,
       
  2379                             SLOT(_q_forceDisconnect()), Qt::DirectConnection);
       
  2380                 }
       
  2381                 if (!d->disconnectTimer->isActive())
       
  2382                     d->disconnectTimer->start(2000);
       
  2383             }
  2351             d->socketEngine->setWriteNotificationEnabled(true);
  2384             d->socketEngine->setWriteNotificationEnabled(true);
  2352 
  2385 
  2353 #if defined(QABSTRACTSOCKET_DEBUG)
  2386 #if defined(QABSTRACTSOCKET_DEBUG)
  2354             qDebug("QAbstractSocket::disconnectFromHost() delaying disconnect");
  2387             qDebug("QAbstractSocket::disconnectFromHost() delaying disconnect");
  2355 #endif
  2388 #endif