diff options
Diffstat (limited to 'src/network/socket')
34 files changed, 436 insertions, 247 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 0f13b1d1b8..13e10e4102 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -387,6 +387,11 @@ (see \l{QAbstractSocket::}{setReadBufferSize()}). This enum value has been introduced in Qt 5.3. + \value PathMtuSocketOption Retrieves the Path Maximum Transmission Unit + (PMTU) value currently known by the IP stack, if any. Some IP stacks also + allow setting the MTU for transmission. + This enum value was introduced in Qt 5.11. + Possible values for \e{TypeOfServiceOption} are: \table @@ -940,7 +945,9 @@ void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port) // DefaultProxy here will raise an error proxyInUse = QNetworkProxy(); } +#endif // !QT_NO_NETWORKPROXY +#if !defined(QT_NO_NETWORKPROXY) || defined(Q_OS_WINRT) /*! \internal @@ -982,7 +989,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host) emit q->stateChanged(state); } -#endif +#endif // !QT_NO_NETWORKPROXY || Q_OS_WINRT /*! \internal @@ -1114,10 +1121,6 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() // (localhost address on BSD or any UDP connect), emit // connected() and return. if ( -#if defined(Q_OS_WINRT) && _MSC_VER >= 1900 - !qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT") ? - socketEngine->connectToHostByName(hostName, port) : -#endif socketEngine->connectToHost(host, port)) { //_q_testConnection(); fetchConnectionParameters(); @@ -1356,15 +1359,29 @@ void QAbstractSocketPrivate::fetchConnectionParameters() } state = QAbstractSocket::ConnectedState; - emit q->stateChanged(state); - emit q->connected(); - #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::fetchConnectionParameters() connection to %s:%i established", host.toString().toLatin1().constData(), port); #endif + emit q->stateChanged(state); + emit q->connected(); } +/*! \internal +*/ +qint64 QAbstractSocketPrivate::skip(qint64 maxSize) +{ + // if we're not connected, return -1 indicating EOF + if (!socketEngine || !socketEngine->isValid() || state != QAbstractSocket::ConnectedState) + return -1; + + // Caller, QIODevice::skip(), has ensured buffer is empty. So, wait + // for more data in buffered mode. + if (isBuffered) + return 0; + + return QIODevicePrivate::skip(maxSize); +} void QAbstractSocketPrivate::pauseSocketNotifiers(QAbstractSocket *socket) { @@ -1696,6 +1713,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, } #endif + // Sync up with error string, which open() shall clear. + d->socketError = UnknownSocketError; if (openMode & QIODevice::Unbuffered) d->isBuffered = false; else if (!d_func()->isBuffered) @@ -1704,6 +1723,7 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, QIODevice::open(openMode); d->readChannelCount = d->writeChannelCount = 0; +#ifndef Q_OS_WINRT d->state = HostLookupState; emit stateChanged(d->state); @@ -1741,6 +1761,10 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, (d->state == ConnectingState || d->state == HostLookupState) ? " (connection in progress)" : ""); #endif +#else // !Q_OS_WINRT + // On WinRT we should always connect by name. Lookup and proxy handling are done by the API. + d->startConnectingByName(hostName); +#endif } /*! \overload @@ -1926,6 +1950,8 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState return false; } + // Sync up with error string, which open() shall clear. + d->socketError = UnknownSocketError; if (d->threadData->hasEventDispatcher()) d->socketEngine->setReceiver(d); @@ -2006,6 +2032,10 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons case ReceiveBufferSizeSocketOption: d_func()->socketEngine->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, value.toInt()); break; + + case PathMtuSocketOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::PathMtuInformation, value.toInt()); + break; } } @@ -2048,6 +2078,10 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) case ReceiveBufferSizeSocketOption: ret = d_func()->socketEngine->option(QAbstractSocketEngine::ReceiveBufferSocketOption); break; + + case PathMtuSocketOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::PathMtuInformation); + break; } if (ret == -1) return QVariant(); diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 875609aa28..6d5e57ac52 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -120,7 +120,8 @@ public: MulticastLoopbackOption, // IP_MULTICAST_LOOPBACK TypeOfServiceOption, //IP_TOS SendBufferSizeSocketOption, //SO_SNDBUF - ReceiveBufferSizeSocketOption //SO_RCVBUF + ReceiveBufferSizeSocketOption, //SO_RCVBUF + PathMtuSocketOption // IP_MTU }; Q_ENUM(SocketOption) enum BindFlag { @@ -154,10 +155,10 @@ public: bool isValid() const; - qint64 bytesAvailable() const Q_DECL_OVERRIDE; - qint64 bytesToWrite() const Q_DECL_OVERRIDE; + qint64 bytesAvailable() const override; + qint64 bytesToWrite() const override; - bool canReadLine() const Q_DECL_OVERRIDE; // ### Qt6: remove me + bool canReadLine() const override; // ### Qt6: remove me quint16 localPort() const; QHostAddress localAddress() const; @@ -182,15 +183,15 @@ public: SocketError error() const; // from QIODevice - void close() Q_DECL_OVERRIDE; - bool isSequential() const Q_DECL_OVERRIDE; - bool atEnd() const Q_DECL_OVERRIDE; // ### Qt6: remove me + void close() override; + bool isSequential() const override; + bool atEnd() const override; // ### Qt6: remove me bool flush(); // for synchronous access virtual bool waitForConnected(int msecs = 30000); - bool waitForReadyRead(int msecs = 30000) Q_DECL_OVERRIDE; - bool waitForBytesWritten(int msecs = 30000) Q_DECL_OVERRIDE; + bool waitForReadyRead(int msecs = 30000) override; + bool waitForBytesWritten(int msecs = 30000) override; virtual bool waitForDisconnected(int msecs = 30000); #ifndef QT_NO_NETWORKPROXY @@ -209,9 +210,9 @@ Q_SIGNALS: #endif protected: - qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 readLineData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 writeData(const char *data, qint64 len) Q_DECL_OVERRIDE; + qint64 readData(char *data, qint64 maxlen) override; + qint64 readLineData(char *data, qint64 maxlen) override; + qint64 writeData(const char *data, qint64 len) override; void setSocketState(SocketState state); void setSocketError(SocketError socketError); @@ -221,7 +222,7 @@ protected: void setPeerAddress(const QHostAddress &address); void setPeerName(const QString &name); - QAbstractSocket(SocketType socketType, QAbstractSocketPrivate &dd, QObject *parent = Q_NULLPTR); + QAbstractSocket(SocketType socketType, QAbstractSocketPrivate &dd, QObject *parent = nullptr); private: Q_DECLARE_PRIVATE(QAbstractSocket) diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 5411133ea9..066a35ff85 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -71,6 +71,9 @@ public: QAbstractSocketPrivate(); virtual ~QAbstractSocketPrivate(); + // from QIODevicePrivate + qint64 skip(qint64 maxSize) override; + // from QAbstractSocketEngineReceiver inline void readNotification() override { canReadNotification(); } inline void writeNotification() override { canWriteNotification(); } @@ -153,6 +156,7 @@ public: QAbstractSocket::SocketType socketType; QAbstractSocket::SocketState state; + // Must be kept in sync with QIODevicePrivate::errorString. QAbstractSocket::SocketError socketError; QAbstractSocket::NetworkLayerProtocol preferredNetworkLayerProtocol; diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index 0cb519ce90..b15dd73c96 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -105,7 +105,8 @@ public: TypeOfServiceOption, ReceivePacketInformation, ReceiveHopLimit, - MaxStreamsSocketOption + MaxStreamsSocketOption, + PathMtuInformation }; enum PacketHeaderOption { diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 899c02fba6..b543ea7981 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -46,7 +46,7 @@ #include "qelapsedtimer.h" #include "qnetworkinterface.h" -#if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP) +#if !defined(QT_NO_NETWORKPROXY) #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -572,18 +572,13 @@ void QHttpSocketEngine::slotSocketReadNotification() } if (d->state == ReadResponseContent) { - char dummybuffer[4096]; - while (d->pendingResponseData) { - int read = d->socket->read(dummybuffer, qMin(sizeof(dummybuffer), (size_t)d->pendingResponseData)); - if (read == 0) - return; - if (read == -1) { - d->socket->disconnectFromHost(); - emitWriteNotification(); - return; - } - d->pendingResponseData -= read; + qint64 skipped = d->socket->skip(d->pendingResponseData); + if (skipped == -1) { + d->socket->disconnectFromHost(); + emitWriteNotification(); + return; } + d->pendingResponseData -= uint(skipped); if (d->pendingResponseData > 0) return; if (d->reply->d_func()->statusCode == 407) @@ -871,4 +866,4 @@ QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(qintptr, QOb QT_END_NAMESPACE -#endif +#endif // !QT_NO_NETWORKPROXY diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 07815a7e51..cb7798694a 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -57,9 +57,11 @@ #include "qnetworkproxy.h" #include "private/qauthenticator_p.h" +QT_REQUIRE_CONFIG(http); + QT_BEGIN_NAMESPACE -#if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP) +#if !defined(QT_NO_NETWORKPROXY) class QTcpSocket; class QHttpNetworkReply; @@ -80,62 +82,62 @@ public: QHttpSocketEngine(QObject *parent = 0); ~QHttpSocketEngine(); - bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) Q_DECL_OVERRIDE; - bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) Q_DECL_OVERRIDE; + bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override; + bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override; void setProxy(const QNetworkProxy &networkProxy); - qintptr socketDescriptor() const Q_DECL_OVERRIDE; + qintptr socketDescriptor() const override; - bool isValid() const Q_DECL_OVERRIDE; + bool isValid() const override; bool connectInternal(); - bool connectToHost(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool connectToHostByName(const QString &name, quint16 port) Q_DECL_OVERRIDE; - bool bind(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool listen() Q_DECL_OVERRIDE; - int accept() Q_DECL_OVERRIDE; - void close() Q_DECL_OVERRIDE; + bool connectToHost(const QHostAddress &address, quint16 port) override; + bool connectToHostByName(const QString &name, quint16 port) override; + bool bind(const QHostAddress &address, quint16 port) override; + bool listen() override; + int accept() override; + void close() override; - qint64 bytesAvailable() const Q_DECL_OVERRIDE; + qint64 bytesAvailable() const override; - qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; + qint64 read(char *data, qint64 maxlen) override; + qint64 write(const char *data, qint64 len) override; #ifndef QT_NO_UDPSOCKET #ifndef QT_NO_NETWORKINTERFACE bool joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &interface) Q_DECL_OVERRIDE; + const QNetworkInterface &interface) override; bool leaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &interface) Q_DECL_OVERRIDE; - QNetworkInterface multicastInterface() const Q_DECL_OVERRIDE; - bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; + const QNetworkInterface &interface) override; + QNetworkInterface multicastInterface() const override; + bool setMulticastInterface(const QNetworkInterface &iface) override; #endif // QT_NO_NETWORKINTERFACE - bool hasPendingDatagrams() const Q_DECL_OVERRIDE; - qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; + bool hasPendingDatagrams() const override; + qint64 pendingDatagramSize() const override; #endif // QT_NO_UDPSOCKET qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, - PacketHeaderOptions) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; - qint64 bytesToWrite() const Q_DECL_OVERRIDE; + PacketHeaderOptions) override; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override; + qint64 bytesToWrite() const override; - int option(SocketOption option) const Q_DECL_OVERRIDE; - bool setOption(SocketOption option, int value) Q_DECL_OVERRIDE; + int option(SocketOption option) const override; + bool setOption(SocketOption option, int value) override; - bool waitForRead(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; - bool waitForWrite(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; + bool waitForRead(int msecs = 30000, bool *timedOut = 0) override; + bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override; bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, - int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; + int msecs = 30000, bool *timedOut = 0) override; - bool isReadNotificationEnabled() const Q_DECL_OVERRIDE; - void setReadNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isWriteNotificationEnabled() const Q_DECL_OVERRIDE; - void setWriteNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isExceptionNotificationEnabled() const Q_DECL_OVERRIDE; - void setExceptionNotificationEnabled(bool enable) Q_DECL_OVERRIDE; + bool isReadNotificationEnabled() const override; + void setReadNotificationEnabled(bool enable) override; + bool isWriteNotificationEnabled() const override; + void setWriteNotificationEnabled(bool enable) override; + bool isExceptionNotificationEnabled() const override; + void setExceptionNotificationEnabled(bool enable) override; public slots: void slotSocketConnected(); @@ -190,8 +192,8 @@ class Q_AUTOTEST_EXPORT QHttpSocketEngineHandler : public QSocketEngineHandler { public: virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, - const QNetworkProxy &, QObject *parent) Q_DECL_OVERRIDE; - virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescripter, QObject *parent) Q_DECL_OVERRIDE; + const QNetworkProxy &, QObject *parent) override; + virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescripter, QObject *parent) override; }; #endif diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 3fcec954e7..a9789b7d04 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -41,6 +41,10 @@ #include "qlocalserver_p.h" #include "qlocalsocket.h" +#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP) +#include <QtCore/qt_windows.h> +#endif + QT_BEGIN_NAMESPACE /*! @@ -181,6 +185,42 @@ QLocalServer::SocketOptions QLocalServer::socketOptions() const } /*! + \since 5.10 + Returns the native socket descriptor the server uses to listen + for incoming instructions, or -1 if the server is not listening. + + The type of the descriptor depends on the platform: + \list + \li On Windows, the returned value is a + \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx} + {Winsock 2 Socket Handle}. + + \li With WinRT and on INTEGRITY, the returned value is the + QTcpServer socket descriptor and the type is defined by + \l{QTcpServer::socketDescriptor}{socketDescriptor}. + + \li On all other UNIX-like operating systems, the type is + a file descriptor representing a listening socket. + \endlist + + \sa listen() +*/ +qintptr QLocalServer::socketDescriptor() const +{ + Q_D(const QLocalServer); + if (!isListening()) + return -1; +#if defined(QT_LOCALSOCKET_TCP) + return d->tcpServer.socketDescriptor(); +#elif defined(Q_OS_WIN) + const auto handle = d->connectionEventNotifier->handle(); + return handle != INVALID_HANDLE_VALUE ? qintptr(handle) : -1; +#else + return d->socketNotifier->socket(); +#endif +} + +/*! Stop listening for incoming connections. Existing connections are not affected, but any new connections will be refused. diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h index 9bd2990389..211aa94d85 100644 --- a/src/network/socket/qlocalserver.h +++ b/src/network/socket/qlocalserver.h @@ -71,7 +71,7 @@ public: Q_DECLARE_FLAGS(SocketOptions, SocketOption) Q_FLAG(SocketOptions) - explicit QLocalServer(QObject *parent = Q_NULLPTR); + explicit QLocalServer(QObject *parent = nullptr); ~QLocalServer(); void close(); @@ -87,11 +87,13 @@ public: static bool removeServer(const QString &name); QAbstractSocket::SocketError serverError() const; void setMaxPendingConnections(int numConnections); - bool waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR); + bool waitForNewConnection(int msec = 0, bool *timedOut = nullptr); void setSocketOptions(SocketOptions options); SocketOptions socketOptions() const; + qintptr socketDescriptor() const; + protected: virtual void incomingConnection(quintptr socketDescriptor); diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 516fac681c..9547ec5b88 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -297,7 +297,7 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut) } errno = EBADF; - // FALLTHROUGH + Q_FALLTHROUGH(); case -1: setError(QLatin1String("QLocalServer::waitForNewConnection")); closeServer(); diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 8cb3449343..ced923ced1 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -225,7 +225,7 @@ bool QLocalServerPrivate::addListener() void QLocalServerPrivate::setError(const QString &function) { int windowsError = GetLastError(); - errorString = QString::fromLatin1("%1: %2").arg(function).arg(qt_error_string(windowsError)); + errorString = QString::fromLatin1("%1: %2").arg(function, qt_error_string(windowsError)); error = QAbstractSocket::UnknownSocketError; } diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp index 090a9e98c6..6fec2fdbd2 100644 --- a/src/network/socket/qlocalsocket.cpp +++ b/src/network/socket/qlocalsocket.cpp @@ -126,6 +126,20 @@ QT_BEGIN_NAMESPACE The socket descriptor is not available when QLocalSocket is in UnconnectedState. + The type of the descriptor depends on the platform: + + \list + \li On Windows, the returned value is a + \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx} + {Winsock 2 Socket Handle}. + + \li With WinRT and on INTEGRITY, the returned value is the + QTcpSocket socket descriptor and the type is defined by + \l{QTcpSocket::socketDescriptor}{socketDescriptor}. + + \li On all other UNIX-like operating systems, the type is + a file descriptor representing a socket. + \endlist \sa setSocketDescriptor() */ diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index 9905d3a86c..1876a6ac0d 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -79,7 +79,7 @@ public: ClosingState = QAbstractSocket::ClosingState }; - QLocalSocket(QObject *parent = Q_NULLPTR); + QLocalSocket(QObject *parent = nullptr); ~QLocalSocket(); void connectToServer(OpenMode openMode = ReadWrite); @@ -91,12 +91,12 @@ public: QString fullServerName() const; void abort(); - virtual bool isSequential() const Q_DECL_OVERRIDE; - virtual qint64 bytesAvailable() const Q_DECL_OVERRIDE; - virtual qint64 bytesToWrite() const Q_DECL_OVERRIDE; - virtual bool canReadLine() const Q_DECL_OVERRIDE; - virtual bool open(OpenMode openMode = ReadWrite) Q_DECL_OVERRIDE; - virtual void close() Q_DECL_OVERRIDE; + virtual bool isSequential() const override; + virtual qint64 bytesAvailable() const override; + virtual qint64 bytesToWrite() const override; + virtual bool canReadLine() const override; + virtual bool open(OpenMode openMode = ReadWrite) override; + virtual void close() override; LocalSocketError error() const; bool flush(); bool isValid() const; @@ -109,10 +109,10 @@ public: qintptr socketDescriptor() const; LocalSocketState state() const; - bool waitForBytesWritten(int msecs = 30000) Q_DECL_OVERRIDE; + bool waitForBytesWritten(int msecs = 30000) override; bool waitForConnected(int msecs = 30000); bool waitForDisconnected(int msecs = 30000); - bool waitForReadyRead(int msecs = 30000) Q_DECL_OVERRIDE; + bool waitForReadyRead(int msecs = 30000) override; Q_SIGNALS: void connected(); @@ -121,8 +121,8 @@ Q_SIGNALS: void stateChanged(QLocalSocket::LocalSocketState socketState); protected: - virtual qint64 readData(char*, qint64) Q_DECL_OVERRIDE; - virtual qint64 writeData(const char*, qint64) Q_DECL_OVERRIDE; + virtual qint64 readData(char*, qint64) override; + virtual qint64 writeData(const char*, qint64) override; private: Q_DISABLE_COPY(QLocalSocket) diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index eb59af5577..8b72da397f 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -120,6 +120,7 @@ public: void init(); #if defined(QT_LOCALSOCKET_TCP) + qint64 skip(qint64 maxSize) override; QLocalUnixSocket* tcpSocket; bool ownsTcpSocket; void setSocket(QLocalUnixSocket*); @@ -139,6 +140,7 @@ public: QWindowsPipeReader *pipeReader; QLocalSocket::LocalSocketError error; #else + qint64 skip(qint64 maxSize) override; QLocalUnixSocket unixSocket; QString generateErrorString(QLocalSocket::LocalSocketError, const QString &function) const; void errorOccurred(QLocalSocket::LocalSocketError, const QString &function); diff --git a/src/network/socket/qlocalsocket_tcp.cpp b/src/network/socket/qlocalsocket_tcp.cpp index 379cdd096d..41e5b47627 100644 --- a/src/network/socket/qlocalsocket_tcp.cpp +++ b/src/network/socket/qlocalsocket_tcp.cpp @@ -83,6 +83,11 @@ void QLocalSocketPrivate::setSocket(QLocalUnixSocket* socket) tcpSocket->setParent(q); } +qint64 QLocalSocketPrivate::skip(qint64 maxSize) +{ + return tcpSocket->skip(maxSize); +} + void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError) { Q_Q(QLocalSocket); diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index c1d79e8137..d1df26d9f1 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -88,6 +88,11 @@ void QLocalSocketPrivate::init() unixSocket.setParent(q); } +qint64 QLocalSocketPrivate::skip(qint64 maxSize) +{ + return unixSocket.skip(maxSize); +} + void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError) { Q_Q(QLocalSocket); diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 312c934632..ae94cb9d51 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -183,10 +183,8 @@ void QLocalSocket::connectToServer(OpenMode openMode) } // we have a valid handle - if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode)) { - d->handle = localSocket; + if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode)) emit connected(); - } } // This is reading from the buffer diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 3f7c0d94e1..8947a7ee8a 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -1113,7 +1113,7 @@ bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWri int msecs, bool *timedOut) { Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false); Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(), QAbstractSocket::UnconnectedState, false); @@ -1162,7 +1162,8 @@ bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWri return ret > 0; } -/*! +#if 0 // currently unused +/* Returns the size of the operating system's socket receive buffer. Depending on the operating system, this size may be different from what has been set earlier with @@ -1174,7 +1175,7 @@ qint64 QNativeSocketEngine::receiveBufferSize() const return option(ReceiveBufferSocketOption); } -/*! +/* Sets the size of the operating system receive buffer to \a size. For clients, this should be set before connectToHost() is called; @@ -1195,7 +1196,7 @@ void QNativeSocketEngine::setReceiveBufferSize(qint64 size) setOption(ReceiveBufferSocketOption, size); } -/*! +/* Returns the size of the operating system send buffer. Depending on the operating system, this size may be different from what has been set earlier with setSendBufferSize(). @@ -1206,7 +1207,7 @@ qint64 QNativeSocketEngine::sendBufferSize() const return option(SendBufferSocketOption); } -/*! +/* Sets the size of the operating system send buffer to \a size. The operating system send buffer size effectively limits how much @@ -1220,7 +1221,7 @@ void QNativeSocketEngine::setSendBufferSize(qint64 size) Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), Q_VOID); setOption(SendBufferSocketOption, size); } - +#endif /*! Sets the option \a option to the value \a value. diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 08e72072ef..aa61b74823 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -128,65 +128,67 @@ public: QNativeSocketEngine(QObject *parent = 0); ~QNativeSocketEngine(); - bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) Q_DECL_OVERRIDE; - bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) Q_DECL_OVERRIDE; + bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override; + bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override; - qintptr socketDescriptor() const Q_DECL_OVERRIDE; + qintptr socketDescriptor() const override; - bool isValid() const Q_DECL_OVERRIDE; + bool isValid() const override; - bool connectToHost(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool connectToHostByName(const QString &name, quint16 port) Q_DECL_OVERRIDE; - bool bind(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool listen() Q_DECL_OVERRIDE; - int accept() Q_DECL_OVERRIDE; - void close() Q_DECL_OVERRIDE; + bool connectToHost(const QHostAddress &address, quint16 port) override; + bool connectToHostByName(const QString &name, quint16 port) override; + bool bind(const QHostAddress &address, quint16 port) override; + bool listen() override; + int accept() override; + void close() override; - qint64 bytesAvailable() const Q_DECL_OVERRIDE; + qint64 bytesAvailable() const override; - qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; + qint64 read(char *data, qint64 maxlen) override; + qint64 write(const char *data, qint64 len) override; #ifndef QT_NO_UDPSOCKET #ifndef QT_NO_NETWORKINTERFACE bool joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface) Q_DECL_OVERRIDE; + const QNetworkInterface &iface) override; bool leaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface) Q_DECL_OVERRIDE; - QNetworkInterface multicastInterface() const Q_DECL_OVERRIDE; - bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; + const QNetworkInterface &iface) override; + QNetworkInterface multicastInterface() const override; + bool setMulticastInterface(const QNetworkInterface &iface) override; #endif - bool hasPendingDatagrams() const Q_DECL_OVERRIDE; - qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; + bool hasPendingDatagrams() const override; + qint64 pendingDatagramSize() const override; #endif // QT_NO_UDPSOCKET qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, - PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; - qint64 bytesToWrite() const Q_DECL_OVERRIDE; + PacketHeaderOptions = WantNone) override; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override; + qint64 bytesToWrite() const override; +#if 0 // currently unused qint64 receiveBufferSize() const; void setReceiveBufferSize(qint64 bufferSize); qint64 sendBufferSize() const; void setSendBufferSize(qint64 bufferSize); +#endif - int option(SocketOption option) const Q_DECL_OVERRIDE; - bool setOption(SocketOption option, int value) Q_DECL_OVERRIDE; + int option(SocketOption option) const override; + bool setOption(SocketOption option, int value) override; - bool waitForRead(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; - bool waitForWrite(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; + bool waitForRead(int msecs = 30000, bool *timedOut = 0) override; + bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override; bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, - int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; - - bool isReadNotificationEnabled() const Q_DECL_OVERRIDE; - void setReadNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isWriteNotificationEnabled() const Q_DECL_OVERRIDE; - void setWriteNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isExceptionNotificationEnabled() const Q_DECL_OVERRIDE; - void setExceptionNotificationEnabled(bool enable) Q_DECL_OVERRIDE; + int msecs = 30000, bool *timedOut = 0) override; + + bool isReadNotificationEnabled() const override; + void setReadNotificationEnabled(bool enable) override; + bool isWriteNotificationEnabled() const override; + void setWriteNotificationEnabled(bool enable) override; + bool isExceptionNotificationEnabled() const override; + void setExceptionNotificationEnabled(bool enable) override; public Q_SLOTS: // non-virtual override; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 3cf65b3553..b380b0f7d6 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -226,6 +226,20 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, #endif } break; + + case QNativeSocketEngine::PathMtuInformation: + if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { +#ifdef IPV6_MTU + level = IPPROTO_IPV6; + n = IPV6_MTU; +#endif + } else { +#ifdef IP_MTU + level = IPPROTO_IP; + n = IP_MTU; +#endif + } + break; } } @@ -331,6 +345,20 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co return -1; } + case QNativeSocketEngine::PathMtuInformation: +#if defined(IPV6_PATHMTU) && !defined(IPV6_MTU) + // Prefer IPV6_MTU (handled by convertToLevelAndOption), if available + // (Linux); fall back to IPV6_PATHMTU otherwise (FreeBSD): + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + ip6_mtuinfo mtuinfo; + QT_SOCKOPTLEN_T len = sizeof(mtuinfo); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0) + return int(mtuinfo.ip6m_mtu); + return -1; + } +#endif + break; + default: break; } @@ -420,6 +448,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt } #endif + if (n == -1) + return false; return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; } @@ -670,8 +700,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = interface.index(); - } else - if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = &mreq4; @@ -830,18 +859,10 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const { - // Create a sockaddr struct and reset its port number. - qt_sockaddr storage; - QT_SOCKLEN_T storageSize = sizeof(storage); - memset(&storage, 0, storageSize); - - // Peek 0 bytes into the next message. The size of the message may - // well be 0, so we can't check recvfrom's return value. + // Peek 1 bytes into the next message. ssize_t readBytes; - do { - char c; - readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize); - } while (readBytes == -1 && errno == EINTR); + char c; + EINTR_LOOP(readBytes, ::recv(socketDescriptor, &c, 1, MSG_PEEK)); // If there's no error, or if our buffer was too small, there must be a // pending datagram. @@ -856,24 +877,57 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const { - QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192); ssize_t recvResult = -1; +#ifdef Q_OS_LINUX + // Linux can return the actual datagram size if we use MSG_TRUNC + char c; + EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC)); +#elif defined(SO_NREAD) + // macOS can return the actual datagram size if we use SO_NREAD + int value; + socklen_t valuelen = sizeof(value); + recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen); + if (recvResult != -1) + recvResult = value; +#else + // We need to grow the buffer to fit the entire datagram. + // We start at 1500 bytes (the MTU for Ethernet V2), which should catch + // almost all uses (effective MTU for UDP under IPv4 is 1468), except + // for localhost datagrams and those reassembled by the IP layer. + char udpMessagePeekBuffer[1500]; + struct msghdr msg; + struct iovec vec; + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + vec.iov_base = udpMessagePeekBuffer; + vec.iov_len = sizeof(udpMessagePeekBuffer); for (;;) { // the data written to udpMessagePeekBuffer is discarded, so // this function is still reentrant although it might not look // so. - recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(), - udpMessagePeekBuffer.size(), MSG_PEEK); + recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK); if (recvResult == -1 && errno == EINTR) continue; - if (recvResult != (ssize_t) udpMessagePeekBuffer.size()) + // was the result truncated? + if ((msg.msg_flags & MSG_TRUNC) == 0) break; - udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2); + // grow by 16 times + msg.msg_iovlen *= 16; + if (msg.msg_iov != &vec) + delete[] msg.msg_iov; + msg.msg_iov = new struct iovec[msg.msg_iovlen]; + std::fill_n(msg.msg_iov, msg.msg_iovlen, vec); } + if (msg.msg_iov != &vec) + delete[] msg.msg_iov; +#endif + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult); #endif diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index a1f7f36700..c303f01648 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -209,7 +209,7 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n) { - n = 0; + n = -1; level = SOL_SOCKET; // default switch (opt) { @@ -281,6 +281,9 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, n = IP_HOPLIMIT; } break; + + case QAbstractSocketEngine::PathMtuInformation: + break; // not supported on Windows } } @@ -471,9 +474,11 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co QT_SOCKOPTLEN_T len = sizeof(v); convertToLevelAndOption(opt, socketProtocol, level, n); - if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0) - return v; - WS_ERROR_DEBUG(WSAGetLastError()); + if (n != -1) { + if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0) + return v; + WS_ERROR_DEBUG(WSAGetLastError()); + } return -1; } @@ -491,9 +496,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt switch (opt) { case QNativeSocketEngine::SendBufferSocketOption: // see QTBUG-30478 SO_SNDBUF should not be used on Vista or later - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - return false; - break; + return false; case QNativeSocketEngine::NonBlockingSocketOption: { unsigned long buf = v; @@ -516,6 +519,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt int n, level; convertToLevelAndOption(opt, socketProtocol, level, n); + if (n == -1) + return false; if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) { WS_ERROR_DEBUG(WSAGetLastError()); return false; @@ -571,7 +576,6 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() DWORD ipv6only = 0; QT_SOCKOPTLEN_T optlen = sizeof(ipv6only); if (localAddress == QHostAddress::AnyIPv6 - && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0 && !getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, &optlen )) { if (!ipv6only) { socketProtocol = QAbstractSocket::AnyIPProtocol; @@ -632,10 +636,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin if ((socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) && address.toIPv4Address()) { //IPV6_V6ONLY option must be cleared to connect to a V4 mapped address - if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) { - DWORD ipv6only = 0; - ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); - } + DWORD ipv6only = 0; + ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); } forever { @@ -944,9 +946,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); mreq6.ipv6mr_interface = iface.index(); - } else - - if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { level = IPPROTO_IP; sockOpt = how4; sockArg = reinterpret_cast<char *>(&mreq4); @@ -1148,10 +1148,10 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const DWORD bufferCount = 5; WSABUF * buf = 0; for (;;) { - // the data written to udpMessagePeekBuffer is discarded, so - // this function is still reentrant although it might not look - // so. - static char udpMessagePeekBuffer[8192]; + // We start at 1500 bytes (the MTU for Ethernet V2), which should catch + // almost all uses (effective MTU for UDP under IPv4 is 1468), except + // for localhost datagrams and those reassembled by the IP layer. + char udpMessagePeekBuffer[1500]; buf = new WSABUF[bufferCount]; for (DWORD i=0; i<bufferCount; i++) { @@ -1321,6 +1321,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.namelen); + uint oldIfIndex = 0; + bool mustSetIpv6MulticastIf = false; + if (msg.namelen == sizeof(aa.a6)) { // sending IPv6 if (header.hopLimit != -1) { @@ -1332,7 +1335,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr) + WSA_CMSG_SPACE(sizeof(int))); } - if (header.ifindex != 0 || !header.senderAddress.isNull()) { + if (!header.senderAddress.isNull()) { struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr)); memset(data, 0, sizeof(*data)); msg.Control.len += WSA_CMSG_SPACE(sizeof(*data)); @@ -1345,6 +1348,21 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr) + WSA_CMSG_SPACE(sizeof(*data))); + } else if (header.ifindex != 0) { + // Unlike other operating systems, setting the interface index in the in6_pktinfo + // structure above and leaving the ipi6_addr set to :: will cause the packets to be + // sent with source address ::. So we have to use IPV6_MULTICAST_IF, which MSDN is + // quite clear that "This option does not change the default interface for receiving + // IPv6 multicast traffic." + QT_SOCKOPTLEN_T len = sizeof(oldIfIndex); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<char *>(&oldIfIndex), &len) == -1 + || ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<const char *>(&header.ifindex), sizeof(header.ifindex)) == -1) { + setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + return -1; + } + mustSetIpv6MulticastIf = true; } } else { // sending IPv4 @@ -1398,6 +1416,12 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l ret = qint64(bytesSent); } + if (mustSetIpv6MulticastIf) { + // undo what we did above + ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, + reinterpret_cast<char *>(&oldIfIndex), sizeof(oldIfIndex)); + } + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), len, diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index b7d7042923..9df5f0c500 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1340,7 +1340,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , closingDown(false) , socketDescriptor(-1) , worker(new SocketEngineWorker(this)) - , sslSocket(Q_NULLPTR) + , sslSocket(nullptr) , connectionToken( { -1 } ) { } @@ -1514,6 +1514,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) case QAbstractSocketEngine::MulticastLoopbackOption: case QAbstractSocketEngine::TypeOfServiceOption: case QAbstractSocketEngine::MaxStreamsSocketOption: + case QAbstractSocketEngine::PathMtuInformation: default: return -1; } @@ -1573,6 +1574,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o case QAbstractSocketEngine::MulticastLoopbackOption: case QAbstractSocketEngine::TypeOfServiceOption: case QAbstractSocketEngine::MaxStreamsSocketOption: + case QAbstractSocketEngine::PathMtuInformation: default: return false; } diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h index 73d7ec2e77..e038352352 100644 --- a/src/network/socket/qnet_unix_p.h +++ b/src/network/socket/qnet_unix_p.h @@ -78,7 +78,6 @@ QT_BEGIN_NAMESPACE # define QT_SOCKOPTLEN_T QT_SOCKLEN_T #endif -// UnixWare 7 redefines socket -> _socket static inline int qt_safe_socket(int domain, int type, int protocol, int flags = 0) { Q_ASSERT((flags & ~O_NONBLOCK) == 0); @@ -105,7 +104,6 @@ static inline int qt_safe_socket(int domain, int type, int protocol, int flags = #endif } -// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags = 0) { Q_ASSERT((flags & ~O_NONBLOCK) == 0); @@ -137,7 +135,6 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add #endif } -// UnixWare 7 redefines listen -> _listen static inline int qt_safe_listen(int s, int backlog) { return ::listen(s, backlog); @@ -174,16 +171,6 @@ static inline int qt_safe_ioctl(int sockfd, unsigned long request, T arg) #endif } -// VxWorks' headers do not specify any const modifiers -static inline in_addr_t qt_safe_inet_addr(const char *cp) -{ -#ifdef Q_OS_VXWORKS - return ::inet_addr((char *) cp); -#else - return ::inet_addr(cp); -#endif -} - static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags) { #ifdef MSG_NOSIGNAL diff --git a/src/network/socket/qsctpserver.h b/src/network/socket/qsctpserver.h index 1afdab28a0..b678ba053d 100644 --- a/src/network/socket/qsctpserver.h +++ b/src/network/socket/qsctpserver.h @@ -63,7 +63,7 @@ public: QSctpSocket *nextPendingDatagramConnection(); protected: - void incomingConnection(qintptr handle) Q_DECL_OVERRIDE; + void incomingConnection(qintptr handle) override; private: Q_DISABLE_COPY(QSctpServer) diff --git a/src/network/socket/qsctpserver_p.h b/src/network/socket/qsctpserver_p.h index 274939fc3d..8816cc150e 100644 --- a/src/network/socket/qsctpserver_p.h +++ b/src/network/socket/qsctpserver_p.h @@ -66,7 +66,7 @@ public: int maximumChannelCount; - void configureCreatedSocket() Q_DECL_OVERRIDE; + void configureCreatedSocket() override; }; #endif // QT_NO_SCTP diff --git a/src/network/socket/qsctpsocket.h b/src/network/socket/qsctpsocket.h index 9bed1890ff..5288da6129 100644 --- a/src/network/socket/qsctpsocket.h +++ b/src/network/socket/qsctpsocket.h @@ -56,8 +56,8 @@ public: explicit QSctpSocket(QObject *parent = nullptr); virtual ~QSctpSocket(); - void close() Q_DECL_OVERRIDE; - void disconnectFromHost() Q_DECL_OVERRIDE; + void close() override; + void disconnectFromHost() override; void setMaximumChannelCount(int count); int maximumChannelCount() const; @@ -67,8 +67,8 @@ public: bool writeDatagram(const QNetworkDatagram &datagram); protected: - qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 readLineData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; + qint64 readData(char *data, qint64 maxlen) override; + qint64 readLineData(char *data, qint64 maxlen) override; private: Q_DISABLE_COPY(QSctpSocket) diff --git a/src/network/socket/qsctpsocket_p.h b/src/network/socket/qsctpsocket_p.h index 3f765ebed9..8f9413cb47 100644 --- a/src/network/socket/qsctpsocket_p.h +++ b/src/network/socket/qsctpsocket_p.h @@ -70,8 +70,8 @@ public: QSctpSocketPrivate(); virtual ~QSctpSocketPrivate(); - bool canReadNotification() Q_DECL_OVERRIDE; - bool writeToSocket() Q_DECL_OVERRIDE; + bool canReadNotification() override; + bool writeToSocket() override; QByteArray incomingDatagram; int maximumChannelCount; @@ -80,7 +80,7 @@ public: QVector<IpHeaderList> readHeaders; QVector<IpHeaderList> writeHeaders; - void configureCreatedSocket() Q_DECL_OVERRIDE; + void configureCreatedSocket() override; }; #endif // QT_NO_SCTP diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index fa5f198bf2..a07ea65046 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -320,7 +320,7 @@ public: QSocks5BindData *retrieve(qintptr socketDescriptor); protected: - void timerEvent(QTimerEvent * event) Q_DECL_OVERRIDE; + void timerEvent(QTimerEvent * event) override; QMutex mutex; int sweepTimerId; diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h index b248554ae5..1942eff4ca 100644 --- a/src/network/socket/qsocks5socketengine_p.h +++ b/src/network/socket/qsocks5socketengine_p.h @@ -68,62 +68,62 @@ public: QSocks5SocketEngine(QObject *parent = 0); ~QSocks5SocketEngine(); - bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) Q_DECL_OVERRIDE; - bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) Q_DECL_OVERRIDE; + bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) override; + bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) override; void setProxy(const QNetworkProxy &networkProxy); - qintptr socketDescriptor() const Q_DECL_OVERRIDE; + qintptr socketDescriptor() const override; - bool isValid() const Q_DECL_OVERRIDE; + bool isValid() const override; bool connectInternal(); - bool connectToHost(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool connectToHostByName(const QString &name, quint16 port) Q_DECL_OVERRIDE; - bool bind(const QHostAddress &address, quint16 port) Q_DECL_OVERRIDE; - bool listen() Q_DECL_OVERRIDE; - int accept() Q_DECL_OVERRIDE; - void close() Q_DECL_OVERRIDE; + bool connectToHost(const QHostAddress &address, quint16 port) override; + bool connectToHostByName(const QString &name, quint16 port) override; + bool bind(const QHostAddress &address, quint16 port) override; + bool listen() override; + int accept() override; + void close() override; - qint64 bytesAvailable() const Q_DECL_OVERRIDE; + qint64 bytesAvailable() const override; - qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; - qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; + qint64 read(char *data, qint64 maxlen) override; + qint64 write(const char *data, qint64 len) override; #ifndef QT_NO_UDPSOCKET #ifndef QT_NO_NETWORKINTERFACE bool joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &interface) Q_DECL_OVERRIDE; + const QNetworkInterface &interface) override; bool leaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &interface) Q_DECL_OVERRIDE; - QNetworkInterface multicastInterface() const Q_DECL_OVERRIDE; - bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; + const QNetworkInterface &interface) override; + QNetworkInterface multicastInterface() const override; + bool setMulticastInterface(const QNetworkInterface &iface) override; #endif // QT_NO_NETWORKINTERFACE - bool hasPendingDatagrams() const Q_DECL_OVERRIDE; - qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; + bool hasPendingDatagrams() const override; + qint64 pendingDatagramSize() const override; #endif // QT_NO_UDPSOCKET qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, - PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; - qint64 bytesToWrite() const Q_DECL_OVERRIDE; + PacketHeaderOptions = WantNone) override; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) override; + qint64 bytesToWrite() const override; - int option(SocketOption option) const Q_DECL_OVERRIDE; - bool setOption(SocketOption option, int value) Q_DECL_OVERRIDE; + int option(SocketOption option) const override; + bool setOption(SocketOption option, int value) override; - bool waitForRead(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; - bool waitForWrite(int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; + bool waitForRead(int msecs = 30000, bool *timedOut = 0) override; + bool waitForWrite(int msecs = 30000, bool *timedOut = 0) override; bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, - int msecs = 30000, bool *timedOut = 0) Q_DECL_OVERRIDE; + int msecs = 30000, bool *timedOut = 0) override; - bool isReadNotificationEnabled() const Q_DECL_OVERRIDE; - void setReadNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isWriteNotificationEnabled() const Q_DECL_OVERRIDE; - void setWriteNotificationEnabled(bool enable) Q_DECL_OVERRIDE; - bool isExceptionNotificationEnabled() const Q_DECL_OVERRIDE; - void setExceptionNotificationEnabled(bool enable) Q_DECL_OVERRIDE; + bool isReadNotificationEnabled() const override; + void setReadNotificationEnabled(bool enable) override; + bool isWriteNotificationEnabled() const override; + void setWriteNotificationEnabled(bool enable) override; + bool isExceptionNotificationEnabled() const override; + void setExceptionNotificationEnabled(bool enable) override; private: Q_DECLARE_PRIVATE(QSocks5SocketEngine) @@ -166,11 +166,11 @@ class QSocks5PasswordAuthenticator : public QSocks5Authenticator { public: QSocks5PasswordAuthenticator(const QString &userName, const QString &password); - char methodId() Q_DECL_OVERRIDE; - bool beginAuthenticate(QTcpSocket *socket, bool *completed) Q_DECL_OVERRIDE; - bool continueAuthenticate(QTcpSocket *socket, bool *completed) Q_DECL_OVERRIDE; + char methodId() override; + bool beginAuthenticate(QTcpSocket *socket, bool *completed) override; + bool continueAuthenticate(QTcpSocket *socket, bool *completed) override; - QString errorString() Q_DECL_OVERRIDE; + QString errorString() override; private: QString userName; @@ -287,8 +287,8 @@ class Q_AUTOTEST_EXPORT QSocks5SocketEngineHandler : public QSocketEngineHandler { public: virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, - const QNetworkProxy &, QObject *parent) Q_DECL_OVERRIDE; - virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent) Q_DECL_OVERRIDE; + const QNetworkProxy &, QObject *parent) override; + virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent) override; }; QT_END_NAMESPACE diff --git a/src/network/socket/qtcpserver.h b/src/network/socket/qtcpserver.h index 192cbce54c..37df12919f 100644 --- a/src/network/socket/qtcpserver.h +++ b/src/network/socket/qtcpserver.h @@ -58,7 +58,7 @@ class Q_NETWORK_EXPORT QTcpServer : public QObject { Q_OBJECT public: - explicit QTcpServer(QObject *parent = Q_NULLPTR); + explicit QTcpServer(QObject *parent = nullptr); virtual ~QTcpServer(); bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0); @@ -75,7 +75,7 @@ public: qintptr socketDescriptor() const; bool setSocketDescriptor(qintptr socketDescriptor); - bool waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR); + bool waitForNewConnection(int msec = 0, bool *timedOut = nullptr); virtual bool hasPendingConnections() const; virtual QTcpSocket *nextPendingConnection(); @@ -95,7 +95,7 @@ protected: void addPendingConnection(QTcpSocket* socket); QTcpServer(QAbstractSocket::SocketType socketType, QTcpServerPrivate &dd, - QObject *parent = Q_NULLPTR); + QObject *parent = nullptr); Q_SIGNALS: void newConnection(); diff --git a/src/network/socket/qtcpserver_p.h b/src/network/socket/qtcpserver_p.h index 71dc4d985f..6ee8c5f0b1 100644 --- a/src/network/socket/qtcpserver_p.h +++ b/src/network/socket/qtcpserver_p.h @@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE -class QTcpServerPrivate : public QObjectPrivate, public QAbstractSocketEngineReceiver +class Q_NETWORK_EXPORT QTcpServerPrivate : public QObjectPrivate, + public QAbstractSocketEngineReceiver { Q_DECLARE_PUBLIC(QTcpServer) public: @@ -92,13 +93,13 @@ public: virtual void configureCreatedSocket(); // from QAbstractSocketEngineReceiver - void readNotification() Q_DECL_OVERRIDE; - void closeNotification() Q_DECL_OVERRIDE { readNotification(); } - void writeNotification() Q_DECL_OVERRIDE {} - void exceptionNotification() Q_DECL_OVERRIDE {} - void connectionNotification() Q_DECL_OVERRIDE {} + void readNotification() override; + void closeNotification() override { readNotification(); } + void writeNotification() override {} + void exceptionNotification() override {} + void connectionNotification() override {} #ifndef QT_NO_NETWORKPROXY - void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *) Q_DECL_OVERRIDE {} + void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *) override {} #endif }; diff --git a/src/network/socket/qtcpsocket.h b/src/network/socket/qtcpsocket.h index 3c3e3b69fd..b2c8bcc884 100644 --- a/src/network/socket/qtcpsocket.h +++ b/src/network/socket/qtcpsocket.h @@ -53,13 +53,13 @@ class Q_NETWORK_EXPORT QTcpSocket : public QAbstractSocket { Q_OBJECT public: - explicit QTcpSocket(QObject *parent = Q_NULLPTR); + explicit QTcpSocket(QObject *parent = nullptr); virtual ~QTcpSocket(); protected: - QTcpSocket(QTcpSocketPrivate &dd, QObject *parent = Q_NULLPTR); + QTcpSocket(QTcpSocketPrivate &dd, QObject *parent = nullptr); QTcpSocket(QAbstractSocket::SocketType socketType, QTcpSocketPrivate &dd, - QObject *parent = Q_NULLPTR); + QObject *parent = nullptr); private: Q_DISABLE_COPY(QTcpSocket) diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 79629a07f2..85c4f4cbfd 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -185,6 +185,10 @@ QUdpSocket::~QUdpSocket() This function returns \c true if successful; otherwise it returns \c false and sets the socket error accordingly. + \note Joining IPv6 multicast groups without an interface selection is not + supported in all operating systems. Consider using the overload where the + interface is specified. + \sa leaveMulticastGroup() */ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress) @@ -219,6 +223,9 @@ bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, This function returns \c true if successful; otherwise it returns \c false and sets the socket error accordingly. + \note This function should be called with the same arguments as were passed + to joinMulticastGroup(). + \sa joinMulticastGroup() */ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) @@ -233,6 +240,9 @@ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) Leaves the multicast group specified by \a groupAddress on the interface \a iface. + \note This function should be called with the same arguments as were passed + to joinMulticastGroup(). + \sa joinMulticastGroup() */ bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress, diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h index 6ef10e2edb..ce4429d1cd 100644 --- a/src/network/socket/qudpsocket.h +++ b/src/network/socket/qudpsocket.h @@ -57,7 +57,7 @@ class Q_NETWORK_EXPORT QUdpSocket : public QAbstractSocket { Q_OBJECT public: - explicit QUdpSocket(QObject *parent = Q_NULLPTR); + explicit QUdpSocket(QObject *parent = nullptr); virtual ~QUdpSocket(); #ifndef QT_NO_NETWORKINTERFACE @@ -75,7 +75,7 @@ public: bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; QNetworkDatagram receiveDatagram(qint64 maxSize = -1); - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = Q_NULLPTR, quint16 *port = Q_NULLPTR); + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = nullptr, quint16 *port = nullptr); qint64 writeDatagram(const QNetworkDatagram &datagram); qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port); diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index b2ee1a8054..a8a37492b7 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -1,7 +1,6 @@ # Qt network socket HEADERS += socket/qabstractsocketengine_p.h \ - socket/qhttpsocketengine_p.h \ socket/qabstractsocket.h \ socket/qabstractsocket_p.h \ socket/qtcpsocket.h \ @@ -11,7 +10,6 @@ HEADERS += socket/qabstractsocketengine_p.h \ socket/qtcpserver_p.h SOURCES += socket/qabstractsocketengine.cpp \ - socket/qhttpsocketengine.cpp \ socket/qabstractsocket.cpp \ socket/qtcpsocket.cpp \ socket/qudpsocket.cpp \ @@ -26,6 +24,13 @@ qtConfig(socks5) { socket/qsocks5socketengine.cpp } +qtConfig(http) { + HEADERS += \ + socket/qhttpsocketengine_p.h + SOURCES += \ + socket/qhttpsocketengine.cpp +} + # SCTP support. qtConfig(sctp) { |