diff options
Diffstat (limited to 'src/network/socket')
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 77 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket.h | 2 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket_p.h | 2 | ||||
-rw-r--r-- | src/network/socket/qhttpsocketengine.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qhttpsocketengine_p.h | 2 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_p.h | 4 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 74 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 13 |
8 files changed, 62 insertions, 116 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 1831d25718..ed86dbbbae 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -722,19 +722,9 @@ bool QAbstractSocketPrivate::canReadNotification() } } - // only emit readyRead() when not recursing, and only if there is data available - bool hasData = newBytes > 0 -#ifndef QT_NO_UDPSOCKET - || (!isBuffered && socketType != QAbstractSocket::TcpSocket && socketEngine && socketEngine->hasPendingDatagrams()) -#endif - || (!isBuffered && socketType == QAbstractSocket::TcpSocket && socketEngine) - ; - - if (!emittedReadyRead && hasData) { - QScopedValueRollback<bool> r(emittedReadyRead); - emittedReadyRead = true; - emit q->readyRead(); - } + // Only emit readyRead() if there is data available. + if (newBytes > 0 || !isBuffered) + emitReadyRead(); // If we were closed as a result of the readyRead() signal, // return. @@ -792,12 +782,12 @@ void QAbstractSocketPrivate::canCloseNotification() // then occur when we read from the socket again and fail // in canReadNotification or by the manually created // closeNotification below. - emit q->readyRead(); + emitReadyRead(); QMetaObject::invokeMethod(socketEngine, "closeNotification", Qt::QueuedConnection); } } else if (socketType == QAbstractSocket::TcpSocket && socketEngine) { - emit q->readyRead(); + emitReadyRead(); } } @@ -817,8 +807,7 @@ bool QAbstractSocketPrivate::canWriteNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canWriteNotification() flushing"); #endif - qint64 tmp = writeBuffer.size(); - flush(); + bool dataWasWritten = writeToSocket(); if (socketEngine) { #if defined (Q_OS_WIN) @@ -830,7 +819,7 @@ bool QAbstractSocketPrivate::canWriteNotification() #endif } - return (writeBuffer.size() < tmp); + return dataWasWritten; } /*! \internal @@ -852,21 +841,20 @@ void QAbstractSocketPrivate::connectionNotification() /*! \internal - Writes pending data in the write buffers to the socket. The - function writes as much as it can without blocking. + Writes one pending data block in the write buffer to the socket. It is usually invoked by canWriteNotification after one or more calls to write(). Emits bytesWritten(). */ -bool QAbstractSocketPrivate::flush() +bool QAbstractSocketPrivate::writeToSocket() { Q_Q(QAbstractSocket); if (!socketEngine || !socketEngine->isValid() || (writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0)) { #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocketPrivate::flush() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s", + qDebug("QAbstractSocketPrivate::writeToSocket() nothing to do: valid ? %s, writeBuffer.isEmpty() ? %s", (socketEngine && socketEngine->isValid()) ? "yes" : "no", writeBuffer.isEmpty() ? "yes" : "no"); #endif @@ -884,7 +872,8 @@ bool QAbstractSocketPrivate::flush() qint64 written = socketEngine->write(ptr, nextSize); if (written < 0) { #if defined (QABSTRACTSOCKET_DEBUG) - qDebug() << "QAbstractSocketPrivate::flush() write error, aborting." << socketEngine->errorString(); + qDebug() << "QAbstractSocketPrivate::writeToSocket() write error, aborting." + << socketEngine->errorString(); #endif setErrorAndEmit(socketEngine->error(), socketEngine->errorString()); // an unexpected error so close the socket. @@ -893,7 +882,7 @@ bool QAbstractSocketPrivate::flush() } #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocketPrivate::flush() %lld bytes written to the network", + qDebug("QAbstractSocketPrivate::writeToSocket() %lld bytes written to the network", written); #endif @@ -914,7 +903,23 @@ bool QAbstractSocketPrivate::flush() if (state == QAbstractSocket::ClosingState) q->disconnectFromHost(); - return true; + return written > 0; +} + +/*! \internal + + Writes pending data in the write buffers to the socket. The function + writes as much as it can without blocking. If any data was written, + this function returns true; otherwise false is returned. +*/ +bool QAbstractSocketPrivate::flush() +{ + bool dataWasWritten = false; + + while (!writeBuffer.isEmpty() && writeToSocket()) + dataWasWritten = true; + + return dataWasWritten; } #ifndef QT_NO_NETWORKPROXY @@ -1248,10 +1253,7 @@ void QAbstractSocketPrivate::_q_forceDisconnect() */ bool QAbstractSocketPrivate::readFromSocket() { -#ifdef QABSTRACTSOCKET_DEBUG Q_Q(QAbstractSocket); -#endif - // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable(); if (bytesToRead == 0) { @@ -1280,7 +1282,7 @@ bool QAbstractSocketPrivate::readFromSocket() buffer.chop(bytesToRead); return true; } - buffer.chop(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)); + buffer.chop(bytesToRead - ((readBytes < 0 || !q->isReadable()) ? qint64(0) : readBytes)); #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::readFromSocket() got %lld bytes, buffer size = %lld", readBytes, buffer.size()); @@ -1301,6 +1303,21 @@ bool QAbstractSocketPrivate::readFromSocket() /*! \internal + Prevents from the recursive readyRead() emission. +*/ +void QAbstractSocketPrivate::emitReadyRead() +{ + Q_Q(QAbstractSocket); + // Only emit readyRead() when not recursing. + if (!emittedReadyRead) { + QScopedValueRollback<bool> r(emittedReadyRead); + emittedReadyRead = true; + emit q->readyRead(); + } +} + +/*! \internal + Sets up the internal state after the connection has succeeded. */ void QAbstractSocketPrivate::fetchConnectionParameters() @@ -2378,7 +2395,7 @@ bool QAbstractSocket::isSequential() const */ bool QAbstractSocket::atEnd() const { - return QIODevice::atEnd() && (!isOpen() || d_func()->buffer.isEmpty()); + return QIODevice::atEnd(); } /*! diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 23f0d26cbd..f8edc74a24 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -176,7 +176,7 @@ public: // from QIODevice void close() Q_DECL_OVERRIDE; bool isSequential() const Q_DECL_OVERRIDE; - bool atEnd() const Q_DECL_OVERRIDE; + bool atEnd() const Q_DECL_OVERRIDE; // ### Qt6: remove me bool flush(); // for synchronous access diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index a905625b19..ba129b48df 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -135,6 +135,8 @@ public: void fetchConnectionParameters(); void setupSocketNotifiers(); bool readFromSocket(); + bool writeToSocket(); + void emitReadyRead(); void setError(QAbstractSocket::SocketError errorCode, const QString &errorString); void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString); diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 92ca76b560..3f20e5c046 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -768,7 +768,6 @@ void QHttpSocketEngine::emitPendingConnectionNotification() void QHttpSocketEngine::emitReadNotification() { Q_D(QHttpSocketEngine); - d->readNotificationActivated = true; // if there is a connection notification pending we have to emit the readNotification // incase there is connection error. This is only needed for Windows, but it does not // hurt in other cases. @@ -781,7 +780,6 @@ void QHttpSocketEngine::emitReadNotification() void QHttpSocketEngine::emitWriteNotification() { Q_D(QHttpSocketEngine); - d->writeNotificationActivated = true; if (d->writeNotificationEnabled && !d->writeNotificationPending) { d->writeNotificationPending = true; QMetaObject::invokeMethod(this, "emitPendingWriteNotification", Qt::QueuedConnection); @@ -801,8 +799,6 @@ QHttpSocketEnginePrivate::QHttpSocketEnginePrivate() : readNotificationEnabled(false) , writeNotificationEnabled(false) , exceptNotificationEnabled(false) - , readNotificationActivated(false) - , writeNotificationActivated(false) , readNotificationPending(false) , writeNotificationPending(false) , connectionNotificationPending(false) diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 41c63fe11e..b34e5b0dc3 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -172,8 +172,6 @@ public: bool readNotificationEnabled; bool writeNotificationEnabled; bool exceptNotificationEnabled; - bool readNotificationActivated; - bool writeNotificationActivated; bool readNotificationPending; bool writeNotificationPending; bool connectionNotificationPending; diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 9a76e23013..39e4d5e457 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -45,6 +45,7 @@ // We mean it. // #include "QtNetwork/qhostaddress.h" +#include "QtNetwork/qnetworkinterface.h" #include "private/qabstractsocketengine_p.h" #ifndef Q_OS_WIN # include "qplatformdefs.h" @@ -266,7 +267,8 @@ public: bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); - static uint scopeIdFromString(const QString &scopeid); + static uint scopeIdFromString(const QString &scopeid) + { return QNetworkInterface::interfaceIndexFromName(scopeid); } /*! \internal Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize. diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 8626a6be0f..2ed39fcc0a 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -107,15 +107,8 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po QHostAddress tmpAddress; tmpAddress.setAddress(tmp); *addr = tmpAddress; - if (s->a6.sin6_scope_id) { -#ifndef QT_NO_IPV6IFNAME - char scopeid[IFNAMSIZ]; - if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) { - addr->setScopeId(QLatin1String(scopeid)); - } else -#endif - addr->setScopeId(QString::number(s->a6.sin6_scope_id)); - } + if (s->a6.sin6_scope_id) + addr->setScopeId(QNetworkInterface::interfaceNameFromIndex(s->a6.sin6_scope_id)); } if (port) *port = ntohs(s->a6.sin6_port); @@ -131,21 +124,6 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po } } -// inline on purpose -inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid) -{ - if (scopeid.isEmpty()) - return 0; - - bool ok; - uint id = scopeid.toUInt(&ok); -#ifndef QT_NO_IPV6IFNAME - if (!ok) - id = ::if_nametoindex(scopeid.toLatin1()); -#endif - return id; -} - static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n) { @@ -1207,53 +1185,6 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) return qint64(r); } -#ifdef Q_OS_BLACKBERRY -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const -{ - fd_set fds; - FD_ZERO(&fds); - FD_SET(socketDescriptor, &fds); - - int retval; - QList<QSocketNotifier *> notifiers; - if (selectForRead) { - notifiers << readNotifier; - retval = bb_select(notifiers, socketDescriptor + 1, &fds, 0, timeout); - } else { - notifiers << writeNotifier; - retval = bb_select(notifiers, socketDescriptor + 1, 0, &fds, timeout); - } - - return retval; -} - -int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, - bool *selectForRead, bool *selectForWrite) const -{ - fd_set fdread; - FD_ZERO(&fdread); - if (checkRead) - FD_SET(socketDescriptor, &fdread); - - fd_set fdwrite; - FD_ZERO(&fdwrite); - if (checkWrite) - FD_SET(socketDescriptor, &fdwrite); - - QList<QSocketNotifier *> notifiers; - notifiers << readNotifier << writeNotifier; - int ret = bb_select(notifiers, socketDescriptor + 1, &fdread, &fdwrite, timeout); - - if (ret <= 0) - return ret; - *selectForRead = FD_ISSET(socketDescriptor, &fdread); - *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); - - return ret; -} - -#else // not Q_OS_BLACKBERRY: - int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const { fd_set fds; @@ -1300,6 +1231,5 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c return ret; } -#endif // Q_OS_BLACKBERRY QT_END_NAMESPACE diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 9aed0caa25..1379ed93ba 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -322,12 +322,6 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor) # define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif -// inline on purpose -inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid) -{ - return scopeid.toUInt(); -} - bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) { @@ -657,6 +651,13 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin int tries = 0; do { if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) { + if (value != NOERROR) { + // MSDN says getsockopt with SO_ERROR clears the error, but it's not actually cleared + // and this can affect all subsequent WSAConnect attempts, so clear it now. + const int val = NO_ERROR; + ::setsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, reinterpret_cast<const char*>(&val), sizeof val); + } + if (value == WSAECONNREFUSED) { setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString); socketState = QAbstractSocket::UnconnectedState; |