summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-10-13 09:49:38 +0200
committerLiang Qi <liang.qi@qt.io>2016-10-13 09:49:38 +0200
commitdfc177e3a99dd593db4b1e9445d6243ce75ebf07 (patch)
tree4e33c7be90a44642e672fff22ea163b500ff3aef /src/network
parent72efb2e6f4af2fd909daaf9104f09fd1425acfb0 (diff)
parent1d6eb70dcec105af28d6a5e9b59d56c895c70389 (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.cpp15
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h1
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp3
-rw-r--r--src/network/access/qnetworkcookiejar.cpp11
-rw-r--r--src/network/kernel/qnetworkproxy_mac.cpp16
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp115
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h11
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