diff options
Diffstat (limited to 'src/network')
32 files changed, 445 insertions, 286 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/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/access/qnetworkfile.cpp b/src/network/access/qnetworkfile.cpp new file mode 100644 index 0000000000..374dd26e2e --- /dev/null +++ b/src/network/access/qnetworkfile.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qnetworkfile_p.h" + +#include <QtCore/QDebug> +#include <QNetworkReply> +#include <QtCore/QDateTime> +#include <QtCore/QFileInfo> +#include <QtCore/QMetaObject> +#include <QtCore/QCoreApplication> + +QT_BEGIN_NAMESPACE + +QNetworkFile::QNetworkFile() + : QFile() +{ +} + +QNetworkFile::QNetworkFile(const QString &name) + : QFile(name) +{ +} + +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); +} + +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(); +} + +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/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..dfade24edd 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 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 832a3badb9..682b7b157a 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -122,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); @@ -152,7 +151,6 @@ static bool currentProcessIsService() } return false; } -#endif // ! Q_OS_WINCE static QStringList splitSpaceSemicolon(const QString &source) { @@ -358,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: @@ -409,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 { @@ -428,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; @@ -464,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 @@ -474,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")); @@ -567,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..731afd4e36 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -691,6 +691,7 @@ bool QAbstractSocketPrivate::canReadNotification() 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 +709,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 +724,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 +780,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 +821,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 +864,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 +1135,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 +1155,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 +2363,6 @@ void QAbstractSocket::abort() return; } #endif - if (d->connectTimer) { - d->connectTimer->stop(); - delete d->connectTimer; - d->connectTimer = 0; - } d->abortCalled = true; close(); @@ -2430,15 +2409,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,7 +2432,7 @@ 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->socketEngine->setReadNotificationEnabled(true); } @@ -2828,12 +2799,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..ab642e039b 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(); 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/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..1fff2c31dd 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). @@ -812,8 +813,9 @@ QVector<QSslEllipticCurve> QSslConfiguration::supportedEllipticCurves() \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 +832,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 +855,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 +868,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/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index b3786f989e..543e87c0ca 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -457,7 +457,25 @@ SSL* QSslContext::createSsl() m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); m_npnContext.len = m_supportedNPNVersions.count(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; - q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); +#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); + } else { +#else + { +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... + 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..bbc62c47ff 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(); } /*! @@ -2614,6 +2606,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..48f8e258df 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -522,15 +522,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 +685,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) { @@ -1571,7 +1557,20 @@ 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; + } + } else { +#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_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index d0982377fb..05b7e2da7f 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -418,6 +418,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) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 36e041b6cb..5a6c934d1a 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -558,6 +558,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"); |