diff options
author | Liang Qi <liang.qi@qt.io> | 2016-10-13 09:49:38 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-10-13 09:49:38 +0200 |
commit | dfc177e3a99dd593db4b1e9445d6243ce75ebf07 (patch) | |
tree | 4e33c7be90a44642e672fff22ea163b500ff3aef /src/network | |
parent | 72efb2e6f4af2fd909daaf9104f09fd1425acfb0 (diff) | |
parent | 1d6eb70dcec105af28d6a5e9b59d56c895c70389 (diff) |
Merge remote-tracking branch 'origin/5.8' into dev
Conflicts:
qmake/library/qmakeevaluator.cpp
(cherry picked from commit 1af6dc2c8fb4d91400fddc5050166f972ae57c9a in qttools)
src/corelib/kernel/qcore_mac_objc.mm
src/gui/painting/qcolor.h
src/plugins/platforms/cocoa/qcocoawindow.mm
Change-Id: I5b3ec468a5a9a73911b528d3d24ff8e19f339f31
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 15 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnection_p.h | 1 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 3 | ||||
-rw-r--r-- | src/network/access/qnetworkcookiejar.cpp | 11 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy_mac.cpp | 16 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_winrt.cpp | 115 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_winrt_p.h | 11 |
7 files changed, 143 insertions, 29 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 8e5cfd9497..6f837de27f 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -674,8 +674,7 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket) HttpMessagePair messagePair = highPriorityQueue.takeLast(); if (!messagePair.second->d_func()->requestIsPrepared) prepareRequest(messagePair); - channels[i].request = messagePair.first; - channels[i].reply = messagePair.second; + updateChannel(i, messagePair); return true; } @@ -684,13 +683,21 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket) HttpMessagePair messagePair = lowPriorityQueue.takeLast(); if (!messagePair.second->d_func()->requestIsPrepared) prepareRequest(messagePair); - channels[i].request = messagePair.first; - channels[i].reply = messagePair.second; + updateChannel(i, messagePair); return true; } return false; } +void QHttpNetworkConnectionPrivate::updateChannel(int i, const HttpMessagePair &messagePair) +{ + channels[i].request = messagePair.first; + channels[i].reply = messagePair.second; + // Now that reply is assigned a channel, correct reply to channel association + // previously set in queueRequest. + channels[i].reply->d_func()->connectionChannel = &channels[i]; +} + QHttpNetworkRequest QHttpNetworkConnectionPrivate::predictNextRequest() const { if (!highPriorityQueue.isEmpty()) diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index cad0ab1ac4..430c715717 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -210,6 +210,7 @@ public: void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke bool dequeueRequest(QAbstractSocket *socket); void prepareRequest(HttpMessagePair &request); + void updateChannel(int i, const HttpMessagePair &messagePair); QHttpNetworkRequest predictNextRequest() const; void fillPipeline(QAbstractSocket *socket); diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b6a9b80511..205490b830 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -1111,6 +1111,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted() connection->d_func()->dequeueRequest(socket); if (reply) { reply->setSpdyWasUsed(false); + Q_ASSERT(reply->d_func()->connectionChannel == this); emit reply->encrypted(); } if (reply) @@ -1137,8 +1138,6 @@ 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/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp index 429b71eb21..0540cb740f 100644 --- a/src/network/access/qnetworkcookiejar.cpp +++ b/src/network/access/qnetworkcookiejar.cpp @@ -335,11 +335,20 @@ bool QNetworkCookieJar::validateCookie(const QNetworkCookie &cookie, const QUrl if (!isParentDomain(domain, host) && !isParentDomain(host, domain)) return false; // not accepted + if (domain.startsWith(QLatin1Char('.'))) + domain = domain.mid(1); + +#if QT_CONFIG(topleveldomain) // the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2 // redundant; the "leading dot" rule has been relaxed anyway, see QNetworkCookie::normalize() // we remove the leading dot for this check if it's present - if (qIsEffectiveTLD(domain.startsWith('.') ? domain.remove(0, 1) : domain)) + if (qIsEffectiveTLD(domain)) return false; // not accepted +#else + // provide minimal checking by not accepting cookies on real TLDs + if (!domain.contains(QLatin1Char('.'))) + return false; +#endif return true; } diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp index 76a2d2df9f..c13a472b90 100644 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ b/src/network/kernel/qnetworkproxy_mac.cpp @@ -104,7 +104,7 @@ static bool isHostExcluded(CFDictionaryRef dict, const QString &host) CFIndex size = CFArrayGetCount(exclusionList); for (CFIndex i = 0; i < size; ++i) { CFStringRef cfentry = (CFStringRef)CFArrayGetValueAtIndex(exclusionList, i); - QString entry = QCFString::toQString(cfentry); + QString entry = QString::fromCFString(cfentry); if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) { return true; // excluded @@ -133,7 +133,7 @@ static QNetworkProxy proxyFromDictionary(CFDictionaryRef dict, QNetworkProxy::Pr && (protoPort = (CFNumberRef)CFDictionaryGetValue(dict, portKey))) { int enabled; if (CFNumberGetValue(protoEnabled, kCFNumberIntType, &enabled) && enabled) { - QString host = QCFString::toQString(protoHost); + QString host = QString::fromCFString(protoHost); int port; CFNumberGetValue(protoPort, kCFNumberIntType, &port); @@ -168,9 +168,9 @@ static QNetworkProxy proxyFromDictionary(CFDictionaryRef dict) proxyType = QNetworkProxy::Socks5Proxy; } - hostName = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyHostNameKey)); - user = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyUsernameKey)); - password = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyPasswordKey)); + hostName = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyHostNameKey)); + user = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyUsernameKey)); + password = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyPasswordKey)); CFNumberRef portNumber = (CFNumberRef)CFDictionaryGetValue(dict, kCFProxyPortNumberKey); if (portNumber) { @@ -229,7 +229,7 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) QCFType<CFDataRef> pacData; QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); if (!pacUrl) { - qWarning("Invalid PAC URL \"%s\"", qPrintable(QCFString::toQString(cfPacLocation))); + qWarning("Invalid PAC URL \"%s\"", qPrintable(QString::fromCFString(cfPacLocation))); return result; } @@ -259,9 +259,9 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) CFRunLoopRunInMode(pacRunLoopMode, 1000, /*returnAfterSourceHandled*/ true); if (!pacInfo.proxies) { - QString pacLocation = QCFString::toQString(cfPacLocation); + QString pacLocation = QString::fromCFString(cfPacLocation); QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacInfo.error); - qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QCFString::toQString(pacErrorDescription))); + qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QString::fromCFString(pacErrorDescription))); return result; } diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 6b71912838..bd9b443602 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -84,6 +84,69 @@ typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation; QT_BEGIN_NAMESPACE +static inline QString qt_QStringFromHString(const HString &string) +{ + UINT32 length; + PCWSTR rawString = string.GetRawBuffer(&length); + return QString::fromWCharArray(rawString, length); +} + +class SocketEngineWorker : public QObject +{ + Q_OBJECT +signals: + void newDatagramsReceived(const QList<WinRtDatagram> &datagram); + +public slots: + Q_INVOKABLE void notifyAboutNewDatagrams() + { + QMutexLocker locker(&mutex); + QList<WinRtDatagram> datagrams = pendingDatagrams; + pendingDatagrams.clear(); + emit newDatagramsReceived(datagrams); + } + +public: + HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args) + { + WinRtDatagram datagram; + QHostAddress returnAddress; + ComPtr<IHostName> remoteHost; + HRESULT hr = args->get_RemoteAddress(&remoteHost); + RETURN_OK_IF_FAILED("Could not obtain remote host"); + HString remoteHostString; + hr = remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); + RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); + returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); + datagram.header.senderAddress = returnAddress; + HString remotePort; + hr = args->get_RemotePort(remotePort.GetAddressOf()); + RETURN_OK_IF_FAILED("Could not obtain remote port"); + datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt(); + + ComPtr<IDataReader> reader; + hr = args->GetDataReader(&reader); + RETURN_OK_IF_FAILED("Could not obtain data reader"); + quint32 length; + hr = reader->get_UnconsumedBufferLength(&length); + RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length"); + datagram.data.resize(length); + hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data())); + RETURN_OK_IF_FAILED("Could not read datagram"); + QMutexLocker locker(&mutex); + // Notify the engine about new datagrams being present at the next event loop iteration + if (pendingDatagrams.isEmpty()) + QMetaObject::invokeMethod(this, "notifyAboutNewDatagrams", Qt::QueuedConnection); + pendingDatagrams << datagram; + + return S_OK; + } + +private: + QList<WinRtDatagram> pendingDatagrams; + QMutex mutex; +}; + static QByteArray socketDescription(const QAbstractSocketEngine *s) { QByteArray result; @@ -159,13 +222,6 @@ struct SocketGlobal }; Q_GLOBAL_STATIC(SocketGlobal, g) -static inline QString qt_QStringFromHString(const HString &string) -{ - UINT32 length; - PCWSTR rawString = string.GetRawBuffer(&length); - return QString::fromWCharArray(rawString, length); -} - #define READ_BUFFER_SIZE 65536 template <typename T> @@ -206,6 +262,7 @@ static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint QNativeSocketEngine::QNativeSocketEngine(QObject *parent) : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent) { + qRegisterMetaType<WinRtDatagram>(); #ifndef QT_NO_SSL Q_D(QNativeSocketEngine); if (parent) @@ -215,6 +272,7 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent) connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection); connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection); connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection); + connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection); } QNativeSocketEngine::~QNativeSocketEngine() @@ -585,7 +643,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const if (d->socketType != QAbstractSocket::TcpSocket) return -1; - return d->readBytes.size() - d->readBytes.pos(); + return d->bytesAvailable; } qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) @@ -603,7 +661,9 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) } QMutexLocker mutexLocker(&d->readMutex); - return d->readBytes.read(data, maxlen); + qint64 b = d->readBytes.read(data, maxlen); + d->bytesAvailable = d->readBytes.size() - d->readBytes.pos(); + return b; } qint64 QNativeSocketEngine::write(const char *data, qint64 len) @@ -634,6 +694,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea { #ifndef QT_NO_UDPSOCKET Q_D(QNativeSocketEngine); + d->readMutex.lock(); if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { if (header) header->clear(); @@ -653,6 +714,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea } else { readOrigin = datagram.data; } + d->readMutex.unlock(); memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length()))); return readOrigin.length(); #else @@ -880,6 +942,24 @@ void QNativeSocketEngine::establishRead() Q_ASSERT_SUCCEEDED(hr); } +void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagrams) +{ + Q_D(QNativeSocketEngine); + // Defer putting the datagrams into the list until the next event loop iteration + // (where the readyRead signal is emitted as well) + QMetaObject::invokeMethod(this, "putIntoPendingDatagramsList", Qt::QueuedConnection, + Q_ARG(QList<WinRtDatagram>, datagrams)); + if (d->notifyOnRead) + emit readReady(); +} + +void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams) +{ + Q_D(QNativeSocketEngine); + QMutexLocker locker(&d->readMutex); + d->pendingDatagrams.append(datagrams); +} + bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) { Q_UNUSED(socketProtocol); @@ -899,8 +979,11 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc RETURN_FALSE_IF_FAILED("createNewSocket: Could not create socket instance"); socketDescriptor = qintptr(socket.Detach()); QEventDispatcherWinRT::runOnXamlThread([&hr, this]() { - hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); - RETURN_OK_IF_FAILED("createNewSocket: Could not add \"message received\" callback") + hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(worker, &SocketEngineWorker::OnNewDatagramReceived).Get(), &connectionToken); + if (FAILED(hr)) { + qErrnoWarning(hr, "createNewSocket: Could not add \"message received\" callback"); + return hr; + } return S_OK; }); if (FAILED(hr)) @@ -931,6 +1014,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , notifyOnException(false) , closingDown(false) , socketDescriptor(-1) + , worker(new SocketEngineWorker) , sslSocket(Q_NULLPTR) , connectionToken( { -1 } ) { @@ -947,6 +1031,8 @@ QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() else if (socketType == QAbstractSocket::TcpSocket) hr = tcpListener->remove_ConnectionReceived(connectionToken); Q_ASSERT_SUCCEEDED(hr); + + worker->deleteLater(); } void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const @@ -1372,6 +1458,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async Q_ASSERT(readBytes.atEnd()); readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength)); readBytes.seek(readPos); + bytesAvailable = readBytes.size() - readBytes.pos(); readMutex.unlock(); if (notifyOnRead) @@ -1436,11 +1523,11 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I datagram.data.resize(length); hr = reader->ReadBytes(length, reinterpret_cast<BYTE *>(datagram.data.data())); RETURN_OK_IF_FAILED("Could not read datagram"); - pendingDatagrams.append(datagram); - if (notifyOnRead) - emit q->readReady(); + emit q->newDatagramReceived(datagram); return S_OK; } QT_END_NAMESPACE + +#include "qnativesocketengine_winrt.moc" diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index ef219e61df..605f3631b9 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -55,6 +55,7 @@ #include <QtCore/QEventLoop> #include <QtCore/QBuffer> #include <QtCore/QMutex> +#include <QtCore/QAtomicInteger> #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" #include <wrl.h> @@ -63,6 +64,7 @@ QT_BEGIN_NAMESPACE class QNativeSocketEnginePrivate; +class SocketEngineWorker; struct WinRtDatagram { QByteArray data; @@ -137,11 +139,15 @@ signals: void connectionReady(); void readReady(); void writeReady(); + void newDatagramReceived(const WinRtDatagram &datagram); private slots: void establishRead(); + void handleNewDatagrams(const QList<WinRtDatagram> &datagram); private: + Q_INVOKABLE void putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams); + Q_DECLARE_PRIVATE(QNativeSocketEngine) Q_DISABLE_COPY(QNativeSocketEngine) }; @@ -154,6 +160,7 @@ public: ~QNativeSocketEnginePrivate(); qintptr socketDescriptor; + SocketEngineWorker *worker; bool notifyOnRead, notifyOnWrite, notifyOnException; QAtomicInt closingDown; @@ -210,6 +217,8 @@ private: Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32>> readOp; QBuffer readBytes; QMutex readMutex; + bool emitOnNewDatagram; + QAtomicInteger<int> bytesAvailable; QList<WinRtDatagram> pendingDatagrams; QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections; @@ -228,4 +237,6 @@ private: QT_END_NAMESPACE +Q_DECLARE_METATYPE(WinRtDatagram) + #endif // QNATIVESOCKETENGINE_WINRT_P_H |