diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-13 07:39:30 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-04-13 09:45:58 +0000 |
commit | eb3e3853c4de146410478fca652ea24f3943f774 (patch) | |
tree | df215a0379d5ce40c5c7725d1f00af982b280c03 /src/network | |
parent | 33044b83c261c485faa0a6f367773138f9892f76 (diff) | |
parent | b94773c9c838a0b3db1bced0bc8daf5b04aefc29 (diff) |
Merge "Merge remote-tracking branch 'origin/5.6' into 5.7" into refs/staging/5.7
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qnetworkreply.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkrequest.cpp | 10 | ||||
-rw-r--r-- | src/network/bearer/qnetworkconfigmanager_p.cpp | 2 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_winrt.cpp | 1 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy_win.cpp | 15 | ||||
-rw-r--r-- | src/network/network.pro | 4 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_winrt.cpp | 122 |
7 files changed, 96 insertions, 60 deletions
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 876e095a0c..3f17b68e79 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -141,10 +141,12 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() \value TooManyRedirectsError while following redirects, the maximum limit was reached. The limit is by default set to 50 or as set by QNetworkRequest::setMaxRedirectsAllowed(). + (This value was introduced in 5.6.) \value InsecureRedirectError while following redirects, the network access API detected a redirect from a encrypted protocol (https) to an unencrypted one (http). + (This value was introduced in 5.6.) \value ProxyConnectionRefusedError the connection to the proxy server was refused (the proxy server is not accepting requests) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index f674cd5c2e..2ee85fd049 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -146,11 +146,12 @@ QT_BEGIN_NAMESPACE Replies only, type: QMetaType::QUrl (no default) If present, it indicates that the server is redirecting the request to a different URL. The Network Access API does not by - default follow redirections: it's up to the application to + default follow redirections: the application can determine if the requested redirection should be allowed, - according to its security policies. However, if - QNetworkRequest::FollowRedirectsAttribute is set, then this attribute - will not be present in the reply. + according to its security policies, or it can set + QNetworkRequest::FollowRedirectsAttribute to true (in which case + the redirection will be followed and this attribute will not + be present in the reply). The returned URL might be relative. Use QUrl::resolved() to create an absolute URL out of it. @@ -271,6 +272,7 @@ QT_BEGIN_NAMESPACE Indicates whether the Network Access API should automatically follow a HTTP redirect response or not. Currently redirects that are insecure, that is redirecting from "https" to "http" protocol, are not allowed. + (This value was introduced in 5.6.) \value User Special type. Additional information can be passed in diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 232875f43c..f2a79319a1 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -420,6 +420,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() if (generic) { if (!envOK || skipGeneric <= 0) sessionEngines.append(generic); + else + delete generic; } } diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp index 1cbc4d686f..24ac3df52f 100644 --- a/src/network/kernel/qnetworkinterface_winrt.cpp +++ b/src/network/kernel/qnetworkinterface_winrt.cpp @@ -92,6 +92,7 @@ static QNetworkInterfacePrivate *interfaceFromProfile(IConnectionProfile *profil Q_ASSERT_SUCCEEDED(hr); if (connectivityLevel != NetworkConnectivityLevel_None) iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning; + iface->flags |= QNetworkInterface::CanBroadcast; ComPtr<INetworkAdapter> adapter; hr = profile->get_NetworkAdapter(&adapter); diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 832a3badb9..fe9f088062 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -47,6 +47,7 @@ #include <qurl.h> #include <private/qsystemlibrary_p.h> #include <qnetworkinterface.h> +#include <qdebug.h> #include <string.h> #include <qt_windows.h> @@ -596,8 +597,16 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro url.setScheme(QLatin1String("https")); } + QString urlQueryString = url.toString(); + if (urlQueryString.size() > 2083) { + // calls to WinHttpGetProxyForUrl with urls longer than 2083 characters + // fail with error code ERROR_INVALID_PARAMETER(87), so we truncate it + qWarning("Proxy query URL too long for windows API, try with truncated URL"); + urlQueryString = url.toString().left(2083); + } + bool getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); DWORD getProxyError = GetLastError(); @@ -614,7 +623,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro sp->autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; sp->autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)sp->autoConfigUrl.utf16(); getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); getProxyError = GetLastError(); @@ -627,7 +636,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro // But now we've to enable it (http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx) sp->autoProxyOptions.fAutoLogonIfChallenged = TRUE; getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession, - (LPCWSTR)url.toString().utf16(), + (LPCWSTR)urlQueryString.utf16(), &sp->autoProxyOptions, &proxyInfo); getProxyError = GetLastError(); diff --git a/src/network/network.pro b/src/network/network.pro index cdea190222..fed14616af 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -32,6 +32,10 @@ MODULE_PLUGIN_TYPES = \ ANDROID_PERMISSIONS += \ android.permission.ACCESS_NETWORK_STATE +MODULE_WINRT_CAPABILITIES = \ + internetClient \ + internetClientServer + MODULE_PLUGIN_TYPES = \ bearer load(qt_module) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 0f632abbb3..45ed1465f2 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -304,8 +304,10 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::ConnectingState; - hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>( + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + return d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>( d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + }); Q_ASSERT_SUCCEEDED(hr); return d->socketState == QAbstractSocket::ConnectedState; @@ -315,50 +317,53 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr<IHostName> hostAddress; + hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() { + HRESULT hr; + ComPtr<IHostName> hostAddress; - if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { - ComPtr<IHostNameFactory> hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - Q_ASSERT_SUCCEEDED(hr); - const QString addressString = address.toString(); - HStringReference addressRef(reinterpret_cast<LPCWSTR>(addressString.utf16())); - hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_FALSE_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); - } + if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { + ComPtr<IHostNameFactory> hostNameFactory; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), + &hostNameFactory); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); + const QString addressString = address.toString(); + HStringReference addressRef(reinterpret_cast<LPCWSTR>(addressString.utf16())); + hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); + } - QString portQString = port ? QString::number(port) : QString(); - HStringReference portString(reinterpret_cast<LPCWSTR>(portQString.utf16())); + QString portQString = port ? QString::number(port) : QString(); + HStringReference portString(reinterpret_cast<LPCWSTR>(portQString.utf16())); - ComPtr<IAsyncAction> op; - if (d->socketType == QAbstractSocket::TcpSocket) { - if (!d->tcpListener) { - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), - &d->tcpListener); - Q_ASSERT_SUCCEEDED(hr); - } + ComPtr<IAsyncAction> op; + if (d->socketType == QAbstractSocket::TcpSocket) { + if (!d->tcpListener) { + hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), + &d->tcpListener); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); + } - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - return d->tcpListener->add_ConnectionReceived( + hr = d->tcpListener->add_ConnectionReceived( Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); - }); - Q_ASSERT_SUCCEEDED(hr); - hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } else if (d->socketType == QAbstractSocket::UdpSocket) { - hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } - if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", - qPrintable(address.toString()), port, socketDescription(this).constData()); - return false; - } - Q_ASSERT_SUCCEEDED(hr); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); + hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); + } else if (d->socketType == QAbstractSocket::UdpSocket) { + hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); + } + if (hr == E_ACCESSDENIED) { + qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", + qPrintable(address.toString()), port, socketDescription(this).constData()); + return hr; + } + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); - hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(op); + hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register bind callback"); + hr = QWinRTFunctions::await(op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::BoundState; @@ -410,7 +415,9 @@ int QNativeSocketEngine::accept() socketDescription(this).constData()); return -1; } - hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([d, op]() { + return op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "accept(): Failed to set socket read callback (%s).", socketDescription(this).constData()); @@ -781,18 +788,22 @@ void QNativeSocketEngine::establishRead() Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr<IInputStream> stream; - hr = d->tcpSocket()->get_InputStream(&stream); - RETURN_VOID_IF_FAILED("Failed to get socket input stream"); + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + ComPtr<IInputStream> stream; + HRESULT hr = d->tcpSocket()->get_InputStream(&stream); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to get socket input stream"); - ComPtr<IBuffer> buffer; - hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - Q_ASSERT_SUCCEEDED(hr); + ComPtr<IBuffer> buffer; + hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to create buffer"); - ComPtr<IAsyncBufferOperation> op; - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); - RETURN_VOID_IF_FAILED("Failed to initiate socket read"); - hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + ComPtr<IAsyncBufferOperation> op; + hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to initiate socket read"); + hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to register read callback"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); } @@ -814,7 +825,10 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket); Q_ASSERT_SUCCEEDED(hr); socketDescriptor = qintptr(socket.Detach()); - hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + hr = QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + return hr; + }); Q_ASSERT_SUCCEEDED(hr); break; } @@ -1242,7 +1256,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async // that the connection was closed. The socket cannot be closed here, as the subsequent read // might fail then. if (status == Error || status == Canceled) { - setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString); + setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); socketState = QAbstractSocket::UnconnectedState; if (notifyOnRead) emit q->readReady(); @@ -1261,7 +1275,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async // the closing of the socket won't be communicated to the caller. So only the error is set. The // actual socket close happens inside of read. if (!bufferLength) { - setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString); + setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); socketState = QAbstractSocket::UnconnectedState; if (notifyOnRead) emit q->readReady(); @@ -1307,7 +1321,9 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async socketDescription(q).constData()); return S_OK; } - hr = op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([op, this]() { + return op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).", socketDescription(q).constData()); |