diff options
Diffstat (limited to 'src/network/kernel')
26 files changed, 935 insertions, 167 deletions
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 811d8b6f0d..34d2f164e8 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -3,7 +3,9 @@ PRECOMPILED_HEADER = ../corelib/global/qt_pch.h INCLUDEPATH += $$PWD -HEADERS += kernel/qauthenticator.h \ +HEADERS += kernel/qtnetworkglobal.h \ + kernel/qtnetworkglobal_p.h \ + kernel/qauthenticator.h \ kernel/qauthenticator_p.h \ kernel/qdnslookup.h \ kernel/qdnslookup_p.h \ @@ -11,6 +13,7 @@ HEADERS += kernel/qauthenticator.h \ kernel/qhostaddress_p.h \ kernel/qhostinfo.h \ kernel/qhostinfo_p.h \ + kernel/qnetworkdatagram.h \ kernel/qnetworkdatagram_p.h \ kernel/qnetworkinterface.h \ kernel/qnetworkinterface_p.h \ @@ -22,9 +25,10 @@ SOURCES += kernel/qauthenticator.cpp \ kernel/qdnslookup.cpp \ kernel/qhostaddress.cpp \ kernel/qhostinfo.cpp \ - kernel/qurlinfo.cpp \ + kernel/qnetworkdatagram.cpp \ + kernel/qnetworkinterface.cpp \ kernel/qnetworkproxy.cpp \ - kernel/qnetworkinterface.cpp + kernel/qurlinfo.cpp unix { !integrity: SOURCES += kernel/qdnslookup_unix.cpp @@ -53,10 +57,10 @@ win32: { mac { LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation - !ios: LIBS_PRIVATE += -framework CoreServices + !uikit: LIBS_PRIVATE += -framework CoreServices } -mac:!ios:SOURCES += kernel/qnetworkproxy_mac.cpp +osx:SOURCES += kernel/qnetworkproxy_mac.cpp else:win32:SOURCES += kernel/qnetworkproxy_win.cpp else:contains(QT_CONFIG, libproxy) { SOURCES += kernel/qnetworkproxy_libproxy.cpp diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 6da231d019..107addae58 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -1271,14 +1271,10 @@ static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx, if(timeArray.size()) { ds.writeRawData(timeArray.constData(), timeArray.size()); } else { - QDateTime currentTime(QDate::currentDate(), - QTime::currentTime(), Qt::UTC); - - // number of seconds between 1601 and epoc(1970) + // number of seconds between 1601 and the epoch (1970) // 369 years, 89 leap years // ((369 * 365) + 89) * 24 * 3600 = 11644473600 - - time = currentTime.toTime_t() + Q_UINT64_C(11644473600); + time = QDateTime::currentSecsSinceEpoch() + 11644473600; // represented as 100 nano seconds time = time * Q_UINT64_C(10000000); @@ -1455,15 +1451,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/qauthenticator.h b/src/network/kernel/qauthenticator.h index 7f8d912b49..1032c2f501 100644 --- a/src/network/kernel/qauthenticator.h +++ b/src/network/kernel/qauthenticator.h @@ -40,6 +40,7 @@ #ifndef QAUTHENTICATOR_H #define QAUTHENTICATOR_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qstring.h> #include <QtCore/qvariant.h> diff --git a/src/network/kernel/qauthenticator_p.h b/src/network/kernel/qauthenticator_p.h index 46388a0185..8a1ee0ebe6 100644 --- a/src/network/kernel/qauthenticator_p.h +++ b/src/network/kernel/qauthenticator_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <qhash.h> #include <qbytearray.h> #include <qstring.h> diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index bf8b6debbe..ead5e650f5 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -40,6 +40,7 @@ #ifndef QDNSLOOKUP_H #define QDNSLOOKUP_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qlist.h> #include <QtCore/qobject.h> #include <QtCore/qshareddata.h> diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h index 98d828b7b5..d070286383 100644 --- a/src/network/kernel/qdnslookup_p.h +++ b/src/network/kernel/qdnslookup_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "QtCore/qmutex.h" #include "QtCore/qrunnable.h" #include "QtCore/qsharedpointer.h" diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 13ecfac3f5..95f90af49e 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 @@ -151,20 +151,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_) @@ -173,7 +190,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_) @@ -385,6 +403,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() @@ -690,7 +722,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; } @@ -812,19 +846,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..58af14ee33 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -41,6 +41,7 @@ #ifndef QHOSTADDRESS_H #define QHOSTADDRESS_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qpair.h> #include <QtCore/qstring.h> #include <QtCore/qscopedpointer.h> @@ -79,6 +80,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 +129,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 +151,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/qhostaddress_p.h b/src/network/kernel/qhostaddress_p.h index 7b43af01bb..55c3e5afde 100644 --- a/src/network/kernel/qhostaddress_p.h +++ b/src/network/kernel/qhostaddress_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qhostaddress.h" #include "qabstractsocket.h" diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index 42317c4c65..9b4a4853d9 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -40,6 +40,7 @@ #ifndef QHOSTINFO_H #define QHOSTINFO_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qlist.h> #include <QtCore/qscopedpointer.h> #include <QtNetwork/qhostaddress.h> diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 68d7dfae5b..ba342bf533 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "QtCore/qcoreapplication.h" #include "private/qcoreapplication_p.h" #include "QtNetwork/qhostinfo.h" diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index b98f36a612..9e5d556f2b 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -81,11 +81,7 @@ static bool resolveLibraryInternal() { // 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; @@ -116,11 +112,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/qnetworkdatagram.cpp b/src/network/kernel/qnetworkdatagram.cpp new file mode 100644 index 0000000000..ba8a063edf --- /dev/null +++ b/src/network/kernel/qnetworkdatagram.cpp @@ -0,0 +1,535 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: http://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 "qnetworkdatagram.h" +#include "qnetworkdatagram_p.h" + +#ifndef QT_NO_UDPSOCKET + +QT_BEGIN_NAMESPACE + +/*! + \class QNetworkDatagram + \brief The QNetworkDatagram class provides the data and matadata of a UDP datagram. + \since 5.8 + \ingroup network + \inmodule QtNetwork + \reentrant + + QNetworkDatagram can be used with the \l QUdpSocket class to represent the full + information contained in a UDP (User Datagram Protocol) datagram. + QNetworkDatagram encapsulates the following information of a datagram: + \list + \li the payload data; + \li the sender address and port number; + \li the destination address and port number; + \li the remaining hop count limit (on IPv4, this field is usually called "time to live" - TTL); + \li the network interface index the datagram was received on or to be sent on. + \endlist + + QUdpSocket will try to match a common behavior as much as possible on all + operating systems, but not all of the metadata above can be obtained in + some operating systems. Metadata that cannot be set on the datagram when + sending with QUdpSocket::writeDatagram() will be silently discarded. + + Upon reception, the senderAddress() and senderPort() properties contain the + address and port of the peer that sent the datagram, while + destinationAddress() and destinationPort() contain the target that was + contained in the datagram. That is usually an address local to the current + machine, but it can also be an IPv4 broadcast address (such as + "255.255.255.255") or an IPv4 or IPv6 multicast address. Applications may + find it useful to determine if the datagram was sent specifically to this + machine via unicast addressing or whether it was sent to multiple destinations. + + When sending, the senderAddress() and senderPort() should contain the local + address to be used when sending. The sender address must be an address that + is assigned to this machine, which can be obtained using + \l{QNetworkInterface}, and the port number must be the port number that the + socket is bound to. Either field can be left unset and will be filled in by + the operating system with default values. The destinationAddress() and + destinationPort() fields may be set to a target address different from the + one the UDP socket is currently associated with. + + Usually, when sending a datagram in reply to a datagram previously + received, one will set the destinationAddress() to be the senderAddress() + of the incoming datagram and similarly for the port numbers. To facilitate + this common process, QNetworkDatagram provides the function makeReply(). + + The hopCount() function contains, for a received datagram, the remaining + hop count limit for the packet. When sending, it contains the hop count + limit to be set. Most protocols will leave this value set to the default + and let the operating system decide on the best value to be used. + Multicasting over IPv4 often uses this field to indicate the scope of the + multicast group (link-local, local to an organization or global). + + The interfaceIndex() function contains the index of the operating system's + interface that received the packet. This value is the same one that can be + set on a QHostAddress::scopeId() property and matches the + QNetworkInterface::index() property. When sending packets to global + addresses, it is not necessary to set the interface index as the operating + system will choose the correct one using the system routing table. This + property is important when sending datagrams to link-local destinations, + whether unicast or multicast. + + \section1 Feature support + + Some features of QNetworkDatagram are not supported in all operating systems. + Only the address and ports of the remote host (sender in received packets + and destination for outgoing packets) are supported in all systems. On most + operating systems, the other features are supported only for IPv6. Software + should check at runtime whether the rest could be determined for IPv4 + addresses. + + The current feature support is as follows: + + \table + \header \li Operating system \li Local address \li Hop count \li Interface index + \row \li FreeBSD \li Supported \li Supported \li Only for IPv6 + \row \li Linux \li Supported \li Supported \li Supported + \row \li OS X \li Supported \li Supported \li Only for IPv6 + \row \li Other Unix supporting RFC 3542 \li Only for IPv6 \li Only for IPv6 \li Only for IPv6 + \row \li Windows XP and older \li Not supported \li Not supported \li Not supported + \row \li Windows Vista & up \li Supported \li Supported \li Supported + \row \li Windows CE \li Not supported \li Not supported \li Not supported + \row \li Windows RT \li Not supported \li Not supported \li Not supported + \endtable + + \sa QUdpSocket, QNetworkInterface + */ + +/*! + Creates a QNetworkDatagram object with no payload data and undefined destination address. + + The payload can be modified by using setData() and the destination address + can be set with setDestination(). + + If the destination address is left undefined, QUdpSocket::writeDatagram() + will attempt to send the datagram to the address last associated with, by + using QUdpSocket::connectToHost(). + */ +QNetworkDatagram::QNetworkDatagram() + : d(new QNetworkDatagramPrivate) +{ +} + +/*! + Creates a QNetworkDatagram object and sets \a data as the payload data, along with + \a destinationAddress and \a port as the destination address of the datagram. + */ +QNetworkDatagram::QNetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress, quint16 port) + : d(new QNetworkDatagramPrivate(data, destinationAddress, port)) +{ +} + +/*! + Creates a copy of the \a other datagram, including the payload and metadata. + + To create a datagram suitable for sending in a reply, use QNetworkDatagram::makeReply(); + */ +QNetworkDatagram::QNetworkDatagram(const QNetworkDatagram &other) + : d(new QNetworkDatagramPrivate(*other.d)) +{ +} + +/*! \internal */ +QNetworkDatagram::QNetworkDatagram(QNetworkDatagramPrivate &dd) + : d(&dd) +{ +} + +/*! + Copies the \a other datagram, including the payload and metadata. + + To create a datagram suitable for sending in a reply, use QNetworkDatagram::makeReply(); + */ +QNetworkDatagram &QNetworkDatagram::operator=(const QNetworkDatagram &other) +{ + *d = *other.d; + return *this; +} + +/*! + Clears the payload data and metadata in this QNetworkDatagram object, resetting + them to their default values. + */ +void QNetworkDatagram::clear() +{ + d->data.clear(); + d->header.senderAddress.clear(); + d->header.destinationAddress.clear(); + d->header.hopLimit = -1; + d->header.ifindex = 0; +} + +/*! + \fn QNetworkDatagram::isNull() const + Returns true if this QNetworkDatagram object is null. This function is the + opposite of isValid(). + */ + +/*! + Returns true if this QNetworkDatagram object is valid. A valid QNetworkDatagram + object contains at least one sender or receiver address. Valid datagrams + can contain empty payloads. + */ +bool QNetworkDatagram::isValid() const +{ + return d->header.senderAddress.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol || + d->header.destinationAddress.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol; +} + +/*! + Returns the sender address associated with this datagram. For a datagram + received from the network, it is the address of the peer node that sent the + datagram. For an outgoing datagrams, it is the local address to be used + when sending. + + If no sender address was set on this datagram, the returned object will + report true to QHostAddress::isNull(). + + \sa destinationAddress(), senderPort(), setSender() +*/ +QHostAddress QNetworkDatagram::senderAddress() const +{ + return d->header.senderAddress; +} + +/*! + Returns the destination address associated with this datagram. For a + datagram received from the network, it is the address the peer node sent + the datagram to, which can either be a local address of this machine or a + multicast or broadcast address. For an outgoing datagrams, it is the + address the datagram should be sent to. + + If no destination address was set on this datagram, the returned object + will report true to QHostAddress::isNull(). + + \sa senderAddress(), destinationPort(), setDestination() +*/ +QHostAddress QNetworkDatagram::destinationAddress() const +{ + return d->header.destinationAddress; +} + +/*! + Returns the port number of the sender associated with this datagram. For a + datagram received from the network, it is the port number that the peer + node sent the datagram from. For an outgoing datagram, it is the local port + the datagram should be sent from. + + If no sender address was associated with this datagram, this function + returns -1. + + \sa senderAddress(), destinationPort(), setSender() +*/ +int QNetworkDatagram::senderPort() const +{ + return d->header.senderAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol + ? -1 : d->header.senderPort; +} + +/*! + Returns the port number of the destination associated with this datagram. + For a datagram received from the network, it is the local port number that + the peer node sent the datagram to. For an outgoing datagram, it is the + peer port the datagram should be sent to. + + If no destination address was associated with this datagram, this function + returns -1. + + \sa destinationAddress(), senderPort(), setDestination() +*/ +int QNetworkDatagram::destinationPort() const +{ + return d->header.destinationAddress.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol + ? -1 : d->header.destinationPort; +} + +/*! + Sets the sender address associated with this datagram to be the address \a + address and port number \a port. The sender address and port numbers are + usually set by \l QUdpSocket upon reception, so there's no need to call + this function on a received datagram. + + For outgoing datagrams, this function can be used to set the address the + datagram should carry. The address \a address must usually be one of the + local addresses assigned to this machine, which can be obtained using \l + QNetworkInterface. If left unset, the operating system will choose the most + appropriate address to use given the destination in question. + + The port number \a port must be the port number associated with the socket, + if there is one. The value of 0 can be used to indicate that the operating + system should choose the port number. + + \sa QUdpSocket::writeDatagram(), senderAddress(), senderPort(), setDestination() + */ +void QNetworkDatagram::setSender(const QHostAddress &address, quint16 port) +{ + d->header.senderAddress = address; + d->header.senderPort = port; +} + +/*! + Sets the destination address associated with this datagram to be the + address \a address and port number \a port. The destination address and + port numbers are usually set by \l QUdpSocket upon reception, so there's no + need to call this function on a received datagram. + + For outgoing datagrams, this function can be used to set the address the + datagram should be sent to. It can be the unicast address used to + communicate with the peer or a broadcast or multicast address to send to a + group of devices. + + \sa QUdpSocket::writeDatagram(), destinationAddress(), destinationPort(), setSender() + */ +void QNetworkDatagram::setDestination(const QHostAddress &address, quint16 port) +{ + d->header.destinationAddress = address; + d->header.destinationPort = port; +} + +/*! + Returns the hop count limit associated with this datagram. The hop count + limit is the number of nodes that are allowed to forward the IP packet + before it expires and an error is sent back to the sender of the datagram. + In IPv4, this value is usually known as "time to live" (TTL). + + If this datagram was received from the network, this is the remaining hop + count of the datagram after reception and was decremented by 1 by each node + that forwarded the packet. A value of -1 indicates that the hop limit count + not be obtained. + + If this is an outgoing datagram, this is the value to be set in the IP header + upon sending. A value of -1 indicates the operating system should choose + the value. + + \sa setHopLimit() + */ +int QNetworkDatagram::hopLimit() const +{ + return d->header.hopLimit; +} + +/*! + Sets the hop count limit associated with this datagram to \a count. The hop + count limit is the number of nodes that are allowed to forward the IP + packet before it expires and an error is sent back to the sender of the + datagram. In IPv4, this value is usually known as "time to live" (TTL). + + It is usually not necessary to call this function on datagrams received + from the network. + + If this is an outgoing packet, this is the value to be set in the IP header + upon sending. The valid range for the value is 1 to 255. This function also + accepts a value of -1 to indicate that the operating system should choose + the value. + + \sa hopLimit() + */ +void QNetworkDatagram::setHopLimit(int count) +{ + d->header.hopLimit = count; +} + +/*! + Returns the interface index this datagram is associated with. The interface + index is a positive number that uniquely identifies the network interface + in the operating system. This number matches the value returned by + QNetworkInterface::index() for the interface. + + If this datagram was received from the network, this is the index of the + interface that the packet was received from. If this is an outgoing + datagram, this is the index of the interface that the datagram should be + sent on. + + A value of 0 indicates that the interface index is unknown. + + \sa setInterfaceIndex() + */ +uint QNetworkDatagram::interfaceIndex() const +{ + return d->header.ifindex; +} + +/*! + Sets the interface index this datagram is associated with to \a index. The + interface index is a positive number that uniquely identifies the network + interface in the operating system. This number matches the value returned + by QNetworkInterface::index() for the interface. + + It is usually not necessary to call this function on datagrams received + from the network. + + If this is an outgoing packet, this is the index of the interface the + datagram should be sent on. A value of 0 indicates that the operating + system should choose the interface based on other factors. + + Note that the interface index can also be set with + QHostAddress::setScopeId() for IPv6 destination addresses and then with + setDestination(). If the scope ID set in the destination address and \a + index are different and neither is zero, it is undefined which interface + the operating system will send the datagram on. + + \sa setInterfaceIndex() + */ +void QNetworkDatagram::setInterfaceIndex(uint index) +{ + d->header.ifindex = index; +} + +/*! + Returns the data payload of this datagram. For a datagram received from the + network, it contains the payload of the datagram. For an outgoing datagram, + it is the datagram to be sent. + + Note that datagrams can be transmitted with no data, so the returned + QByteArray may be empty. + + \sa setData() + */ +QByteArray QNetworkDatagram::data() const +{ + return d->data; +} + +/*! + Sets the data payload of this datagram to \a data. It is usually not + necessary to call this function on received datagrams. For outgoing + datagrams, this function sets the data to be sent on the network. + + Since datagrams can empty, an empty QByteArray is a valid value for \a + data. + + \sa data() + */ +void QNetworkDatagram::setData(const QByteArray &data) +{ + d->data = data; +} + +/*! + \fn QNetworkDatagram QNetworkDatagram::makeReply(const QByteArray &data) const + + Creates a new QNetworkDatagram representing a reply to this incoming datagram + and sets the payload data to \a data. This function is a very convenient + way of responding to a datagram back to the original sender. + + Example: + \code + void Server::readPendingDatagrams() + { + while (udpSocket->hasPendingDatagrams()) { + QNetworkDatagram datagram = udpSocket->receiveDatagram(); + QByteArray replyData = processThePayload(datagram.data()); + udpSocket->writeDatagram(datagram.makeReply(replyData)); + } + } + \endcode + + This function is especially convenient since it will automatically copy + parameters from this datagram to the new datagram as appropriate: + + \list + \li this datagram's sender address and port are copied to the new + datagram's destination address and port; + \li this datagram's interface index, if any, is copied to the new + datagram's interface index; + \li this datagram's destination address and port are copied to the new + datagram's sender address and port only if the address is IPv6 + global (non-multicast) address; + \li the hop count limit on the new datagram is reset to the default (-1); + \endlist + + If QNetworkDatagram is modified in a future version of Qt to carry further + metadata, this function will copy that metadata as appropriate. + + This datagram's destination address is not copied if it is an IPv4 address + because it is not possible to tell an IPv4 broadcast address apart from a + regular IPv4 address without an exhaustive search of all addresses assigned + to this machine. Attempting to send a datagram with the sender address + equal to the broadcast address is likely to fail. However, this should not + affect the communication as network interfaces with multiple IPv4 addresses + are uncommon, so the address the operating system will select will likely + be one the peer will understand. + + \note This function comes with both rvalue- and lvalue-reference qualifier + overloads, so it is a good idea to make sure this object is rvalue, if + possible, before calling makeReply, so as to make better use of move + semantics. To achieve that, the example above would use: + \code + udpSocket->writeDatagram(std::move(datagram).makeReply(replyData)); + \endcode + */ + +static bool isNonMulticast(const QHostAddress &addr) +{ + // is it a multicast address? + return !addr.isMulticast(); +} + +QNetworkDatagram QNetworkDatagram::makeReply_helper(const QByteArray &data) const +{ + QNetworkDatagramPrivate *x = new QNetworkDatagramPrivate(data, d->header.senderAddress, d->header.senderPort); + x->header.ifindex = d->header.ifindex; + if (isNonMulticast(d->header.destinationAddress)) { + x->header.senderAddress = d->header.destinationAddress; + x->header.senderPort = d->header.destinationPort; + } + return QNetworkDatagram(*x); +} + +void QNetworkDatagram::makeReply_helper_inplace(const QByteArray &data) +{ + d->data = data; + d->header.hopLimit = -1; + qSwap(d->header.destinationPort, d->header.senderPort); + qSwap(d->header.destinationAddress, d->header.senderAddress); + if (!isNonMulticast(d->header.senderAddress)) + d->header.senderAddress.clear(); +} + +void QNetworkDatagram::destroy(QNetworkDatagramPrivate *d) +{ + Q_ASSUME(d); + delete d; +} + +QT_END_NAMESPACE + +#endif // QT_NO_UDPSOCKET diff --git a/src/network/kernel/qnetworkdatagram.h b/src/network/kernel/qnetworkdatagram.h new file mode 100644 index 0000000000..6cbea13afc --- /dev/null +++ b/src/network/kernel/qnetworkdatagram.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: http://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 QNETWORKDATAGRAM_H +#define QNETWORKDATAGRAM_H + +#include <QtCore/qbytearray.h> +#include <QtNetwork/qhostaddress.h> + +#ifndef QT_NO_UDPSOCKET + +QT_BEGIN_NAMESPACE + +class QNetworkDatagramPrivate; +class QUdpSocketPrivate; + +class Q_NETWORK_EXPORT QNetworkDatagram +{ +public: + QNetworkDatagram(); + QNetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress = QHostAddress(), + quint16 port = 0); // implicit + QNetworkDatagram(const QNetworkDatagram &other); + QNetworkDatagram &operator=(const QNetworkDatagram &other); + ~QNetworkDatagram() + { if (d) destroy(d); } + + QNetworkDatagram(QNetworkDatagram &&other) Q_DECL_NOTHROW + : d(other.d) + { other.d = Q_NULLPTR; } + QNetworkDatagram &operator=(QNetworkDatagram &&other) Q_DECL_NOTHROW + { swap(other); return *this; } + + void swap(QNetworkDatagram &other) Q_DECL_NOTHROW + { qSwap(d, other.d); } + + void clear(); + bool isValid() const; + bool isNull() const + { return !isValid(); } + + uint interfaceIndex() const; + void setInterfaceIndex(uint index); + + QHostAddress senderAddress() const; + QHostAddress destinationAddress() const; + int senderPort() const; + int destinationPort() const; + void setSender(const QHostAddress &address, quint16 port = 0); + void setDestination(const QHostAddress &address, quint16 port); + + int hopLimit() const; + void setHopLimit(int count); + + QByteArray data() const; + void setData(const QByteArray &data); + +#ifdef Q_COMPILER_REF_QUALIFIERS + QNetworkDatagram makeReply(const QByteArray &payload) const & + { return makeReply_helper(payload); } + QNetworkDatagram makeReply(const QByteArray &payload) && + { makeReply_helper_inplace(payload); return *this; } +#else + QNetworkDatagram makeReply(const QByteArray &paylaod) const + { return makeReply_helper(paylaod); } +#endif + +private: + QNetworkDatagramPrivate *d; + friend class QUdpSocket; + + explicit QNetworkDatagram(QNetworkDatagramPrivate &dd); + QNetworkDatagram makeReply_helper(const QByteArray &data) const; + void makeReply_helper_inplace(const QByteArray &data); + static void destroy(QNetworkDatagramPrivate *d); +}; + +Q_DECLARE_SHARED(QNetworkDatagram) + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QNetworkDatagram) + +#endif // QT_NO_UDPSOCKET + +#endif // QNETWORKDATAGRAM_H diff --git a/src/network/kernel/qnetworkdatagram_p.h b/src/network/kernel/qnetworkdatagram_p.h index 4941d8c94b..e28be09508 100644 --- a/src/network/kernel/qnetworkdatagram_p.h +++ b/src/network/kernel/qnetworkdatagram_p.h @@ -45,6 +45,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtNetwork/qhostaddress.h> QT_BEGIN_NAMESPACE @@ -73,6 +74,18 @@ public: quint16 destinationPort; }; +class QNetworkDatagramPrivate +{ +public: + QNetworkDatagramPrivate(const QByteArray &data = QByteArray(), + const QHostAddress &dstAddr = QHostAddress(), quint16 port = 0) + : data(data), header(dstAddr, port) + {} + + QByteArray data; + QIpPacketHeader header; +}; + QT_END_NAMESPACE #endif // QNETWORKDATAGRAM_P_H diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp index c64d8e13cd..22d2e6bb70 100644 --- a/src/network/kernel/qnetworkinterface.cpp +++ b/src/network/kernel/qnetworkinterface.cpp @@ -536,7 +536,7 @@ QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const QNetworkInterface::interfaceFromName(name).index() \endcode - \sa interfaceFromName(), interfaceNameFromIndex() + \sa interfaceFromName(), interfaceNameFromIndex(), QNetworkDatagram::interfaceIndex() */ int QNetworkInterface::interfaceIndexFromName(const QString &name) { @@ -596,7 +596,7 @@ QNetworkInterface QNetworkInterface::interfaceFromIndex(int index) QNetworkInterface::interfaceFromIndex(index).name() \endcode - \sa interfaceFromIndex(), interfaceIndexFromName() + \sa interfaceFromIndex(), interfaceIndexFromName(), QNetworkDatagram::interfaceIndex() */ QString QNetworkInterface::interfaceNameFromIndex(int index) { diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h index c519de8081..c31621c3cb 100644 --- a/src/network/kernel/qnetworkinterface.h +++ b/src/network/kernel/qnetworkinterface.h @@ -40,6 +40,7 @@ #ifndef QNETWORKINTERFACE_H #define QNETWORKINTERFACE_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qshareddata.h> #include <QtCore/qscopedpointer.h> #include <QtNetwork/qhostaddress.h> diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h index aa21d7f92c..2dfc93cc18 100644 --- a/src/network/kernel/qnetworkinterface_p.h +++ b/src/network/kernel/qnetworkinterface_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/qatomic.h> #include <QtCore/qlist.h> #include <QtCore/qreadwritelock.h> 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.h b/src/network/kernel/qnetworkproxy.h index e60a84fa34..c9f4372596 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -40,6 +40,7 @@ #ifndef QNETWORKPROXY_H #define QNETWORKPROXY_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtNetwork/qhostaddress.h> #include <QtNetwork/qnetworkrequest.h> #include <QtCore/qshareddata.h> diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp index 06a6fbac45..37126298c6 100644 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ b/src/network/kernel/qnetworkproxy_mac.cpp @@ -234,60 +234,55 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) QCFType<CFStringRef> cfPacLocation = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, pacLocationSetting, NULL, NULL, kCFStringEncodingUTF8); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType<CFDataRef> pacData; - QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); - if (!pacUrl) { - qWarning("Invalid PAC URL \"%s\"", qPrintable(QCFString::toQString(cfPacLocation))); - return result; - } - SInt32 errorCode; - if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, pacUrl, &pacData, NULL, NULL, &errorCode)) { - QString pacLocation = QCFString::toQString(cfPacLocation); - qWarning("Unable to get the PAC script at \"%s\" (%s)", qPrintable(pacLocation), cfurlErrorDescription(errorCode)); - return result; - } - if (!pacData) { - qWarning("\"%s\" returned an empty PAC script", qPrintable(QCFString::toQString(cfPacLocation))); - return result; - } - QCFType<CFStringRef> pacScript = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, pacData, kCFStringEncodingISOLatin1); - if (!pacScript) { - // This should never happen, but the documentation says it may return NULL if there was a problem creating the object. - QString pacLocation = QCFString::toQString(cfPacLocation); - qWarning("Unable to read the PAC script at \"%s\"", qPrintable(pacLocation)); - return result; - } - - QByteArray encodedURL = query.url().toEncoded(); // converted to UTF-8 - if (encodedURL.isEmpty()) { - return result; // Invalid URL, abort - } - - QCFType<CFURLRef> targetURL = CFURLCreateWithBytes(kCFAllocatorDefault, (UInt8*)encodedURL.data(), encodedURL.size(), kCFStringEncodingUTF8, NULL); - if (!targetURL) { - return result; // URL creation problem, abort - } - - QCFType<CFErrorRef> pacError; - QCFType<CFArrayRef> proxies = CFNetworkCopyProxiesForAutoConfigurationScript(pacScript, targetURL, &pacError); - if (!proxies) { - QString pacLocation = QCFString::toQString(cfPacLocation); - QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacError); - qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QCFString::toQString(pacErrorDescription))); - return result; - } - - CFIndex size = CFArrayGetCount(proxies); - for (CFIndex i = 0; i < size; ++i) { - CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(proxies, i); - result << proxyFromDictionary(proxy); - } + QCFType<CFDataRef> pacData; + QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); + if (!pacUrl) { + qWarning("Invalid PAC URL \"%s\"", qPrintable(QCFString::toQString(cfPacLocation))); return result; - } else { + } + SInt32 errorCode; + if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, pacUrl, &pacData, NULL, NULL, &errorCode)) { QString pacLocation = QCFString::toQString(cfPacLocation); - qWarning("Mac system proxy: PAC script at \"%s\" not handled", qPrintable(pacLocation)); + qWarning("Unable to get the PAC script at \"%s\" (%s)", qPrintable(pacLocation), cfurlErrorDescription(errorCode)); + return result; + } + if (!pacData) { + qWarning("\"%s\" returned an empty PAC script", qPrintable(QCFString::toQString(cfPacLocation))); + return result; + } + QCFType<CFStringRef> pacScript = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, pacData, kCFStringEncodingISOLatin1); + if (!pacScript) { + // This should never happen, but the documentation says it may return NULL if there was a problem creating the object. + QString pacLocation = QCFString::toQString(cfPacLocation); + qWarning("Unable to read the PAC script at \"%s\"", qPrintable(pacLocation)); + return result; + } + + QByteArray encodedURL = query.url().toEncoded(); // converted to UTF-8 + if (encodedURL.isEmpty()) { + return result; // Invalid URL, abort + } + + QCFType<CFURLRef> targetURL = CFURLCreateWithBytes(kCFAllocatorDefault, (UInt8*)encodedURL.data(), encodedURL.size(), kCFStringEncodingUTF8, NULL); + if (!targetURL) { + return result; // URL creation problem, abort + } + + QCFType<CFErrorRef> pacError; + QCFType<CFArrayRef> proxies = CFNetworkCopyProxiesForAutoConfigurationScript(pacScript, targetURL, &pacError); + if (!proxies) { + QString pacLocation = QCFString::toQString(cfPacLocation); + QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacError); + qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QCFString::toQString(pacErrorDescription))); + return result; + } + + CFIndex size = CFArrayGetCount(proxies); + for (CFIndex i = 0; i < size; ++i) { + CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(proxies, i); + result << proxyFromDictionary(proxy); } + return result; } } diff --git a/src/network/kernel/qnetworkproxy_p.h b/src/network/kernel/qnetworkproxy_p.h index 74cc4105a0..0b0dcd3a68 100644 --- a/src/network/kernel/qnetworkproxy_p.h +++ b/src/network/kernel/qnetworkproxy_p.h @@ -52,6 +52,8 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> + #ifndef QT_NO_NETWORKPROXY QT_BEGIN_NAMESPACE diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 513eeaac12..2727bd9257 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) { @@ -361,7 +358,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: @@ -412,7 +409,7 @@ private: QVector<HKEY> m_registryHandles; }; } // namespace -#endif // !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#endif // !defined(Q_OS_WINRT) class QWindowsSystemProxy { @@ -431,7 +428,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; @@ -467,7 +464,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 @@ -477,12 +474,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")); @@ -570,7 +562,6 @@ void QWindowsSystemProxy::init() } functional = isAutoConfig || !proxyServerList.isEmpty(); -#endif } QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) diff --git a/src/network/kernel/qnetworkfunctions_wince.h b/src/network/kernel/qtnetworkglobal.h index 0e464a47f3..192601970a 100644 --- a/src/network/kernel/qnetworkfunctions_wince.h +++ b/src/network/kernel/qtnetworkglobal.h @@ -37,60 +37,24 @@ ** ****************************************************************************/ -#ifndef QNETWORKFUNCTIONS_WINCE_H -#define QNETWORKFUNCTIONS_WINCE_H +#ifndef QTNETWORKGLOBAL_H +#define QTNETWORKGLOBAL_H -#if 0 -#pragma qt_sync_stop_processing -#endif - -#ifdef Q_OS_WINCE - -#include <qt_windows.h> +#include <QtCore/qglobal.h> QT_BEGIN_NAMESPACE -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; +#ifndef QT_STATIC +# if defined(QT_BUILD_NETWORK_LIB) +# define Q_NETWORK_EXPORT Q_DECL_EXPORT +# else +# define Q_NETWORK_EXPORT Q_DECL_IMPORT +# endif #else -typedef ENUM_SERVICE_STATUS_PROCESSA ENUM_SERVICE_STATUS_PROCESS; -typedef LPENUM_SERVICE_STATUS_PROCESSA LPENUM_SERVICE_STATUS_PROCESS; -#endif // UNICODE +# define Q_NETWORK_EXPORT +#endif QT_END_NAMESPACE -#endif // Q_OS_WINCE -#endif // QNETWORKFUNCTIONS_WINCE_H +#endif + diff --git a/src/network/kernel/qtnetworkglobal_p.h b/src/network/kernel/qtnetworkglobal_p.h new file mode 100644 index 0000000000..51347e440d --- /dev/null +++ b/src/network/kernel/qtnetworkglobal_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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 QTNETWORKGLOBAL_P_H +#define QTNETWORKGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtNetwork/qtnetworkglobal.h> +#include <QtCore/private/qglobal_p.h> + +#endif // QTNETWORKGLOBAL_P_H diff --git a/src/network/kernel/qurlinfo_p.h b/src/network/kernel/qurlinfo_p.h index b239f94c31..3a430a3321 100644 --- a/src/network/kernel/qurlinfo_p.h +++ b/src/network/kernel/qurlinfo_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/qdatetime.h> #include <QtCore/qstring.h> #include <QtCore/qiodevice.h> |