summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp77
-rw-r--r--src/network/socket/qabstractsocket.h2
-rw-r--r--src/network/socket/qabstractsocket_p.h2
-rw-r--r--src/network/socket/qhttpsocketengine.cpp4
-rw-r--r--src/network/socket/qhttpsocketengine_p.h2
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp74
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp13
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;