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 |
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 |