summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/access.pri6
-rw-r--r--src/network/access/qhttpnetworkreply.cpp5
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp40
-rw-r--r--src/network/access/qnetworkaccessmanager.h1
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h7
-rw-r--r--src/network/access/qnetworkdiskcache.cpp2
-rw-r--r--src/network/access/qnetworkfile.cpp (renamed from src/network/kernel/qnetworkfunctions_wince.h)96
-rw-r--r--src/network/access/qnetworkfile_p.h79
-rw-r--r--src/network/access/qnetworkreplyfileimpl.cpp150
-rw-r--r--src/network/access/qnetworkreplyfileimpl_p.h12
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp15
-rw-r--r--src/network/access/qspdyprotocolhandler.cpp8
-rw-r--r--src/network/kernel/qauthenticator.cpp6
-rw-r--r--src/network/kernel/qhostaddress.cpp120
-rw-r--r--src/network/kernel/qhostaddress.h12
-rw-r--r--src/network/kernel/qhostinfo_win.cpp11
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp8
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp19
-rw-r--r--src/network/socket/qabstractsocket.cpp79
-rw-r--r--src/network/socket/qabstractsocket_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_p.h14
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp46
-rw-r--r--src/network/socket/qsocks5socketengine.cpp4
-rw-r--r--src/network/socket/qtcpserver.cpp5
-rw-r--r--src/network/socket/qudpsocket.cpp3
-rw-r--r--src/network/socket/socket.pri11
-rw-r--r--src/network/ssl/qsslconfiguration.cpp48
-rw-r--r--src/network/ssl/qsslconfiguration.h3
-rw-r--r--src/network/ssl/qsslconfiguration_p.h3
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp22
-rw-r--r--src/network/ssl/qsslsocket.cpp27
-rw-r--r--src/network/ssl/qsslsocket.h2
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp73
-rw-r--r--src/network/ssl/qsslsocket_openssl_android.cpp1
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp16
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h16
-rw-r--r--src/network/ssl/qsslsocket_p.h5
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp4
39 files changed, 622 insertions, 362 deletions
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 42c7c80f3b..17897ca869 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -37,7 +37,8 @@ HEADERS += \
access/qnetworkdiskcache.h \
access/qhttpthreaddelegate_p.h \
access/qhttpmultipart.h \
- access/qhttpmultipart_p.h
+ access/qhttpmultipart_p.h \
+ access/qnetworkfile_p.h
SOURCES += \
access/qftp.cpp \
@@ -68,7 +69,8 @@ SOURCES += \
access/qabstractnetworkcache.cpp \
access/qnetworkdiskcache.cpp \
access/qhttpthreaddelegate.cpp \
- access/qhttpmultipart.cpp
+ access/qhttpmultipart.cpp \
+ access/qnetworkfile.cpp
mac: LIBS_PRIVATE += -framework Security
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 3601c36bc2..24ada3a81f 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -484,8 +484,7 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
}
// is this a valid reply?
- if (fragment.length() >= 5 && !fragment.startsWith("HTTP/"))
- {
+ if (fragment.length() == 5 && !fragment.startsWith("HTTP/")) {
fragment.clear();
return -1;
}
@@ -739,6 +738,8 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff
#ifndef QT_NO_COMPRESS
int QHttpNetworkReplyPrivate::initializeInflateStream()
{
+ Q_ASSERT(inflateStrm);
+
inflateStrm->zalloc = Z_NULL;
inflateStrm->zfree = Z_NULL;
inflateStrm->opaque = Z_NULL;
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index d2b1a8a912..ed586c1de5 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1523,27 +1523,35 @@ void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
manager->d_func()->objectCache.clear();
manager->d_func()->authenticationManager->clearCache();
- if (manager->d_func()->httpThread) {
- manager->d_func()->httpThread->quit();
- manager->d_func()->httpThread->wait(5000);
- if (manager->d_func()->httpThread->isFinished())
- delete manager->d_func()->httpThread;
- else
- QObject::connect(manager->d_func()->httpThread, SIGNAL(finished()), manager->d_func()->httpThread, SLOT(deleteLater()));
- manager->d_func()->httpThread = 0;
- }
+ manager->d_func()->destroyThread();
}
QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
{
- if (httpThread) {
- httpThread->quit();
- httpThread->wait(5000);
- if (httpThread->isFinished())
- delete httpThread;
+ destroyThread();
+}
+
+QThread * QNetworkAccessManagerPrivate::createThread()
+{
+ if (!thread) {
+ thread = new QThread;
+ thread->setObjectName(QStringLiteral("QNetworkAccessManager thread"));
+ thread->start();
+ }
+ Q_ASSERT(thread);
+ return thread;
+}
+
+void QNetworkAccessManagerPrivate::destroyThread()
+{
+ if (thread) {
+ thread->quit();
+ thread->wait(5000);
+ if (thread->isFinished())
+ delete thread;
else
- QObject::connect(httpThread, SIGNAL(finished()), httpThread, SLOT(deleteLater()));
- httpThread = 0;
+ QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
+ thread = 0;
}
}
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 4efa30df49..9d02fd7c34 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -172,6 +172,7 @@ private:
friend class QNetworkReplyImplPrivate;
friend class QNetworkReplyHttpImpl;
friend class QNetworkReplyHttpImplPrivate;
+ friend class QNetworkReplyFileImpl;
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 413de2a4fe..48270f0c17 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -74,7 +74,7 @@ class QNetworkAccessManagerPrivate: public QObjectPrivate
public:
QNetworkAccessManagerPrivate()
: networkCache(0), cookieJar(0),
- httpThread(0),
+ thread(0),
#ifndef QT_NO_NETWORKPROXY
proxyFactory(0),
#endif
@@ -107,6 +107,9 @@ public:
}
~QNetworkAccessManagerPrivate();
+ QThread * createThread();
+ void destroyThread();
+
void _q_replyFinished();
void _q_replyEncrypted();
void _q_replySslErrors(const QList<QSslError> &errors);
@@ -158,7 +161,7 @@ public:
QNetworkCookieJar *cookieJar;
- QThread *httpThread;
+ QThread *thread;
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 99e67cb463..68c962636e 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -421,7 +421,7 @@ QIODevice *QNetworkDiskCache::data(const QUrl &url)
// ### verify that QFile uses the fd size and not the file name
qint64 size = file->size() - file->pos();
const uchar *p = 0;
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_INTEGRITY)
p = file->map(file->pos(), size);
#endif
if (p) {
diff --git a/src/network/kernel/qnetworkfunctions_wince.h b/src/network/access/qnetworkfile.cpp
index 0e464a47f3..374dd26e2e 100644
--- a/src/network/kernel/qnetworkfunctions_wince.h
+++ b/src/network/access/qnetworkfile.cpp
@@ -37,60 +37,56 @@
**
****************************************************************************/
-#ifndef QNETWORKFUNCTIONS_WINCE_H
-#define QNETWORKFUNCTIONS_WINCE_H
+#include "qnetworkfile_p.h"
-#if 0
-#pragma qt_sync_stop_processing
-#endif
+#include <QtCore/QDebug>
+#include <QNetworkReply>
+#include <QtCore/QDateTime>
+#include <QtCore/QFileInfo>
+#include <QtCore/QMetaObject>
+#include <QtCore/QCoreApplication>
-#ifdef Q_OS_WINCE
+QT_BEGIN_NAMESPACE
-#include <qt_windows.h>
+QNetworkFile::QNetworkFile()
+ : QFile()
+{
+}
-QT_BEGIN_NAMESPACE
+QNetworkFile::QNetworkFile(const QString &name)
+ : QFile(name)
+{
+}
-DECLARE_HANDLE(SC_HANDLE);
-typedef enum _SC_ENUM_TYPE {
- SC_ENUM_PROCESS_INFO = 0
-} SC_ENUM_TYPE;
-#define SC_MANAGER_CONNECT 0x0001
-#define SC_MANAGER_CREATE_SERVICE 0x0002
-#define SC_MANAGER_ENUMERATE_SERVICE 0x0004
-#define SERVICE_ACTIVE 0x00000001
-#define SERVICE_INACTIVE 0x00000002
-#define SERVICE_STATE_ALL (SERVICE_ACTIVE | \
- SERVICE_INACTIVE)
-typedef struct _SERVICE_STATUS_PROCESS {
- DWORD dwServiceType;
- DWORD dwCurrentState;
- DWORD dwControlsAccepted;
- DWORD dwWin32ExitCode;
- DWORD dwServiceSpecificExitCode;
- DWORD dwCheckPoint;
- DWORD dwWaitHint;
- DWORD dwProcessId;
- DWORD dwServiceFlags;
-} SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
-typedef struct _ENUM_SERVICE_STATUS_PROCESSA {
- LPSTR lpServiceName;
- LPSTR lpDisplayName;
- SERVICE_STATUS_PROCESS ServiceStatusProcess;
-} ENUM_SERVICE_STATUS_PROCESSA, *LPENUM_SERVICE_STATUS_PROCESSA;
-typedef struct _ENUM_SERVICE_STATUS_PROCESSW {
- LPWSTR lpServiceName;
- LPWSTR lpDisplayName;
- SERVICE_STATUS_PROCESS ServiceStatusProcess;
-} ENUM_SERVICE_STATUS_PROCESSW, *LPENUM_SERVICE_STATUS_PROCESSW;
-#ifdef UNICODE
-typedef ENUM_SERVICE_STATUS_PROCESSW ENUM_SERVICE_STATUS_PROCESS;
-typedef LPENUM_SERVICE_STATUS_PROCESSW LPENUM_SERVICE_STATUS_PROCESS;
-#else
-typedef ENUM_SERVICE_STATUS_PROCESSA ENUM_SERVICE_STATUS_PROCESS;
-typedef LPENUM_SERVICE_STATUS_PROCESSA LPENUM_SERVICE_STATUS_PROCESS;
-#endif // UNICODE
+void QNetworkFile::open()
+{
+ bool opened = false;
+ QFileInfo fi(fileName());
+ if (fi.isDir()) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend",
+ "Cannot open %1: Path is a directory").arg(fileName());
+ error(QNetworkReply::ContentOperationNotPermittedError, msg);
+ } else {
+ headerRead(QNetworkRequest::LastModifiedHeader, QVariant::fromValue(fi.lastModified()));
+ headerRead(QNetworkRequest::ContentLengthHeader, QVariant::fromValue(fi.size()));
+ opened = QFile::open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+ if (!opened) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend",
+ "Error opening %1: %2").arg(fileName(), errorString());
+ if (exists())
+ error(QNetworkReply::ContentAccessDenied, msg);
+ else
+ error(QNetworkReply::ContentNotFoundError, msg);
+ }
+ }
+ finished(opened);
+}
-QT_END_NAMESPACE
+void QNetworkFile::close()
+{
+ // This override is needed because 'using' keyword cannot be used for slots. And the base
+ // function is not an invokable/slot function.
+ QFile::close();
+}
-#endif // Q_OS_WINCE
-#endif // QNETWORKFUNCTIONS_WINCE_H
+QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkfile_p.h b/src/network/access/qnetworkfile_p.h
new file mode 100644
index 0000000000..7794c0f18a
--- /dev/null
+++ b/src/network/access/qnetworkfile_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKFILE_H
+#define QNETWORKFILE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Network Access API. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QFile>
+#include <qnetworkreply.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkFile : public QFile
+{
+ Q_OBJECT
+public:
+ QNetworkFile();
+ QNetworkFile(const QString &name);
+ using QFile::open;
+
+public Q_SLOTS:
+ void open();
+ void close() Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ void finished(bool ok);
+ void headerRead(QNetworkRequest::KnownHeaders header, const QVariant &value);
+ void error(QNetworkReply::NetworkError error, const QString &message);
+};
+
+QT_END_NAMESPACE
+
+#endif // QNETWORKFILE_H
diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp
index 36bc4b41df..ef319ebf0d 100644
--- a/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/src/network/access/qnetworkreplyfileimpl.cpp
@@ -40,31 +40,45 @@
#include "qnetworkreplyfileimpl_p.h"
#include "QtCore/qdatetime.h"
+#include "qnetworkaccessmanager_p.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include "qnetworkfile_p.h"
+#include "qnetworkrequest.h"
QT_BEGIN_NAMESPACE
QNetworkReplyFileImplPrivate::QNetworkReplyFileImplPrivate()
- : QNetworkReplyPrivate(), realFileSize(0)
+ : QNetworkReplyPrivate(), managerPrivate(0), realFile(0)
{
+ qRegisterMetaType<QNetworkRequest::KnownHeaders>();
+ qRegisterMetaType<QNetworkReply::NetworkError>();
}
QNetworkReplyFileImpl::~QNetworkReplyFileImpl()
{
+ QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func();
+ if (d->realFile) {
+ if (d->realFile->thread() == QThread::currentThread())
+ delete d->realFile;
+ else
+ QMetaObject::invokeMethod(d->realFile, "deleteLater", Qt::QueuedConnection);
+ }
}
-QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op)
- : QNetworkReply(*new QNetworkReplyFileImplPrivate(), parent)
+QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, const QNetworkRequest &req, const QNetworkAccessManager::Operation op)
+ : QNetworkReply(*new QNetworkReplyFileImplPrivate(), manager)
{
setRequest(req);
setUrl(req.url());
setOperation(op);
- setFinished(true);
QNetworkReply::open(QIODevice::ReadOnly);
QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func();
+ d->managerPrivate = manager->d_func();
+
QUrl url = req.url();
if (url.host() == QLatin1String("localhost"))
url.setHost(QString());
@@ -77,7 +91,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
setError(QNetworkReply::ProtocolInvalidOperationError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ fileOpenFinished(false);
return;
}
#endif
@@ -85,7 +99,6 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
url.setPath(QLatin1String("/"));
setUrl(url);
-
QString fileName = url.toLocalFile();
if (fileName.isEmpty()) {
const QString scheme = url.scheme();
@@ -101,68 +114,85 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ
}
}
- QFileInfo fi(fileName);
- if (fi.isDir()) {
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString());
- setError(QNetworkReply::ContentOperationNotPermittedError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError));
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
- return;
- }
-
- d->realFile.setFileName(fileName);
- bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
-
- // could we open the file?
- if (!opened) {
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
- .arg(d->realFile.fileName(), d->realFile.errorString());
-
- if (d->realFile.exists()) {
- setError(QNetworkReply::ContentAccessDenied, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied));
- } else {
- setError(QNetworkReply::ContentNotFoundError, msg);
+ if (req.attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) { // Asynchronous open
+ auto realFile = new QNetworkFile(fileName);
+ connect(realFile, &QNetworkFile::headerRead, this, &QNetworkReplyFileImpl::setHeader,
+ Qt::QueuedConnection);
+ connect(realFile, &QNetworkFile::error, this, &QNetworkReplyFileImpl::setError,
+ Qt::QueuedConnection);
+ connect(realFile, SIGNAL(finished(bool)), SLOT(fileOpenFinished(bool)),
+ Qt::QueuedConnection);
+
+ realFile->moveToThread(d->managerPrivate->createThread());
+ QMetaObject::invokeMethod(realFile, "open", Qt::QueuedConnection);
+
+ d->realFile = realFile;
+ } else { // Synch open
+ setFinished(true);
+
+ QFileInfo fi(fileName);
+ if (fi.isDir()) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString());
+ setError(QNetworkReply::ContentOperationNotPermittedError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
- Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError));
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError));
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ return;
+ }
+ d->realFile = new QFile(fileName, this);
+ bool opened = d->realFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
+
+ // could we open the file?
+ if (!opened) {
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2")
+ .arg(d->realFile->fileName(), d->realFile->errorString());
+
+ if (fi.exists()) {
+ setError(QNetworkReply::ContentAccessDenied, msg);
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied));
+ } else {
+ setError(QNetworkReply::ContentNotFoundError, msg);
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError));
+ }
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+ return;
}
+ setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified());
+ setHeader(QNetworkRequest::ContentLengthHeader, fi.size());
+
+ QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection,
+ Q_ARG(qint64, fi.size()), Q_ARG(qint64, fi.size()));
+ QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
- return;
}
-
- setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified());
- d->realFileSize = fi.size();
- setHeader(QNetworkRequest::ContentLengthHeader, d->realFileSize);
-
- QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection,
- Q_ARG(qint64, d->realFileSize), Q_ARG(qint64, d->realFileSize));
- QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
void QNetworkReplyFileImpl::close()
{
Q_D(QNetworkReplyFileImpl);
QNetworkReply::close();
- d->realFile.close();
+ if (d->realFile) {
+ if (d->realFile->thread() == thread())
+ d->realFile->close();
+ else
+ QMetaObject::invokeMethod(d->realFile, "close", Qt::QueuedConnection);
+ }
}
void QNetworkReplyFileImpl::abort()
{
- Q_D(QNetworkReplyFileImpl);
- QNetworkReply::close();
- d->realFile.close();
+ close();
}
qint64 QNetworkReplyFileImpl::bytesAvailable() const
{
Q_D(const QNetworkReplyFileImpl);
- if (!d->realFile.isOpen())
+ if (!d->isFinished || !d->realFile || !d->realFile->isOpen())
return QNetworkReply::bytesAvailable();
- return QNetworkReply::bytesAvailable() + d->realFile.bytesAvailable();
+ return QNetworkReply::bytesAvailable() + d->realFile->bytesAvailable();
}
bool QNetworkReplyFileImpl::isSequential () const
@@ -172,8 +202,9 @@ bool QNetworkReplyFileImpl::isSequential () const
qint64 QNetworkReplyFileImpl::size() const
{
- Q_D(const QNetworkReplyFileImpl);
- return d->realFileSize;
+ bool ok;
+ int size = header(QNetworkRequest::ContentLengthHeader).toInt(&ok);
+ return ok ? size : 0;
}
/*!
@@ -182,11 +213,11 @@ qint64 QNetworkReplyFileImpl::size() const
qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen)
{
Q_D(QNetworkReplyFileImpl);
- if (!d->realFile.isOpen())
+ if (!d->isFinished || !d->realFile || !d->realFile->isOpen())
return -1;
- qint64 ret = d->realFile.read(data, maxlen);
- if (bytesAvailable() == 0 && d->realFile.isOpen())
- d->realFile.close();
+ qint64 ret = d->realFile->read(data, maxlen);
+ if (bytesAvailable() == 0)
+ d->realFile->close();
if (ret == 0 && bytesAvailable() == 0)
return -1;
else {
@@ -196,6 +227,17 @@ qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen)
}
}
+void QNetworkReplyFileImpl::fileOpenFinished(bool isOpen)
+{
+ setFinished(true);
+ if (isOpen) {
+ const auto fileSize = size();
+ Q_EMIT metaDataChanged();
+ Q_EMIT downloadProgress(fileSize, fileSize);
+ Q_EMIT readyRead();
+ }
+ Q_EMIT finished();
+}
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplyfileimpl_p.h b/src/network/access/qnetworkreplyfileimpl_p.h
index bac00881a8..1f1be40bc8 100644
--- a/src/network/access/qnetworkreplyfileimpl_p.h
+++ b/src/network/access/qnetworkreplyfileimpl_p.h
@@ -59,13 +59,12 @@
QT_BEGIN_NAMESPACE
-
class QNetworkReplyFileImplPrivate;
class QNetworkReplyFileImpl: public QNetworkReply
{
Q_OBJECT
public:
- QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op);
+ QNetworkReplyFileImpl(QNetworkAccessManager *manager, const QNetworkRequest &req, const QNetworkAccessManager::Operation op);
~QNetworkReplyFileImpl();
virtual void abort() Q_DECL_OVERRIDE;
@@ -77,6 +76,9 @@ public:
virtual qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
+private Q_SLOTS:
+ void fileOpenFinished(bool isOpen);
+
Q_DECLARE_PRIVATE(QNetworkReplyFileImpl)
};
@@ -85,12 +87,14 @@ class QNetworkReplyFileImplPrivate: public QNetworkReplyPrivate
public:
QNetworkReplyFileImplPrivate();
- QFile realFile;
- qint64 realFileSize;
+ QNetworkAccessManagerPrivate *managerPrivate;
+ QPointer<QFile> realFile;
Q_DECLARE_PUBLIC(QNetworkReplyFileImpl)
};
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders)
+
#endif // QNETWORKREPLYFILEIMPL_H
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index e1323527f6..6b77ab303f 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -617,17 +617,10 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
thread->setObjectName(QStringLiteral("Qt HTTP synchronous thread"));
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
- } else if (!managerPrivate->httpThread) {
+ } else {
// We use the manager-global thread.
// At some point we could switch to having multiple threads if it makes sense.
- managerPrivate->httpThread = new QThread();
- managerPrivate->httpThread->setObjectName(QStringLiteral("Qt HTTP thread"));
- managerPrivate->httpThread->start();
-
- thread = managerPrivate->httpThread;
- } else {
- // Asynchronous request, thread already exists
- thread = managerPrivate->httpThread;
+ thread = managerPrivate->createThread();
}
QUrl url = newHttpRequest.url();
@@ -1137,8 +1130,8 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt
cookedHeaders.clear();
- if (managerPrivate->httpThread)
- managerPrivate->httpThread->disconnect();
+ if (managerPrivate->thread)
+ managerPrivate->thread->disconnect();
// Recurse
QMetaObject::invokeMethod(q, "start", Qt::QueuedConnection,
diff --git a/src/network/access/qspdyprotocolhandler.cpp b/src/network/access/qspdyprotocolhandler.cpp
index 1a6dd04ecb..4641516549 100644
--- a/src/network/access/qspdyprotocolhandler.cpp
+++ b/src/network/access/qspdyprotocolhandler.cpp
@@ -458,7 +458,7 @@ bool QSpdyProtocolHandler::uncompressHeader(const QByteArray &input, QByteArray
break;
}
default: {
- qWarning() << "got unexpected zlib return value:" << zlibRet;
+ qWarning("got unexpected zlib return value: %d", zlibRet);
return false;
}
}
@@ -849,7 +849,7 @@ void QSpdyProtocolHandler::handleControlFrame(const QByteArray &frameHeaders) //
break;
}
default:
- qWarning() << "cannot handle frame of type" << type;
+ qWarning("cannot handle frame of type %d", int(type));
}
}
@@ -1085,7 +1085,7 @@ void QSpdyProtocolHandler::handleSETTINGS(char flags, quint32 /*length*/, const
break;
}
default:
- qWarning() << "found unknown settings value" << value;
+ qWarning("found unknown settings value %u", uint(value));
}
}
}
@@ -1124,7 +1124,7 @@ void QSpdyProtocolHandler::handleGOAWAY(char /*flags*/, quint32 /*length*/,
break;
}
default:
- qWarning() << "unexpected status code" << statusCode;
+ qWarning("unexpected status code %d", int(statusCode));
errorCode = QNetworkReply::ProtocolUnknownError;
}
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index 78753a7393..10c0dccb9e 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -1453,15 +1453,9 @@ static bool q_NTLM_SSPI_library_load()
if (pSecurityFunctionTable == NULL) {
securityDLLHandle = LoadLibrary(L"secur32.dll");
if (securityDLLHandle != NULL) {
-#if defined(Q_OS_WINCE)
- INIT_SECURITY_INTERFACE pInitSecurityInterface =
- (INIT_SECURITY_INTERFACE)GetProcAddress(securityDLLHandle,
- L"InitSecurityInterfaceW");
-#else
INIT_SECURITY_INTERFACE pInitSecurityInterface =
(INIT_SECURITY_INTERFACE)GetProcAddress(securityDLLHandle,
"InitSecurityInterfaceW");
-#endif
if (pInitSecurityInterface != NULL)
pSecurityFunctionTable = pInitSecurityInterface();
}
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 0dbe1112cd..757a6ad0b0 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
// sockaddr_in6 size changed between old and new SDK
// Only the new version is the correct one, so always
// use this structure.
-#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
+#if defined(Q_OS_WINRT)
# if !defined(u_char)
# define u_char unsigned char
# endif
@@ -152,20 +152,37 @@ void QHostAddressPrivate::setAddress(quint32 a_)
/// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a;
/// returns true if the address was one of those
-static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6)
+static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6, const QHostAddress::ConversionMode mode)
{
+ if (mode == QHostAddress::StrictConversion)
+ return false;
+
const uchar *ptr = a6.c;
if (qFromUnaligned<quint64>(ptr) != 0)
return false;
- if (qFromBigEndian<quint32>(ptr + 8) == 0) {
- // is it AnyIPv6?
- a = 0;
- return qFromBigEndian<quint32>(ptr + 12) == 0;
+
+ const quint32 mid = qFromBigEndian<quint32>(ptr + 8);
+ if ((mid == 0xffff) && (mode & QHostAddress::ConvertV4MappedToIPv4)) {
+ a = qFromBigEndian<quint32>(ptr + 12);
+ return true;
}
- if (qFromBigEndian<quint32>(ptr + 8) != 0xFFFF)
+ if (mid != 0)
return false;
- a = qFromBigEndian<quint32>(ptr + 12);
- return true;
+
+ const quint32 low = qFromBigEndian<quint32>(ptr + 12);
+ if ((low == 0) && (mode & QHostAddress::ConvertUnspecifiedAddress)) {
+ a = 0;
+ return true;
+ }
+ if ((low == 1) && (mode & QHostAddress::ConvertLocalHost)) {
+ a = INADDR_LOOPBACK;
+ return true;
+ }
+ if ((low != 1) && (mode & QHostAddress::ConvertV4CompatToIPv4)) {
+ a = low;
+ return true;
+ }
+ return false;
}
void QHostAddressPrivate::setAddress(const quint8 *a_)
@@ -174,7 +191,8 @@ void QHostAddressPrivate::setAddress(const quint8 *a_)
isParsed = true;
memcpy(a6.c, a_, sizeof(a6));
a = 0;
- convertToIpv4(a, a6);
+ convertToIpv4(a, a6, (QHostAddress::ConvertV4MappedToIPv4
+ | QHostAddress::ConvertUnspecifiedAddress));
}
void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
@@ -386,6 +404,20 @@ void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol prot
\value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
*/
+/*! \enum QHostAddress::ConversionModeFlag
+
+ \since 5.8
+
+ \value StrictConversion Don't convert IPv6 addresses to IPv4 when comparing two QHostAddress objects of different protocols, so they will always be considered different.
+ \value ConvertV4MappedToIPv4 Convert IPv4-mapped IPv6 addresses (RFC 4291 sect. 2.5.5.2) when comparing. Therefore QHostAddress("::ffff:192.168.1.1") will compare equal to QHostAddress("192.168.1.1").
+ \value ConvertV4CompatToIPv4 Convert IPv4-compatible IPv6 addresses (RFC 4291 sect. 2.5.5.1) when comparing. Therefore QHostAddress("::192.168.1.1") will compare equal to QHostAddress("192.168.1.1").
+ \value ConvertLocalHost Convert the IPv6 loopback addresses to its IPv4 equivalent when comparing. Therefore e.g. QHostAddress("::1") will compare equal to QHostAddress("127.0.0.1").
+ \value ConvertUnspecifiedAddress All unspecified addresses will compare equal, namely AnyIPv4, AnyIPv6 and Any.
+ \value TolerantConversion Sets all three preceding flags.
+
+ \sa isEqual()
+ */
+
/*! Constructs a null host address object, i.e. an address which is not valid for any host or interface.
\sa clear()
@@ -691,7 +723,9 @@ quint32 QHostAddress::toIPv4Address(bool *ok) const
quint32 dummy;
if (ok)
*ok = d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol
- || (d->protocol == QAbstractSocket::IPv6Protocol && convertToIpv4(dummy, d->a6));
+ || (d->protocol == QAbstractSocket::IPv6Protocol
+ && convertToIpv4(dummy, d->a6, ConversionMode(QHostAddress::ConvertV4MappedToIPv4
+ | QHostAddress::ConvertUnspecifiedAddress)));
return d->a;
}
@@ -813,19 +847,73 @@ void QHostAddress::setScopeId(const QString &id)
/*!
Returns \c true if this host address is the same as the \a other address
- given; otherwise returns \c false.
+ given; otherwise returns \c false. This operator just calls isEqual(other, StrictConversion).
+
+ \sa isEqual()
*/
bool QHostAddress::operator==(const QHostAddress &other) const
{
+ return isEqual(other, StrictConversion);
+}
+
+/*!
+ \since 5.8
+
+ Returns \c true if this host address is the same as the \a other address
+ given; otherwise returns \c false.
+
+ The parameter \a mode controls which conversions are preformed between addresses
+ of differing protocols. If no \a mode is given, \c TolerantConversion is performed
+ by default.
+
+ \sa ConversionMode, operator==()
+ */
+bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const
+{
QT_ENSURE_PARSED(this);
QT_ENSURE_PARSED(&other);
- if (d->protocol == QAbstractSocket::IPv4Protocol)
- return other.d->protocol == QAbstractSocket::IPv4Protocol && d->a == other.d->a;
+ if (d->protocol == QAbstractSocket::IPv4Protocol) {
+ switch (other.d->protocol) {
+ case QAbstractSocket::IPv4Protocol:
+ return d->a == other.d->a;
+ case QAbstractSocket::IPv6Protocol:
+ quint32 a4;
+ return convertToIpv4(a4, other.d->a6, mode) && (a4 == d->a);
+ case QAbstractSocket::AnyIPProtocol:
+ return (mode & QHostAddress::ConvertUnspecifiedAddress) && d->a == 0;
+ case QAbstractSocket::UnknownNetworkLayerProtocol:
+ return false;
+ }
+ }
+
if (d->protocol == QAbstractSocket::IPv6Protocol) {
- return other.d->protocol == QAbstractSocket::IPv6Protocol
- && memcmp(&d->a6, &other.d->a6, sizeof(Q_IPV6ADDR)) == 0;
+ switch (other.d->protocol) {
+ case QAbstractSocket::IPv4Protocol:
+ quint32 a4;
+ return convertToIpv4(a4, d->a6, mode) && (a4 == other.d->a);
+ case QAbstractSocket::IPv6Protocol:
+ return memcmp(&d->a6, &other.d->a6, sizeof(Q_IPV6ADDR)) == 0;
+ case QAbstractSocket::AnyIPProtocol:
+ return (mode & QHostAddress::ConvertUnspecifiedAddress)
+ && (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
+ case QAbstractSocket::UnknownNetworkLayerProtocol:
+ return false;
+ }
+ }
+
+ if ((d->protocol == QAbstractSocket::AnyIPProtocol)
+ && (mode & QHostAddress::ConvertUnspecifiedAddress)) {
+ switch (other.d->protocol) {
+ case QAbstractSocket::IPv4Protocol:
+ return other.d->a == 0;
+ case QAbstractSocket::IPv6Protocol:
+ return (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
+ default:
+ break;
+ }
}
+
return d->protocol == other.d->protocol;
}
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index 8236a71986..8cf6876511 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -79,6 +79,16 @@ public:
AnyIPv6,
AnyIPv4
};
+ enum ConversionModeFlag {
+ ConvertV4MappedToIPv4 = 1,
+ ConvertV4CompatToIPv4 = 2,
+ ConvertUnspecifiedAddress = 4,
+ ConvertLocalHost = 8,
+ TolerantConversion = 0xff,
+
+ StrictConversion = 0
+ };
+ Q_DECLARE_FLAGS(ConversionMode, ConversionModeFlag)
QHostAddress();
explicit QHostAddress(quint32 ip4Addr);
@@ -118,6 +128,7 @@ public:
QString scopeId() const;
void setScopeId(const QString &id);
+ bool isEqual(const QHostAddress &address, ConversionMode mode = TolerantConversion) const;
bool operator ==(const QHostAddress &address) const;
bool operator ==(SpecialAddress address) const;
inline bool operator !=(const QHostAddress &address) const
@@ -139,6 +150,7 @@ public:
protected:
QScopedPointer<QHostAddressPrivate> d;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QHostAddress::ConversionMode)
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QHostAddress)
inline bool operator ==(QHostAddress::SpecialAddress address1, const QHostAddress &address2)
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index cc6102a713..1d34ae8277 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -82,11 +82,7 @@ static void resolveLibrary()
{
// Attempt to resolve getaddrinfo(); without it we'll have to fall
// back to gethostbyname(), which has no IPv6 support.
-#if defined(Q_OS_WINCE)
- local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getaddrinfo");
- local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "freeaddrinfo");
- local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getnameinfo");
-#elif defined (Q_OS_WINRT)
+#if defined (Q_OS_WINRT)
local_getaddrinfo = (getaddrinfoProto) &getaddrinfo;
local_freeaddrinfo = (freeaddrinfoProto) &freeaddrinfo;
local_getnameinfo = (getnameinfoProto) getnameinfo;
@@ -115,11 +111,6 @@ static void translateWSAError(int error, QHostInfo *results)
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
-#if defined(Q_OS_WINCE)
- static QBasicMutex qPrivCEMutex;
- QMutexLocker locker(&qPrivCEMutex);
-#endif
-
QSysInfo::machineHostName(); // this initializes ws2_32.dll
// Load res_init on demand.
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 0a82eac417..3002b2497b 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -81,19 +81,11 @@ static void resolveLibs()
HINSTANCE iphlpapiHnd = GetModuleHandle(L"iphlpapi");
Q_ASSERT(iphlpapiHnd);
-#if defined(Q_OS_WINCE)
- // since Windows Embedded Compact 7
- ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceIndexToLuid");
- ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToNameW");
- ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToIndex");
- ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceNameToLuidW");
-#else
// since Windows Vista
ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceIndexToLuid");
ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW");
ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToIndex");
ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceNameToLuidW");
-#endif
done = true;
}
}
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index fe9f088062..a37585b5cd 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -53,7 +53,6 @@
#include <qt_windows.h>
#include <wininet.h>
#include <lmcons.h>
-#include "qnetworkfunctions_wince.h"
/*
* Information on the WinHTTP DLL:
@@ -123,7 +122,6 @@ static PtrWinHttpGetIEProxyConfigForCurrentUser ptrWinHttpGetIEProxyConfigForCur
static PtrWinHttpCloseHandle ptrWinHttpCloseHandle = 0;
-#ifndef Q_OS_WINCE
static bool currentProcessIsService()
{
typedef BOOL (WINAPI *PtrGetUserName)(LPTSTR lpBuffer, LPDWORD lpnSize);
@@ -153,7 +151,6 @@ static bool currentProcessIsService()
}
return false;
}
-#endif // ! Q_OS_WINCE
static QStringList splitSpaceSemicolon(const QString &source)
{
@@ -359,7 +356,7 @@ static QList<QNetworkProxy> parseServerList(const QNetworkProxyQuery &query, con
return removeDuplicateProxies(result);
}
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(Q_OS_WINRT)
namespace {
class QRegistryWatcher {
public:
@@ -410,7 +407,7 @@ private:
QVector<HKEY> m_registryHandles;
};
} // namespace
-#endif // !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#endif // !defined(Q_OS_WINRT)
class QWindowsSystemProxy
{
@@ -429,7 +426,7 @@ public:
QStringList proxyServerList;
QStringList proxyBypass;
QList<QNetworkProxy> defaultResult;
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(Q_OS_WINRT)
QRegistryWatcher proxySettingsWatcher;
#endif
bool initialized;
@@ -465,7 +462,7 @@ void QWindowsSystemProxy::reset()
void QWindowsSystemProxy::init()
{
bool proxySettingsChanged = false;
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(Q_OS_WINRT)
proxySettingsChanged = proxySettingsWatcher.hasChanged();
#endif
@@ -475,12 +472,7 @@ void QWindowsSystemProxy::init()
reset();
-#ifdef Q_OS_WINCE
- // Windows CE does not have any of the following API
- return;
-#else
-
-#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+#if !defined(Q_OS_WINRT)
proxySettingsWatcher.clear(); // needs reset to trigger a new detection
proxySettingsWatcher.addLocation(HKEY_CURRENT_USER, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"));
proxySettingsWatcher.addLocation(HKEY_LOCAL_MACHINE, QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"));
@@ -568,7 +560,6 @@ void QWindowsSystemProxy::init()
}
functional = isAutoConfig || !proxyServerList.isEmpty();
-#endif
}
QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query)
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 802b623375..03f2ddb968 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -563,6 +563,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
cachedSocketDescriptor(-1),
readBufferMaxSize(0),
isBuffered(false),
+ hasPendingData(false),
connectTimer(0),
disconnectTimer(0),
hostLookupId(-1),
@@ -593,6 +594,7 @@ void QAbstractSocketPrivate::resetSocketLayer()
qDebug("QAbstractSocketPrivate::resetSocketLayer()");
#endif
+ hasPendingData = false;
if (socketEngine) {
socketEngine->close();
socketEngine->disconnect();
@@ -683,14 +685,20 @@ bool QAbstractSocketPrivate::canReadNotification()
qDebug("QAbstractSocketPrivate::canReadNotification()");
#endif
- if (!isBuffered)
- socketEngine->setReadNotificationEnabled(false);
+ if (!isBuffered) {
+ if (hasPendingData) {
+ socketEngine->setReadNotificationEnabled(false);
+ return true;
+ }
+ hasPendingData = true;
+ }
// If buffered, read data from the socket into the read buffer
qint64 newBytes = 0;
if (isBuffered) {
// Return if there is no space in the buffer
if (readBufferMaxSize && buffer.size() >= readBufferMaxSize) {
+ socketEngine->setReadNotificationEnabled(false);
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full");
#endif
@@ -708,11 +716,6 @@ bool QAbstractSocketPrivate::canReadNotification()
return false;
}
newBytes = buffer.size() - newBytes;
-
- // If read buffer is full, disable the read socket notifier.
- if (readBufferMaxSize && buffer.size() == readBufferMaxSize) {
- socketEngine->setReadNotificationEnabled(false);
- }
}
// Only emit readyRead() if there is data available.
@@ -728,10 +731,6 @@ bool QAbstractSocketPrivate::canReadNotification()
return true;
}
- // turn the socket engine off if we've reached the buffer size limit
- if (socketEngine && isBuffered)
- socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
-
return true;
}
@@ -788,12 +787,8 @@ bool QAbstractSocketPrivate::canWriteNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canWriteNotification() flushing");
#endif
- bool dataWasWritten = writeToSocket();
-
- if (socketEngine && writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0)
- socketEngine->setWriteNotificationEnabled(false);
- return dataWasWritten;
+ return writeToSocket();
}
/*! \internal
@@ -833,8 +828,12 @@ bool QAbstractSocketPrivate::writeToSocket()
#endif
// this covers the case when the buffer was empty, but we had to wait for the socket engine to finish
- if (state == QAbstractSocket::ClosingState)
+ if (state == QAbstractSocket::ClosingState) {
q->disconnectFromHost();
+ } else {
+ if (socketEngine)
+ socketEngine->setWriteNotificationEnabled(false);
+ }
return false;
}
@@ -872,8 +871,7 @@ bool QAbstractSocketPrivate::writeToSocket()
emit q->channelBytesWritten(0, written);
}
- if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()
- && !socketEngine->bytesToWrite())
+ if (writeBuffer.isEmpty() && socketEngine && !socketEngine->bytesToWrite())
socketEngine->setWriteNotificationEnabled(false);
if (state == QAbstractSocket::ClosingState)
q->disconnectFromHost();
@@ -1144,12 +1142,10 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
*/
void QAbstractSocketPrivate::_q_testConnection()
{
- if (socketEngine) {
- if (threadData->hasEventDispatcher()) {
- if (connectTimer)
- connectTimer->stop();
- }
+ if (connectTimer)
+ connectTimer->stop();
+ if (socketEngine) {
if (socketEngine->state() == QAbstractSocket::ConnectedState) {
// Fetch the parameters if our connection is completed;
// otherwise, fall out and try the next address.
@@ -1166,11 +1162,6 @@ void QAbstractSocketPrivate::_q_testConnection()
addresses.clear();
}
- if (threadData->hasEventDispatcher()) {
- if (connectTimer)
- connectTimer->stop();
- }
-
#if defined(QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::_q_testConnection() connection failed,"
" checking for alternative addresses");
@@ -2379,11 +2370,6 @@ void QAbstractSocket::abort()
return;
}
#endif
- if (d->connectTimer) {
- d->connectTimer->stop();
- delete d->connectTimer;
- d->connectTimer = 0;
- }
d->abortCalled = true;
close();
@@ -2430,15 +2416,7 @@ bool QAbstractSocket::atEnd() const
// Note! docs copied to QSslSocket::flush()
bool QAbstractSocket::flush()
{
- Q_D(QAbstractSocket);
-#ifndef QT_NO_SSL
- // Manual polymorphism; flush() isn't virtual, but QSslSocket overloads
- // it.
- if (QSslSocket *socket = qobject_cast<QSslSocket *>(this))
- return socket->flush();
-#endif
- Q_CHECK_SOCKETENGINE(false);
- return d->flush();
+ return d_func()->flush();
}
/*! \reimp
@@ -2461,8 +2439,9 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize)
d->setError(d->socketEngine->error(), d->socketEngine->errorString());
d->resetSocketLayer();
d->state = QAbstractSocket::UnconnectedState;
- } else if (!d->socketEngine->isReadNotificationEnabled()) {
+ } else {
// Only do this when there was no error
+ d->hasPendingData = false;
d->socketEngine->setReadNotificationEnabled(true);
}
@@ -2828,12 +2807,12 @@ void QAbstractSocket::setReadBufferSize(qint64 size)
if (d->readBufferMaxSize == size)
return;
d->readBufferMaxSize = size;
- if (!d->emittedReadyRead && d->socketEngine) {
- // ensure that the read notification is enabled if we've now got
- // room in the read buffer
- // but only if we're not inside canReadNotification -- that will take care on its own
- if ((size == 0 || d->buffer.size() < size) && d->state == QAbstractSocket::ConnectedState) // Do not change the notifier unless we are connected.
- d->socketEngine->setReadNotificationEnabled(true);
+
+ // Do not change the notifier unless we are connected.
+ if (d->socketEngine && d->state == QAbstractSocket::ConnectedState) {
+ // Ensure that the read notification is enabled if we've now got
+ // room in the read buffer.
+ d->socketEngine->setReadNotificationEnabled(size == 0 || d->buffer.size() < size);
}
}
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index b718c21ff5..3164c96c1e 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -128,13 +128,12 @@ public:
inline void resolveProxy(quint16 port) { resolveProxy(QString(), port); }
void resetSocketLayer();
- bool flush();
+ virtual bool flush();
bool initSocketLayer(QAbstractSocket::NetworkLayerProtocol protocol);
virtual void configureCreatedSocket();
void startConnectingByName(const QString &host);
void fetchConnectionParameters();
- void setupSocketNotifiers();
bool readFromSocket();
bool writeToSocket();
void emitReadyRead();
@@ -144,6 +143,7 @@ public:
qint64 readBufferMaxSize;
bool isBuffered;
+ bool hasPendingData;
QTimer *connectTimer;
QTimer *disconnectTimer;
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 19e9e1d9b7..5a05d7c98c 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -66,21 +66,20 @@
QT_BEGIN_NAMESPACE
#ifdef Q_OS_WIN
-#define QT_SOCKLEN_T int
-#define QT_SOCKOPTLEN_T int
+# define QT_SOCKLEN_T int
+# define QT_SOCKOPTLEN_T int
// The following definitions are copied from the MinGW header mswsock.h which
// was placed in the public domain. The WSASendMsg and WSARecvMsg functions
// were introduced with Windows Vista, so some Win32 headers are lacking them.
// There are no known versions of Windows CE or Embedded that contain them.
-#ifndef Q_OS_WINCE
# ifndef WSAID_WSARECVMSG
typedef INT (WINAPI *LPFN_WSARECVMSG)(SOCKET s, LPWSAMSG lpMsg,
LPDWORD lpdwNumberOfBytesRecvd,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
# define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
-# endif
+# endif // !WSAID_WSARECVMSG
# ifndef WSAID_WSASENDMSG
typedef struct {
LPWSAMSG lpMsg;
@@ -96,9 +95,8 @@ typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
# define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
-# endif
-#endif
-#endif
+# endif // !WSAID_WSASENDMSG
+#endif // Q_OS_WIN
union qt_sockaddr {
sockaddr a;
@@ -210,7 +208,7 @@ public:
QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN)
LPFN_WSASENDMSG sendmsg;
LPFN_WSARECVMSG recvmsg;
# endif
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 648f2bf376..07f4899bae 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -387,7 +387,6 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
return false;
}
-#if !defined(Q_OS_WINCE)
if (socketType == QAbstractSocket::UdpSocket) {
// enable new behavior using
// SIO_UDP_CONNRESET
@@ -414,7 +413,6 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
&sendmsgguid, sizeof(sendmsgguid),
&sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
sendmsg = 0;
-#endif
socketDescriptor = socket;
if (socket != INVALID_SOCKET) {
@@ -1078,7 +1076,6 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
{
-#if !defined(Q_OS_WINCE)
// Create a sockaddr struct and reset its port number.
qt_sockaddr storage;
QT_SOCKLEN_T storageSize = sizeof(storage);
@@ -1105,18 +1102,6 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
result = true;
}
-#else // Q_OS_WINCE
- bool result = false;
- fd_set readS;
- FD_ZERO(&readS);
- FD_SET((SOCKET)socketDescriptor, &readS);
- timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 5000;
- int available = ::select(1, &readS, 0, 0, &timeout);
- result = available > 0;
-#endif
-
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
result ? "true" : "false");
@@ -1128,7 +1113,6 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
{
qint64 ret = -1;
-#if !defined(Q_OS_WINCE)
int recvResult = 0;
DWORD flags;
DWORD bufferCount = 5;
@@ -1173,18 +1157,6 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
if (buf)
delete[] buf;
-#else // Q_OS_WINCE
- DWORD size = -1;
- DWORD bytesReturned;
- int ioResult = WSAIoctl(socketDescriptor, FIONREAD, 0,0, &size, sizeof(size), &bytesReturned, 0, 0);
- if (ioResult == SOCKET_ERROR) {
- int err = WSAGetLastError();
- WS_ERROR_DEBUG(err);
- } else {
- ret = qint64(size);
- }
-#endif
-
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret);
#endif
@@ -1192,12 +1164,6 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return ret;
}
-#ifdef Q_OS_WINCE
-// Windows CE has no support for sendmsg or recvmsg. We set it to null here to simplify the code below.
-static int (*const recvmsg)(...) = 0;
-static int (*const sendmsg)(...) = 0;
-#endif
-
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
QAbstractSocketEngine::PacketHeaderOptions options)
{
@@ -1316,12 +1282,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
memset(&msg, 0, sizeof(msg));
memset(&aa, 0, sizeof(aa));
-#if !defined(Q_OS_WINCE)
buf.buf = len ? (char*)data : 0;
-#else
- char tmp;
- buf.buf = len ? (char*)data : &tmp;
-#endif
msg.lpBuffers = &buf;
msg.dwBufferCount = 1;
msg.name = &aa.a;
@@ -1482,9 +1443,6 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
buf.len = maxLength;
DWORD flags = 0;
DWORD bytesRead = 0;
-#if defined(Q_OS_WINCE)
- WSASetLastError(0);
-#endif
if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) == SOCKET_ERROR) {
int err = WSAGetLastError();
WS_ERROR_DEBUG(err);
@@ -1598,11 +1556,7 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout,
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
-#if !defined(Q_OS_WINCE)
ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
-#else
- ret = select(1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
-#endif
//... but if it is actually set, pretend it did not happen
if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index 0c15810a48..369396271e 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -64,11 +64,7 @@ static const int MaxWriteBufferSize = 128*1024;
//#define QSOCKS5SOCKETLAYER_DEBUG
#define MAX_DATA_DUMP 256
-#if !defined(Q_OS_WINCE)
#define SOCKS5_BLOCKING_BIND_TIMEOUT 5000
-#else
-#define SOCKS5_BLOCKING_BIND_TIMEOUT 10000
-#endif
#define Q_INIT_CHECK(returnValue) do { \
if (!d->data) { \
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index 7dd884c16a..809b603403 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -543,8 +543,11 @@ QTcpSocket *QTcpServer::nextPendingConnection()
if (d->pendingConnections.isEmpty())
return 0;
- if (!d->socketEngine->isReadNotificationEnabled())
+ if (!d->socketEngine) {
+ qWarning("QTcpServer::nextPendingConnection() called while not listening");
+ } else if (!d->socketEngine->isReadNotificationEnabled()) {
d->socketEngine->setReadNotificationEnabled(true);
+ }
return d->pendingConnections.takeFirst();
}
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index c406009069..083648bc23 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -398,7 +398,8 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres
readBytes = d->socketEngine->readDatagram(data, maxSize);
}
- d_func()->socketEngine->setReadNotificationEnabled(true);
+ d->hasPendingData = false;
+ d->socketEngine->setReadNotificationEnabled(true);
if (readBytes < 0)
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
return readBytes;
diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri
index f50a7b1229..2d80f38bec 100644
--- a/src/network/socket/socket.pri
+++ b/src/network/socket/socket.pri
@@ -43,7 +43,7 @@ win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp \
socket/qlocalsocket_win.cpp \
socket/qlocalserver_win.cpp
-win32:!wince:!winrt:LIBS_PRIVATE += -ladvapi32
+win32:!winrt:LIBS_PRIVATE += -ladvapi32
winrt {
SOURCES += socket/qnativesocketengine_winrt.cpp \
@@ -54,15 +54,6 @@ winrt {
DEFINES += QT_LOCALSOCKET_TCP
}
-wince {
- SOURCES -= socket/qlocalsocket_win.cpp \
- socket/qlocalserver_win.cpp
- SOURCES += socket/qlocalsocket_tcp.cpp \
- socket/qlocalserver_tcp.cpp
-
- DEFINES += QT_LOCALSOCKET_TCP
-}
-
integrity: {
SOURCES -= socket/qlocalsocket_unix.cpp \
socket/qlocalserver_unix.cpp
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index f9bb28e033..1eb253d202 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -119,7 +119,8 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
/*!
\enum QSslConfiguration::NextProtocolNegotiationStatus
- Describes the status of the Next Protocol Negotiation (NPN).
+ Describes the status of the Next Protocol Negotiation (NPN) or
+ Application-Layer Protocol Negotiation (ALPN).
\value NextProtocolNegotiationNone No application protocol
has been negotiated (yet).
@@ -209,6 +210,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->privateKey == other.d->privateKey &&
d->sessionCipher == other.d->sessionCipher &&
d->sessionProtocol == other.d->sessionProtocol &&
+ d->preSharedKeyIdentityHint == other.d->preSharedKeyIdentityHint &&
d->ciphers == other.d->ciphers &&
d->ellipticCurves == other.d->ellipticCurves &&
d->caCertificates == other.d->caCertificates &&
@@ -259,6 +261,7 @@ bool QSslConfiguration::isNull() const
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
d->sslSession.isNull() &&
d->sslSessionTicketLifeTimeHint == -1 &&
+ d->preSharedKeyIdentityHint.isNull() &&
d->nextAllowedProtocols.isEmpty() &&
d->nextNegotiatedProtocol.isNull() &&
d->nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNone);
@@ -809,11 +812,38 @@ QVector<QSslEllipticCurve> QSslConfiguration::supportedEllipticCurves()
}
/*!
+ \since 5.8
+
+ Returns the identity hint.
+
+ \sa setPreSharedKeyIdentityHint()
+*/
+QByteArray QSslConfiguration::preSharedKeyIdentityHint() const
+{
+ return d->preSharedKeyIdentityHint;
+}
+
+/*!
+ \since 5.8
+
+ Sets the identity hint for a preshared key authentication. This will affect the next
+ initiated handshake; calling this function on an already-encrypted socket
+ will not affect the socket's identity hint.
+
+ The identity hint is used in QSslSocket::SslServerMode only!
+*/
+void QSslConfiguration::setPreSharedKeyIdentityHint(const QByteArray &hint)
+{
+ d->preSharedKeyIdentityHint = hint;
+}
+
+/*!
\since 5.3
This function returns the protocol negotiated with the server
- if the Next Protocol Negotiation (NPN) TLS extension was enabled.
- In order for the NPN extension to be enabled, setAllowedNextProtocols()
+ if the Next Protocol Negotiation (NPN) or Application-Layer Protocol
+ Negotiation (ALPN) TLS extension was enabled.
+ In order for the NPN/ALPN extension to be enabled, setAllowedNextProtocols()
needs to be called explicitly before connecting to the server.
If no protocol could be negotiated or the extension was not enabled,
@@ -830,9 +860,10 @@ QByteArray QSslConfiguration::nextNegotiatedProtocol() const
\since 5.3
This function sets the allowed \a protocols to be negotiated with the
- server through the Next Protocol Negotiation (NPN) TLS extension; each
+ server through the Next Protocol Negotiation (NPN) or Application-Layer
+ Protocol Negotiation (ALPN) TLS extension; each
element in \a protocols must define one allowed protocol.
- The function must be called explicitly before connecting to send the NPN
+ The function must be called explicitly before connecting to send the NPN/ALPN
extension in the SSL handshake.
Whether or not the negotiation succeeded can be queried through
nextProtocolNegotiationStatus().
@@ -852,8 +883,8 @@ void QSslConfiguration::setAllowedNextProtocols(QList<QByteArray> protocols)
\since 5.3
This function returns the allowed protocols to be negotiated with the
- server through the Next Protocol Negotiation (NPN) TLS extension, as set
- by setAllowedNextProtocols().
+ server through the Next Protocol Negotiation (NPN) or Application-Layer
+ Protocol Negotiation (ALPN) TLS extension, as set by setAllowedNextProtocols().
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1
*/
@@ -865,7 +896,8 @@ QList<QByteArray> QSslConfiguration::allowedNextProtocols() const
/*!
\since 5.3
- This function returns the status of the Next Protocol Negotiation (NPN).
+ This function returns the status of the Next Protocol Negotiation (NPN)
+ or Application-Layer Protocol Negotiation (ALPN).
If the feature has not been enabled through setAllowedNextProtocols(),
this function returns NextProtocolNegotiationNone.
The status will be set before emitting the encrypted() signal.
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index f0754d7ef5..1f39e1a06f 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -141,6 +141,9 @@ public:
void setEllipticCurves(const QVector<QSslEllipticCurve> &curves);
static QVector<QSslEllipticCurve> supportedEllipticCurves();
+ QByteArray preSharedKeyIdentityHint() const;
+ void setPreSharedKeyIdentityHint(const QByteArray &hint);
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 093c9d6598..113954d7d1 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -88,6 +88,7 @@ public:
peerSessionShared(false),
sslOptions(QSslConfigurationPrivate::defaultSslOptions),
sslSessionTicketLifeTimeHint(-1),
+ preSharedKeyIdentityHint(),
nextProtocolNegotiationStatus(QSslConfiguration::NextProtocolNegotiationNone)
{ }
@@ -121,6 +122,8 @@ public:
QSslKey ephemeralServerKey;
+ QByteArray preSharedKeyIdentityHint;
+
QList<QByteArray> nextAllowedProtocols;
QByteArray nextNegotiatedProtocol;
QSslConfiguration::NextProtocolNegotiationStatus nextProtocolNegotiationStatus;
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index b3786f989e..0db7e10409 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -344,6 +344,11 @@ init_context:
}
#endif // OPENSSL_NO_EC
+#ifndef OPENSSL_NO_PSK
+ if (!client)
+ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
+#endif // OPENSSL_NO_PSK
+
const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
if (!qcurves.isEmpty()) {
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
@@ -457,6 +462,23 @@ SSL* QSslContext::createSsl()
m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data());
m_npnContext.len = m_supportedNPNVersions.count();
m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L) {
+ // Callback's type has a parameter 'const unsigned char ** out'
+ // since it was introduced in 1.0.2. Internally, OpenSSL's own code
+ // (tests/examples) cast it to unsigned char * (since it's 'out').
+ // We just re-use our NPN callback and cast here:
+ typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *,
+ const unsigned char *, unsigned int, void *);
+ // With ALPN callback is for a server side only, for a client m_npnContext.status
+ // will stay in NextProtocolNegotiationNone.
+ q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
+ // Client:
+ q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
+ }
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
+
+ // And in case our peer does not support ALPN, but supports NPN:
q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 3e7a30aa9f..82df861859 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -836,15 +836,7 @@ bool QSslSocket::atEnd() const
// Note! docs copied from QAbstractSocket::flush()
bool QSslSocket::flush()
{
- Q_D(QSslSocket);
-#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << "QSslSocket::flush()";
-#endif
- if (d->mode != UnencryptedMode)
- // encrypt any unencrypted bytes in our buffer
- d->transmit();
-
- return d->plainSocket ? d->plainSocket->flush() : false;
+ return d_func()->flush();
}
/*!
@@ -923,6 +915,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.privateKey = configuration.privateKey();
d->configuration.ciphers = configuration.ciphers();
d->configuration.ellipticCurves = configuration.ellipticCurves();
+ d->configuration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
d->configuration.caCertificates = configuration.caCertificates();
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
@@ -2614,6 +2607,22 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
/*!
\internal
*/
+bool QSslSocketPrivate::flush()
+{
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "QSslSocketPrivate::flush()";
+#endif
+ if (mode != QSslSocket::UnencryptedMode) {
+ // encrypt any unencrypted bytes in our buffer
+ transmit();
+ }
+
+ return plainSocket && plainSocket->flush();
+}
+
+/*!
+ \internal
+*/
bool QSslSocketPrivate::rootCertOnDemandLoadingSupported()
{
return s_loadRootCertsOnDemand;
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index c069ff2f9d..1f2ed7687b 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -116,7 +116,7 @@ public:
bool canReadLine() const Q_DECL_OVERRIDE;
void close() Q_DECL_OVERRIDE;
bool atEnd() const Q_DECL_OVERRIDE;
- bool flush();
+ bool flush(); // ### Qt6: remove me (implementation moved to private flush())
void abort();
// From QAbstractSocket:
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 4f62f53a93..5cbd2af323 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -201,6 +201,15 @@ static unsigned int q_ssl_psk_client_callback(SSL *ssl,
Q_ASSERT(d);
return d->tlsPskClientCallback(hint, identity, max_identity_len, psk, max_psk_len);
}
+
+static unsigned int q_ssl_psk_server_callback(SSL *ssl,
+ const char *identity,
+ unsigned char *psk, unsigned int max_psk_len)
+{
+ QSslSocketBackendPrivate *d = reinterpret_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData));
+ Q_ASSERT(d);
+ return d->tlsPskServerCallback(identity, psk, max_psk_len);
+}
#endif
} // extern "C"
@@ -436,8 +445,12 @@ bool QSslSocketBackendPrivate::initSslContext()
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
// Set the client callback for PSK
- if (q_SSLeay() >= 0x10001000L && mode == QSslSocket::SslClientMode)
- q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
+ if (q_SSLeay() >= 0x10001000L) {
+ if (mode == QSslSocket::SslClientMode)
+ q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
+ else if (mode == QSslSocket::SslServerMode)
+ q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback);
+ }
#endif
return true;
@@ -522,15 +535,9 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
#if defined(Q_OS_WIN)
HINSTANCE hLib = LoadLibraryW(L"Crypt32");
if (hLib) {
-#if defined(Q_OS_WINCE)
- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, L"CertOpenStore");
- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, L"CertFindCertificateInStore");
- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, L"CertCloseStore");
-#else
ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
-#endif
if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
} else {
@@ -691,15 +698,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
#if defined(Q_OS_WIN)
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
HCERTSTORE hSystemStore;
-#if defined(Q_OS_WINCE)
- hSystemStore = ptrCertOpenSystemStoreW(CERT_STORE_PROV_SYSTEM_W,
- 0,
- 0,
- CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,
- L"ROOT");
-#else
hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
-#endif
if(hSystemStore) {
PCCERT_CONTEXT pc = NULL;
while(1) {
@@ -1274,6 +1273,31 @@ unsigned int QSslSocketBackendPrivate::tlsPskClientCallback(const char *hint,
return pskLength;
}
+unsigned int QSslSocketBackendPrivate::tlsPskServerCallback(const char *identity,
+ unsigned char *psk, unsigned int max_psk_len)
+{
+ QSslPreSharedKeyAuthenticator authenticator;
+
+ // Fill in some read-only fields (for the user)
+ authenticator.d->identityHint = configuration.preSharedKeyIdentityHint;
+ authenticator.d->identity = identity;
+ authenticator.d->maximumIdentityLength = 0; // user cannot set an identity
+ authenticator.d->maximumPreSharedKeyLength = int(max_psk_len);
+
+ // Let the client provide the remaining bits...
+ Q_Q(QSslSocket);
+ emit q->preSharedKeyAuthenticationRequired(&authenticator);
+
+ // No PSK set? Return now to make the handshake fail
+ if (authenticator.preSharedKey().isEmpty())
+ return 0;
+
+ // Copy data back into OpenSSL
+ const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength());
+ ::memcpy(psk, authenticator.preSharedKey().constData(), pskLength);
+ return pskLength;
+}
+
#ifdef Q_OS_WIN
void QSslSocketBackendPrivate::fetchCaRootForCert(const QSslCertificate &cert)
@@ -1571,7 +1595,22 @@ void QSslSocketBackendPrivate::continueHandshake()
} else {
const unsigned char *proto = 0;
unsigned int proto_len = 0;
- q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L) {
+ q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
+ if (proto_len && mode == QSslSocket::SslClientMode) {
+ // Client does not have a callback that sets it ...
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ }
+ }
+
+ if (!proto_len) { // Test if NPN was more lucky ...
+#else
+ {
+#endif
+ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+ }
+
if (proto_len)
configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
else
diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp
index d73ed8995e..b5d2458d56 100644
--- a/src/network/ssl/qsslsocket_openssl_android.cpp
+++ b/src/network/ssl/qsslsocket_openssl_android.cpp
@@ -70,6 +70,7 @@ QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData()
QJNIEnvironmentPrivate env;
jobjectArray jcertificates = static_cast<jobjectArray>(certificates.object());
const jint nCertificates = env->GetArrayLength(jcertificates);
+ certificateData.reserve(static_cast<int>(nCertificates));
for (int i = 0; i < nCertificates; ++i) {
jbyteArray jCert = static_cast<jbyteArray>(env->GetObjectArrayElement(jcertificates, i));
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index 0674c05d71..c6572315f0 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -143,6 +143,7 @@ public:
bool checkSslErrors();
void storePeerCertificates();
unsigned int tlsPskClientCallback(const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len);
+ unsigned int tlsPskServerCallback(const char *identity, unsigned char *psk, unsigned int max_psk_len);
#ifdef Q_OS_WIN
void fetchCaRootForCert(const QSslCertificate &cert);
void _q_caRootLoaded(QSslCertificate,QSslCertificate) Q_DECL_OVERRIDE;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index d0982377fb..f625fd3e96 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -300,6 +300,8 @@ DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return N
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG)
+DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG)
+DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#ifndef OPENSSL_NO_SSL2
@@ -418,6 +420,18 @@ DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s,
void *arg, arg, return, DUMMYARG)
DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s,
const unsigned char **data, data, unsigned *len, len, return, DUMMYARG)
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+DEFINEFUNC3(int, SSL_set_alpn_protos, SSL *s, s, const unsigned char *protos, protos,
+ unsigned protos_len, protos_len, return -1, return)
+DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s,
+ int (*cb) (SSL *ssl, const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen, void *arg), cb,
+ void *arg, arg, return, DUMMYARG)
+DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char **data, data,
+ unsigned *len, len, return, DUMMYARG)
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG)
@@ -889,6 +903,8 @@ bool q_resolveOpenSslSymbols()
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
RESOLVEFUNC(SSL_set_psk_client_callback)
+ RESOLVEFUNC(SSL_set_psk_server_callback)
+ RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
#endif
RESOLVEFUNC(SSL_write)
#ifndef OPENSSL_NO_SSL2
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 36e041b6cb..45e4380580 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -376,6 +376,9 @@ void *q_SSL_get_ex_data(const SSL *ssl, int idx);
#ifndef OPENSSL_NO_PSK
typedef unsigned int (*q_psk_client_callback_t)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len);
void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback);
+typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len);
+void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback);
+int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
#endif // OPENSSL_NO_PSK
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#ifndef OPENSSL_NO_SSL2
@@ -558,6 +561,19 @@ void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
void *arg);
void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len);
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
+ unsigned protos_len);
+void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
+ int (*cb) (SSL *ssl,
+ const unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen,
+ void *arg), void *arg);
+void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
+ unsigned *len);
+#endif
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
// Helper function
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 5d4d52cd6d..e791b9d166 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -89,11 +89,7 @@ QT_BEGIN_NAMESPACE
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-#if defined(Q_OS_WINCE)
- typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, const void*);
-#else
typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(HCRYPTPROV_LEGACY, LPCWSTR);
-#endif
typedef PCCERT_CONTEXT (WINAPI *PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT);
typedef BOOL (WINAPI *PtrCertCloseStore)(HCERTSTORE, DWORD);
#endif // Q_OS_WIN && !Q_OS_WINRT
@@ -193,6 +189,7 @@ public:
virtual qint64 peek(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
virtual QByteArray peek(qint64 maxSize) Q_DECL_OVERRIDE;
+ bool flush() Q_DECL_OVERRIDE;
// Platform specific functions
virtual void startClientEncryption() = 0;
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index 045c89eb0e..5704d6b151 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -215,7 +215,9 @@ QList<QSslCipher> QSslSocketBackendPrivate::defaultCiphers()
const QString protocolStrings[] = { QStringLiteral("SSLv3"), QStringLiteral("TLSv1"),
QStringLiteral("TLSv1.1"), QStringLiteral("TLSv1.2") };
const QSsl::SslProtocol protocols[] = { QSsl::SslV3, QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 };
- for (int i = 0; i < ARRAYSIZE(protocols); ++i) {
+ const int size = static_cast<int>(ARRAYSIZE(protocols));
+ ciphers.reserve(size);
+ for (int i = 0; i < size; ++i) {
QSslCipher cipher;
cipher.d->isNull = false;
cipher.d->name = QStringLiteral("WINRT");