diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-02 14:23:08 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-02 16:59:55 +0200 |
commit | d0eaa737e10aed34c09ba753e21c3e027b5ce58c (patch) | |
tree | ce2a9ea9dbfbabf5cfc390feaed5ee94beb0449a /src/network | |
parent | 7c0b9e1e8d069afab997efd3df9632d342b23150 (diff) | |
parent | a5f470240f31d35e694a40fe837fc4f49bc32072 (diff) |
Merge remote-tracking branch 'origin/5.5' into 5.6
Conflicts:
qmake/doc/src/qmake-manual.qdoc
src/corelib/tools/qstring.h
src/gui/image/qimagereader.cpp
src/network/access/qnetworkaccessmanager.cpp
src/tools/qdoc/doc/examples/examples.qdoc
src/widgets/accessible/qaccessiblewidgetfactory_p.h
src/widgets/doc/qtwidgets.qdocconf
Change-Id: I8fae62283aebefe24e5ca4b4abd97386560c0fcb
Diffstat (limited to 'src/network')
22 files changed, 269 insertions, 122 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index c2d986ef3d..e6f1918da8 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -888,8 +888,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) // if HTTP mandates we should close // or the reply is not finished yet, e.g. it was aborted // we have to close that connection - if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) - channels[i].close(); + if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) { + if (reply->isAborted()) { + channels[i].abort(); + } else { + channels[i].close(); + } + } QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); return; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 8980ed7a41..293909c914 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -205,6 +205,26 @@ void QHttpNetworkConnectionChannel::close() } +void QHttpNetworkConnectionChannel::abort() +{ + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) + state = QHttpNetworkConnectionChannel::IdleState; + else + state = QHttpNetworkConnectionChannel::ClosingState; + + // pendingEncrypt must only be true in between connected and encrypted states + pendingEncrypt = false; + + if (socket) { + // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while + // there is no socket yet. + socket->abort(); + } +} + + bool QHttpNetworkConnectionChannel::sendRequest() { Q_ASSERT(!protocolHandler.isNull()); @@ -1080,6 +1100,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) connection->d_func()->pauseConnection(); if (pendingEncrypt && !reply) connection->d_func()->dequeueRequest(socket); + if (reply) // a reply was actually dequeued. + reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest(); if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) { if (reply) emit reply->sslErrors(errors); diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 37ad6c9b0a..87329b7397 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -157,6 +157,7 @@ public: void init(); void close(); + void abort(); bool sendRequest(); diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index dd108ad5c7..a0f05523e3 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -264,6 +264,17 @@ char* QHttpNetworkReply::userProvidedDownloadBuffer() return d->userProvidedDownloadBuffer; } +void QHttpNetworkReply::abort() +{ + Q_D(QHttpNetworkReply); + d->state = QHttpNetworkReplyPrivate::Aborted; +} + +bool QHttpNetworkReply::isAborted() const +{ + return d_func()->state == QHttpNetworkReplyPrivate::Aborted; +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 6e81663500..e8ed73fdac 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -121,6 +121,9 @@ public: void setUserProvidedDownloadBuffer(char*); char* userProvidedDownloadBuffer(); + void abort(); + + bool isAborted() const; bool isFinished() const; bool isPipeliningUsed() const; @@ -214,7 +217,8 @@ public: SPDYSYNSent, SPDYUploading, SPDYHalfClosed, - SPDYClosed + SPDYClosed, + Aborted } state; QHttpNetworkRequest request; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 3fc4fa9dee..c07064fd94 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -396,6 +396,7 @@ void QHttpThreadDelegate::abortRequest() qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous; #endif if (httpReply) { + httpReply->abort(); delete httpReply; httpReply = 0; } diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index e6fb1a09a0..7147823309 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -278,7 +278,8 @@ static void ensureInitialized() \snippet code/src_network_access_qnetworkaccessmanager.cpp 4 - Network requests can be reenabled again by calling + Network requests can be re-enabled again, and this property will resume to + reflect the actual device state by calling \snippet code/src_network_access_qnetworkaccessmanager.cpp 5 @@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) #ifndef QT_NO_BEARERMANAGEMENT Q_D(QNetworkAccessManager); - if (!d->networkSessionRequired) { - // if a session is required, we track online state through - // the QNetworkSession's signals - connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), - SLOT(_q_onlineStateChanged(bool))); - } - // we would need all active configurations to check for - // d->networkConfigurationManager.isOnline(), which is asynchronous - // and potentially expensive. We can just check the configuration here - d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active); + // if a session is required, we track online state through + // the QNetworkSession's signals if a request is already made. + // we need to track current accessibility state by default + // + connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); #endif } @@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible) { Q_D(QNetworkAccessManager); - d->defaultAccessControl = false; + + d->defaultAccessControl = accessible == NotAccessible ? false : true; if (d->networkAccessible != accessible) { NetworkAccessibility previous = networkAccessible(); @@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const { Q_D(const QNetworkAccessManager); + + if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) + return UnknownAccessibility; + if (d->networkSessionRequired) { QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession()); if (networkSession) { @@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession if (online) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { online = false; - networkAccessible = QNetworkAccessManager::NotAccessible; - emit q->networkAccessibleChanged(networkAccessible); + if (networkAccessible != QNetworkAccessManager::NotAccessible) { + networkAccessible = QNetworkAccessManager::NotAccessible; + emit q->networkAccessibleChanged(networkAccessible); + } } } else { if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) { online = true; if (defaultAccessControl) - networkAccessible = QNetworkAccessManager::Accessible; - emit q->networkAccessibleChanged(networkAccessible); + if (networkAccessible != QNetworkAccessManager::Accessible) { + networkAccessible = QNetworkAccessManager::Accessible; + emit q->networkAccessibleChanged(networkAccessible); + } } } } void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) { - // if the user set a config, we only care whether this one is active. + Q_Q(QNetworkAccessManager); + // if the user set a config, we only care whether this one is active. // Otherwise, this QNAM is online if there is an online config. if (customNetworkConfiguration) { online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { - if (isOnline && online != isOnline) { - networkSessionStrongRef.clear(); - networkSessionWeakRef.clear(); + if (online != isOnline) { + if (isOnline) { + networkSessionStrongRef.clear(); + networkSessionWeakRef.clear(); + } + online = isOnline; + } + } + if (online) { + if (defaultAccessControl) { + if (networkAccessible != QNetworkAccessManager::Accessible) { + networkAccessible = QNetworkAccessManager::Accessible; + emit q->networkAccessibleChanged(networkAccessible); + } + } + } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) { + if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) { + networkAccessible = QNetworkAccessManager::UnknownAccessibility; + emit q->networkAccessibleChanged(networkAccessible); + } + } else { + if (networkAccessible != QNetworkAccessManager::NotAccessible) { + networkAccessible = QNetworkAccessManager::NotAccessible; + emit q->networkAccessibleChanged(networkAccessible); } - - online = isOnline; } } diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index c715da00c1..54ae114581 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -78,7 +78,6 @@ public: customNetworkConfiguration(false), networkSessionRequired(networkConfigurationManager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired), - networkAccessible(QNetworkAccessManager::Accessible), activeReplyCount(0), online(false), initializeSession(true), @@ -86,7 +85,18 @@ public: cookieJarCreated(false), defaultAccessControl(true), authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create()) - { } + { +#ifndef QT_NO_BEARERMANAGEMENT + // we would need all active configurations to check for + // d->networkConfigurationManager.isOnline(), which is asynchronous + // and potentially expensive. We can just check the configuration here + online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active)); + if (online) + networkAccessible = QNetworkAccessManager::Accessible; + else + networkAccessible = QNetworkAccessManager::NotAccessible; +#endif + } ~QNetworkAccessManagerPrivate(); void _q_replyFinished(); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 8c0c098147..63fca2bda2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1238,7 +1238,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData if (statusCode == 304) { #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Received a 304 from" << url(); + qDebug() << "Received a 304 from" << request.url(); #endif QAbstractNetworkCache *nc = managerPrivate->networkCache; if (nc) { @@ -1562,7 +1562,7 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe } #if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - QByteArray n = rawHeader(header); + QByteArray n = q->rawHeader(header); QByteArray o; if (it != cacheHeaders.rawHeaders.constEnd()) o = (*it).second; @@ -1782,6 +1782,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection); return; #endif + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); +#endif } if (synchronous) { @@ -1950,6 +1955,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index fff88f8f2d..44d51d82a4 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -96,6 +96,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif Q_PRIVATE_SLOT(d_func(), void _q_finished()) @@ -171,6 +172,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif void _q_finished(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index a73e0ea75e..c73e6162d1 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -125,6 +125,11 @@ void QNetworkReplyImplPrivate::_q_startOperation() finished(); #endif return; + } else { +#ifndef QT_NO_BEARERMANAGEMENT + QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); +#endif } #ifndef QT_NO_BEARERMANAGEMENT @@ -309,6 +314,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() } } +void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState) +{ + if (sessionState == QNetworkSession::Disconnected + && (state != Idle || state != Reconnecting)) { + error(QNetworkReplyImpl::NetworkSessionFailedError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyImplPrivate::_q_networkSessionFailed() { // Abort waiting and working replies. diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 3e720ef597..209bf40b72 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -89,6 +89,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)) #endif @@ -122,6 +123,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void _q_networkSessionConnected(); void _q_networkSessionFailed(); + void _q_networkSessionStateChanged(QNetworkSession::State); void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies); #endif diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index abb47e9e29..d626d0bcfc 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -85,6 +85,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \li Digest-MD5 \endlist + \target qauthenticator-options \section1 Options In addition to the username and password required for authentication, a @@ -104,8 +105,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \section2 Basic \table - \header \li Option \li Direction \li Description - \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Type \li Description + \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm() \endtable The Basic authentication mechanism supports no outgoing options. @@ -119,8 +120,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& \section2 Digest-MD5 \table - \header \li Option \li Direction \li Description - \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Type \li Description + \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm() \endtable The Digest-MD5 authentication mechanism supports no outgoing options. @@ -130,7 +131,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray& /*! - Constructs an empty authentication object + Constructs an empty authentication object. */ QAuthenticator::QAuthenticator() : d(0) @@ -138,7 +139,7 @@ QAuthenticator::QAuthenticator() } /*! - Destructs the object + Destructs the object. */ QAuthenticator::~QAuthenticator() { @@ -207,7 +208,7 @@ bool QAuthenticator::operator==(const QAuthenticator &other) const */ /*! - returns the user used for authentication. + Returns the user used for authentication. */ QString QAuthenticator::user() const { @@ -227,7 +228,7 @@ void QAuthenticator::setUser(const QString &user) } /*! - returns the password used for authentication. + Returns the password used for authentication. */ QString QAuthenticator::password() const { @@ -260,7 +261,7 @@ void QAuthenticator::detach() } /*! - returns the realm requiring authentication. + Returns the realm requiring authentication. */ QString QAuthenticator::realm() const { @@ -279,10 +280,11 @@ void QAuthenticator::setRealm(const QString &realm) /*! \since 4.7 Returns the value related to option \a opt if it was set by the server. - See \l{QAuthenticator#Options} for more information on incoming options. + See the \l{QAuthenticator#qauthenticator-options}{Options section} for + more information on incoming options. If option \a opt isn't found, an invalid QVariant will be returned. - \sa options(), QAuthenticator#Options + \sa options(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ QVariant QAuthenticator::option(const QString &opt) const { @@ -292,10 +294,10 @@ QVariant QAuthenticator::option(const QString &opt) const /*! \since 4.7 Returns all incoming options set in this QAuthenticator object by parsing - the server reply. See \l{QAuthenticator#Options} for more information - on incoming options. + the server reply. See the \l{QAuthenticator#qauthenticator-options}{Options section} + for more information on incoming options. - \sa option(), QAuthenticator#Options + \sa option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ QVariantHash QAuthenticator::options() const { @@ -306,9 +308,9 @@ QVariantHash QAuthenticator::options() const \since 4.7 Sets the outgoing option \a opt to value \a value. - See \l{QAuthenticator#Options} for more information on outgoing options. + See the \l{QAuthenticator#qauthenticator-options}{Options section} for more information on outgoing options. - \sa options(), option(), QAuthenticator#Options + \sa options(), option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options} */ void QAuthenticator::setOption(const QString &opt, const QVariant &value) { @@ -318,7 +320,10 @@ void QAuthenticator::setOption(const QString &opt, const QVariant &value) /*! - Returns \c true if the authenticator is null. + Returns \c true if the object has not been initialized. Returns + \c false if non-const member functions have been called, or + the content was constructed or copied from another initialized + QAuthenticator object. */ bool QAuthenticator::isNull() const { diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 02147d2054..e344a9d17e 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -745,15 +745,9 @@ bool QAbstractSocketPrivate::canReadNotification() return true; } - if (socketEngine) { - // turn the socket engine off if we've either: - // - got pending datagrams - // - reached the buffer size limit - if (isBuffered) - socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable()); - else if (socketType != QAbstractSocket::TcpSocket) - socketEngine->setReadNotificationEnabled(!socketEngine->hasPendingDatagrams()); - } + // turn the socket engine off if we've reached the buffer size limit + if (socketEngine && isBuffered) + socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable()); // reset the read socket notifier state if we reentered inside the // readyRead() connected slot. diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index ef10b1e68d..634074d91f 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -85,7 +85,8 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) } serverName = requestedServerName; - QString tempPath; + QByteArray encodedTempPath; + const QByteArray encodedFullServerName = QFile::encodeName(fullServerName); QScopedPointer<QTemporaryDir> tempDir; // Check any of the flags @@ -96,8 +97,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) setError(QLatin1String("QLocalServer::listen")); return false; } - tempPath = tempDir->path(); - tempPath += QLatin1String("/s"); + encodedTempPath = QFile::encodeName(tempDir->path() + QLatin1String("/s")); } // create the unix socket @@ -111,23 +111,23 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) // Construct the unix address struct ::sockaddr_un addr; addr.sun_family = PF_UNIX; - if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) { + if (sizeof(addr.sun_path) < (uint)encodedFullServerName.size() + 1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } if (socketOptions & QLocalServer::WorldAccessOption) { - if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) { + if (sizeof(addr.sun_path) < (uint)encodedTempPath.size() + 1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } - ::memcpy(addr.sun_path, tempPath.toLatin1().data(), - tempPath.toLatin1().size() + 1); + ::memcpy(addr.sun_path, encodedTempPath.constData(), + encodedTempPath.size() + 1); } else { - ::memcpy(addr.sun_path, fullServerName.toLatin1().data(), - fullServerName.toLatin1().size() + 1); + ::memcpy(addr.sun_path, encodedFullServerName.constData(), + encodedFullServerName.size() + 1); } // bind @@ -165,13 +165,13 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) if (socketOptions & QLocalServer::OtherAccessOption) mode |= S_IRWXO; - if (::chmod(tempPath.toLatin1(), mode) == -1) { + if (::chmod(encodedTempPath.constData(), mode) == -1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; } - if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) { + if (::rename(encodedTempPath.constData(), encodedFullServerName.constData()) == -1) { setError(QLatin1String("QLocalServer::listen")); closeServer(); return false; diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 77c5028fb3..bb0f11f038 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -268,15 +268,16 @@ void QLocalSocketPrivate::_q_connectToSocket() connectingPathName += QLatin1Char('/') + connectingName; } + const QByteArray encodedConnectingPathName = QFile::encodeName(connectingPathName); struct sockaddr_un name; name.sun_family = PF_UNIX; - if (sizeof(name.sun_path) < (uint)connectingPathName.toLatin1().size() + 1) { + if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) { QString function = QLatin1String("QLocalSocket::connectToServer"); errorOccurred(QLocalSocket::ServerNotFoundError, function); return; } - ::memcpy(name.sun_path, connectingPathName.toLatin1().data(), - connectingPathName.toLatin1().size() + 1); + ::memcpy(name.sun_path, encodedConnectingPathName.constData(), + encodedConnectingPathName.size() + 1); if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { QString function = QLatin1String("QLocalSocket::connectToServer"); switch (errno) diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 0e14c175c5..c40eef769e 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -370,7 +370,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt int n, level; convertToLevelAndOption(opt, socketProtocol, level, n); -#if defined(SO_REUSEPORT) +#if defined(SO_REUSEPORT) && !defined(Q_OS_LINUX) if (opt == QNativeSocketEngine::AddressReusable) { // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the // same port (which is useful for multicast UDP). SO_REUSEPORT is, but diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 2e905ad610..9aed0caa25 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1070,8 +1070,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const buf.buf = &c; buf.len = sizeof(c); DWORD flags = MSG_PEEK; - if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) - return 0; + if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) { + int err = WSAGetLastError(); + if (err != WSAECONNRESET && err != WSAENETRESET) + return 0; + } } return nbytes; } @@ -1099,14 +1102,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const int err = WSAGetLastError(); if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) { WS_ERROR_DEBUG(err); - if (err == WSAECONNRESET || err == WSAENETRESET) { - // Discard error message to prevent QAbstractSocket from - // getting this message repeatedly after reenabling the - // notifiers. - flags = 0; - ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, - &storage.a, &storageSize, 0, 0); - } + result = (err == WSAECONNRESET || err == WSAENETRESET); } else { // If there's no error, or if our buffer was too small, there must be // a pending datagram. @@ -1159,12 +1155,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const if (recvResult != SOCKET_ERROR) { ret = qint64(bytesRead); break; - } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) { - bufferCount += 5; - delete[] buf; - } else if (recvResult == SOCKET_ERROR) { - WS_ERROR_DEBUG(err); - ret = -1; + } else { + switch (err) { + case WSAEMSGSIZE: + bufferCount += 5; + delete[] buf; + continue; + case WSAECONNRESET: + case WSAENETRESET: + ret = 0; + break; + default: + WS_ERROR_DEBUG(err); + ret = -1; + break; + } break; } } diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 025e3e5017..44de7f8526 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -285,23 +285,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) return false; } d->socketState = QAbstractSocket::ConnectingState; - hr = QWinRTFunctions::await(d->connectOp); - RETURN_FALSE_IF_FAILED("Connection could not be established"); - bool connectionErrors = false; - d->handleConnectionErrors(d->connectOp.Get(), &connectionErrors); - if (connectionErrors) - return false; - d->connectOp.Reset(); - - d->socketState = QAbstractSocket::ConnectedState; - emit connectionReady(); + hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>( + d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + Q_ASSERT_SUCCEEDED(hr); - // Delay the reader so that the SSL socket can upgrade - if (d->sslSocket) - connect(d->sslSocket, SIGNAL(encrypted()), SLOT(establishRead())); - else - establishRead(); - return true; + return d->socketState == QAbstractSocket::ConnectedState; } bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) @@ -330,8 +318,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) return false; } - EventRegistrationToken token; - d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token); + d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); if (FAILED(hr)) { qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message @@ -688,6 +675,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) { Q_UNUSED(msecs); Q_UNUSED(timedOut); + Q_D(QNativeSocketEngine); + if (d->socketState == QAbstractSocket::ConnectingState) { + HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents); + if (SUCCEEDED(hr)) { + d->handleConnectionEstablished(d->connectOp.Get()); + return true; + } + } return false; } @@ -728,7 +723,6 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable) if (bytesToWrite()) return; // will be emitted as a result of bytes written writeNotification(); - d->notifyOnWrite = false; } } @@ -785,9 +779,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc qWarning("Failed to create stream socket"); return false; } - EventRegistrationToken token; socketDescriptor = qintptr(socket.Detach()); - udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token); + udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); break; } default: @@ -815,11 +808,19 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , closingDown(false) , socketDescriptor(-1) , sslSocket(Q_NULLPTR) + , connectionToken( { -1 } ) { } QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() { + if (socketDescriptor == -1 || connectionToken.value == -1) + return; + + if (socketType == QAbstractSocket::UdpSocket) + udpSocket()->remove_MessageReceived(connectionToken); + else if (socketType == QAbstractSocket::TcpSocket) + tcpListener->remove_ConnectionReceived(connectionToken); } void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const @@ -1119,10 +1120,19 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener return S_OK; } -void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAction, bool *errorsOccured) +HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus) +{ + handleConnectionEstablished(action); + return S_OK; +} + +void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action) { - bool error = true; - HRESULT hr = connectAction->GetResults(); + Q_Q(QNativeSocketEngine); + if (wasDeleted || !connectOp) // Protect against a late callback + return; + + HRESULT hr = action->GetResults(); switch (hr) { case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); @@ -1140,13 +1150,32 @@ void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAct if (FAILED(hr)) { setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); socketState = QAbstractSocket::UnconnectedState; - } else { - error = false; } break; } - if (errorsOccured) - *errorsOccured = error; + + // The callback might be triggered several times if we do not cancel/reset it here + if (connectOp) { + ComPtr<IAsyncInfo> info; + connectOp.As(&info); + if (info) { + info->Cancel(); + info->Close(); + } + connectOp.Reset(); + } + + socketState = QAbstractSocket::ConnectedState; + emit q->connectionReady(); + + if (socketType != QAbstractSocket::TcpSocket) + return; + + // Delay the reader so that the SSL socket can upgrade + if (sslSocket) + QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead); + else + q->establishRead(); } HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) @@ -1166,7 +1195,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async hr = buffer->get_Length(&bufferLength); Q_ASSERT_SUCCEEDED(hr); if (!bufferLength) { - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); return S_OK; } @@ -1190,7 +1219,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async readBytes.seek(readPos); readMutex.unlock(); - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); ComPtr<IInputStream> stream; diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 4286ff6373..912b7db973 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -207,13 +207,15 @@ private: QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections; QEventLoop eventLoop; QAbstractSocket *sslSocket; + EventRegistrationToken connectionToken; HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); - void handleConnectionErrors(ABI::Windows::Foundation::IAsyncAction *connectAction, bool *errorsOccured); + HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); + void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action); HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus); }; diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp index a16f726429..b4396d567b 100644 --- a/src/network/ssl/qsslellipticcurve.cpp +++ b/src/network/ssl/qsslellipticcurve.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE elliptic-curve cipher algorithms. Elliptic curves can be constructed from a "short name" (SN) (fromShortName()), - and by a call to QSslSocket::supportedEllipticCurves(). + and by a call to QSslConfiguration::supportedEllipticCurves(). QSslEllipticCurve instances can be compared for equality and can be used as keys in QHash and QSet. They cannot be used as key in a QMap. @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE Constructs an invalid elliptic curve. - \sa isValid(), QSslSocket::supportedEllipticCurves() + \sa isValid(), QSslConfiguration::supportedEllipticCurves() */ /*! @@ -136,7 +136,6 @@ QT_BEGIN_NAMESPACE \relates QSslEllipticCurve Returns true if the curve \a lhs represents the same curve of \a rhs; - false otherwise. */ /*! diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp index 4a3b1aa807..ab78aea1cd 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp +++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp @@ -257,7 +257,6 @@ int QSslPreSharedKeyAuthenticator::maximumPreSharedKeyLength() const identity hint, identity, pre shared key, maximum length for the identity and maximum length for the pre shared key. - \sa operator!=(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) */ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) { @@ -277,7 +276,6 @@ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKey Returns true if the authenticator object \a lhs is different than \a rhs; false otherwise. - \sa operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs) */ QT_END_NAMESPACE |