summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp70
-rw-r--r--src/network/socket/qabstractsocket.h2
-rw-r--r--src/network/socket/qabstractsocket_p.h2
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp26
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp13
6 files changed, 62 insertions, 55 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 1831d25718..08ccff83fa 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -722,7 +722,7 @@ bool QAbstractSocketPrivate::canReadNotification()
}
}
- // only emit readyRead() when not recursing, and only if there is data available
+ // Only emit readyRead() if there is data available.
bool hasData = newBytes > 0
#ifndef QT_NO_UDPSOCKET
|| (!isBuffered && socketType != QAbstractSocket::TcpSocket && socketEngine && socketEngine->hasPendingDatagrams())
@@ -730,11 +730,8 @@ bool QAbstractSocketPrivate::canReadNotification()
|| (!isBuffered && socketType == QAbstractSocket::TcpSocket && socketEngine)
;
- if (!emittedReadyRead && hasData) {
- QScopedValueRollback<bool> r(emittedReadyRead);
- emittedReadyRead = true;
- emit q->readyRead();
- }
+ if (hasData)
+ emitReadyRead();
// If we were closed as a result of the readyRead() signal,
// return.
@@ -792,12 +789,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 +814,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 +826,7 @@ bool QAbstractSocketPrivate::canWriteNotification()
#endif
}
- return (writeBuffer.size() < tmp);
+ return dataWasWritten;
}
/*! \internal
@@ -852,21 +848,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 +879,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 +889,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 +910,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 +1260,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 +1289,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 +1310,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 +2402,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/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 0fa1d8f96e..5cc5e529fc 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"
@@ -264,7 +265,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..6aff1d25b2 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)
{
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;