diff options
Diffstat (limited to 'src/network/kernel')
-rw-r--r-- | src/network/kernel/kernel.pri | 3 | ||||
-rw-r--r-- | src/network/kernel/qdnslookup.cpp | 4 | ||||
-rw-r--r-- | src/network/kernel/qhostaddress.cpp | 86 | ||||
-rw-r--r-- | src/network/kernel/qhostaddress.h | 10 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.cpp | 156 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.h | 63 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo_p.h | 42 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy.cpp | 19 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy.h | 4 |
9 files changed, 328 insertions, 59 deletions
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 005f000c25..a80b2d387e 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -56,8 +56,7 @@ win32: { mac { LIBS_PRIVATE += -framework CoreFoundation - !uikit: LIBS_PRIVATE += -framework CoreServices - !if(watchos:CONFIG(device, simulator|device)): LIBS_PRIVATE += -framework SystemConfiguration + !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration } osx:SOURCES += kernel/qnetworkproxy_mac.cpp diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp index 02df00a590..6203ba37b3 100644 --- a/src/network/kernel/qdnslookup.cpp +++ b/src/network/kernel/qdnslookup.cpp @@ -58,7 +58,7 @@ static bool qt_qdnsmailexchangerecord_less_than(const QDnsMailExchangeRecord &r1 return r1.preference() < r2.preference(); } -/*! +/* Sorts a list of QDnsMailExchangeRecord objects according to RFC 5321. */ @@ -100,7 +100,7 @@ static bool qt_qdnsservicerecord_less_than(const QDnsServiceRecord &r1, const QD && r1.weight() == 0 && r2.weight() > 0); } -/*! +/* Sorts a list of QDnsServiceRecord objects according to RFC 2782. */ diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index fc753204a9..b8c0584a62 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -63,12 +63,6 @@ QT_BEGIN_NAMESPACE -#define QT_ENSURE_PARSED(a) \ - do { \ - if (!(a)->d->isParsed) \ - (a)->d->parse(); \ - } while (0) - #ifdef Q_OS_WIN // sockaddr_in6 size changed between old and new SDK // Only the new version is the correct one, so always @@ -100,7 +94,7 @@ typedef struct { #endif -class QHostAddressPrivate +class QHostAddressPrivate : public QSharedData { public: QHostAddressPrivate(); @@ -109,10 +103,9 @@ public: void setAddress(const quint8 *a_); void setAddress(const Q_IPV6ADDR &a_); - bool parse(); + bool parse(const QString &ipString); void clear(); - QString ipString; QString scopeId; union { @@ -122,13 +115,12 @@ public: }; quint32 a; // IPv4 address qint8 protocol; - bool isParsed; friend class QHostAddress; }; QHostAddressPrivate::QHostAddressPrivate() - : a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol), isParsed(true) + : a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol) { memset(&a6, 0, sizeof(a6)); } @@ -137,7 +129,6 @@ void QHostAddressPrivate::setAddress(quint32 a_) { a = a_; protocol = QAbstractSocket::IPv4Protocol; - isParsed = true; //create mapped address, except for a_ == 0 (any) a6_64.c[0] = 0; @@ -187,7 +178,6 @@ static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6, const QHostAddress:: void QHostAddressPrivate::setAddress(const quint8 *a_) { protocol = QAbstractSocket::IPv6Protocol; - isParsed = true; memcpy(a6.c, a_, sizeof(a6)); a = 0; convertToIpv4(a, a6, (QHostAddress::ConvertV4MappedToIPv4 @@ -201,10 +191,10 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId) { - QString tmp = address; + QStringRef tmp(&address); int scopeIdPos = tmp.lastIndexOf(QLatin1Char('%')); if (scopeIdPos != -1) { - *scopeId = tmp.mid(scopeIdPos + 1); + *scopeId = tmp.mid(scopeIdPos + 1).toString(); tmp.chop(tmp.size() - scopeIdPos); } else { scopeId->clear(); @@ -212,9 +202,8 @@ static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()) == 0; } -Q_NEVER_INLINE bool QHostAddressPrivate::parse() +bool QHostAddressPrivate::parse(const QString &ipString) { - isParsed = true; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; QString a = ipString.simplified(); if (a.isEmpty()) @@ -242,13 +231,13 @@ void QHostAddressPrivate::clear() { a = 0; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; - isParsed = true; memset(&a6, 0, sizeof(a6)); } bool QNetmaskAddress::setAddress(const QString &address) { + d.detach(); length = -1; QHostAddress other; return other.setAddress(address) && setAddress(other); @@ -256,6 +245,8 @@ bool QNetmaskAddress::setAddress(const QString &address) bool QNetmaskAddress::setAddress(const QHostAddress &address) { + d.detach(); + static const quint8 zeroes[16] = { 0 }; union { quint32 v4; @@ -349,6 +340,7 @@ int QNetmaskAddress::prefixLength() const void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol proto, int newLength) { + d.detach(); length = newLength; if (length < 0 || length > (proto == QAbstractSocket::IPv4Protocol ? 32 : proto == QAbstractSocket::IPv6Protocol ? 128 : -1)) { @@ -377,6 +369,7 @@ void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol prot \class QHostAddress \brief The QHostAddress class provides an IP address. \ingroup network + \ingroup shared \inmodule QtNetwork This class holds an IPv4 or IPv6 address in a platform- and @@ -484,8 +477,7 @@ QHostAddress::QHostAddress(const Q_IPV6ADDR &ip6Addr) QHostAddress::QHostAddress(const QString &address) : d(new QHostAddressPrivate) { - d->ipString = address; - d->isParsed = false; + d->parse(address); } /*! @@ -513,7 +505,7 @@ QHostAddress::QHostAddress(const struct sockaddr *sockaddr) Constructs a copy of the given \a address. */ QHostAddress::QHostAddress(const QHostAddress &address) - : d(new QHostAddressPrivate(*address.d.data())) + : d(address.d) { } @@ -582,7 +574,7 @@ QHostAddress::~QHostAddress() */ QHostAddress &QHostAddress::operator=(const QHostAddress &address) { - *d.data() = *address.d.data(); + d = address.d; return *this; } @@ -633,6 +625,7 @@ QHostAddress &QHostAddress::operator=(SpecialAddress address) */ void QHostAddress::clear() { + d.detach(); d->clear(); } @@ -641,6 +634,7 @@ void QHostAddress::clear() */ void QHostAddress::setAddress(quint32 ip4Addr) { + d.detach(); d->setAddress(ip4Addr); } @@ -654,6 +648,7 @@ void QHostAddress::setAddress(quint32 ip4Addr) */ void QHostAddress::setAddress(quint8 *ip6Addr) { + d.detach(); d->setAddress(ip6Addr); } @@ -668,6 +663,7 @@ void QHostAddress::setAddress(quint8 *ip6Addr) */ void QHostAddress::setAddress(const quint8 *ip6Addr) { + d.detach(); d->setAddress(ip6Addr); } @@ -678,6 +674,7 @@ void QHostAddress::setAddress(const quint8 *ip6Addr) */ void QHostAddress::setAddress(const Q_IPV6ADDR &ip6Addr) { + d.detach(); d->setAddress(ip6Addr); } @@ -691,8 +688,8 @@ void QHostAddress::setAddress(const Q_IPV6ADDR &ip6Addr) */ bool QHostAddress::setAddress(const QString &address) { - d->ipString = address; - return d->parse(); + d.detach(); + return d->parse(address); } /*! @@ -705,6 +702,7 @@ bool QHostAddress::setAddress(const QString &address) */ void QHostAddress::setAddress(const struct sockaddr *sockaddr) { + d.detach(); #ifndef Q_OS_WINRT clear(); if (sockaddr->sa_family == AF_INET) @@ -752,7 +750,6 @@ quint32 QHostAddress::toIPv4Address() const */ quint32 QHostAddress::toIPv4Address(bool *ok) const { - QT_ENSURE_PARSED(this); quint32 dummy; if (ok) *ok = d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol @@ -767,7 +764,6 @@ quint32 QHostAddress::toIPv4Address(bool *ok) const */ QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const { - QT_ENSURE_PARSED(this); return QAbstractSocket::NetworkLayerProtocol(d->protocol); } @@ -787,7 +783,6 @@ QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const */ Q_IPV6ADDR QHostAddress::toIPv6Address() const { - QT_ENSURE_PARSED(this); return d->a6; } @@ -803,7 +798,6 @@ Q_IPV6ADDR QHostAddress::toIPv6Address() const */ QString QHostAddress::toString() const { - QT_ENSURE_PARSED(this); QString s; if (d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol) { @@ -855,7 +849,6 @@ QString QHostAddress::toString() const */ QString QHostAddress::scopeId() const { - QT_ENSURE_PARSED(this); return (d->protocol == QAbstractSocket::IPv6Protocol) ? d->scopeId : QString(); } @@ -873,7 +866,7 @@ QString QHostAddress::scopeId() const */ void QHostAddress::setScopeId(const QString &id) { - QT_ENSURE_PARSED(this); + d.detach(); if (d->protocol == QAbstractSocket::IPv6Protocol) d->scopeId = id; } @@ -886,7 +879,7 @@ void QHostAddress::setScopeId(const QString &id) */ bool QHostAddress::operator==(const QHostAddress &other) const { - return isEqual(other, StrictConversion); + return d == other.d || isEqual(other, StrictConversion); } /*! @@ -903,8 +896,8 @@ bool QHostAddress::operator==(const QHostAddress &other) const */ bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const { - QT_ENSURE_PARSED(this); - QT_ENSURE_PARSED(&other); + if (d == other.d) + return true; if (d->protocol == QAbstractSocket::IPv4Protocol) { switch (other.d->protocol) { @@ -956,7 +949,6 @@ bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const */ bool QHostAddress::operator ==(SpecialAddress other) const { - QT_ENSURE_PARSED(this); quint32 ip4 = INADDR_ANY; switch (other) { case Null: @@ -996,7 +988,6 @@ bool QHostAddress::operator ==(SpecialAddress other) const */ bool QHostAddress::isNull() const { - QT_ENSURE_PARSED(this); return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol; } @@ -1021,7 +1012,6 @@ bool QHostAddress::isNull() const */ bool QHostAddress::isInSubnet(const QHostAddress &subnet, int netmask) const { - QT_ENSURE_PARSED(this); if (subnet.protocol() != d->protocol || netmask < 0) return false; @@ -1120,7 +1110,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet) return invalid; int slash = subnet.indexOf(QLatin1Char('/')); - QString netStr = subnet; + QStringRef netStr(&subnet); if (slash != -1) netStr.truncate(slash); @@ -1151,7 +1141,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet) netmask = 128; QHostAddress net; - if (!net.setAddress(netStr)) + if (!net.setAddress(netStr.toString())) return invalid; // failed to parse the IP clearBits(net.d->a6.c, netmask, 128); @@ -1162,7 +1152,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet) return invalid; // invalid netmask // parse the address manually - auto parts = netStr.splitRef(QLatin1Char('.')); + auto parts = netStr.split(QLatin1Char('.')); if (parts.isEmpty() || parts.count() > 4) return invalid; // invalid IPv4 address @@ -1204,7 +1194,6 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet) */ bool QHostAddress::isLoopback() const { - QT_ENSURE_PARSED(this); if ((d->a & 0xFF000000) == 0x7F000000) return true; // v4 range (including IPv6 wrapped IPv4 addresses) if (d->protocol == QAbstractSocket::IPv6Protocol) { @@ -1230,7 +1219,6 @@ bool QHostAddress::isLoopback() const */ bool QHostAddress::isMulticast() const { - QT_ENSURE_PARSED(this); if ((d->a & 0xF0000000) == 0xE0000000) return true; // 224.0.0.0-239.255.255.255 (including v4-mapped IPv6 addresses) if (d->protocol == QAbstractSocket::IPv6Protocol) @@ -1256,10 +1244,8 @@ QDebug operator<<(QDebug d, const QHostAddress &address) \relates QHostAddress Returns a hash of the host address \a key, using \a seed to seed the calculation. */ -uint qHash(const QHostAddress &key, uint seed) +uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW { - // both lines might throw - QT_ENSURE_PARSED(&key); return qHashBits(key.d->a6.c, 16, seed); } @@ -1272,6 +1258,18 @@ uint qHash(const QHostAddress &key, uint seed) \sa isEqual() */ + +/*! + \relates QHostAddress + \since 5.9 + \fn operator!=(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs) + + Returns \c false if special address \a lhs is the same as host address \a rhs; + otherwise returns \c true. + + \sa isEqual() +*/ + #ifndef QT_NO_DATASTREAM /*! \relates QHostAddress diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 10fe33f6fa..fdbdbfc72c 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -44,7 +44,7 @@ #include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qpair.h> #include <QtCore/qstring.h> -#include <QtCore/qscopedpointer.h> +#include <QtCore/qshareddata.h> #include <QtNetwork/qabstractsocket.h> struct sockaddr; @@ -66,7 +66,7 @@ typedef QIPv6Address Q_IPV6ADDR; class QHostAddress; // qHash is a friend, but we can't use default arguments for friends (ยง8.3.6.4) -Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed = 0); +Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed = 0) Q_DECL_NOTHROW; class Q_NETWORK_EXPORT QHostAddress { @@ -152,15 +152,17 @@ public: static QPair<QHostAddress, int> parseSubnet(const QString &subnet); - friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed); + friend Q_NETWORK_EXPORT uint qHash(const QHostAddress &key, uint seed) Q_DECL_NOTHROW; protected: - QScopedPointer<QHostAddressPrivate> d; + QExplicitlySharedDataPointer<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) { return address2 == address1; } +inline bool operator!=(QHostAddress::SpecialAddress lhs, const QHostAddress &rhs) +{ return rhs != lhs; } #ifndef QT_NO_DEBUG_STREAM Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QHostAddress &); diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 88df65dbcb..d3a1858f86 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -95,6 +95,38 @@ std::pair<OutputIt1, OutputIt2> separate_if(InputIt first, InputIt last, OutputI } return std::make_pair(dest1, dest2); } + +int get_signal_index() +{ + static auto senderMetaObject = &QHostInfoResult::staticMetaObject; + static auto signal = &QHostInfoResult::resultsReady; + int signal_index = -1; + void *args[] = { &signal_index, &signal }; + senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args); + return signal_index + QMetaObjectPrivate::signalOffset(senderMetaObject); +} + +void emit_results_ready(const QHostInfo &hostInfo, const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj) +{ + static const int signal_index = get_signal_index(); + auto result = new QHostInfoResult(receiver, slotObj); + Q_CHECK_PTR(result); + const int nargs = 2; + auto types = reinterpret_cast<int *>(malloc(nargs * sizeof(int))); + Q_CHECK_PTR(types); + types[0] = QMetaType::type("void"); + types[1] = QMetaType::type("QHostInfo"); + auto args = reinterpret_cast<void **>(malloc(nargs * sizeof(void *))); + Q_CHECK_PTR(args); + args[0] = 0; + args[1] = QMetaType::create(types[1], &hostInfo); + Q_CHECK_PTR(args[1]); + auto metaCallEvent = new QMetaCallEvent(slotObj, nullptr, signal_index, nargs, types, args); + Q_CHECK_PTR(metaCallEvent); + qApp->postEvent(result, metaCallEvent); +} + } /*! @@ -151,7 +183,11 @@ std::pair<OutputIt1, OutputIt2> separate_if(InputIt first, InputIt last, OutputI \sa QAbstractSocket, {http://www.rfc-editor.org/rfc/rfc3492.txt}{RFC 3492} */ -static QBasicAtomicInt theIdCounter = Q_BASIC_ATOMIC_INITIALIZER(1); +static int nextId() +{ + static QBasicAtomicInt counter; + return 1 + counter.fetchAndAddRelaxed(1); +} /*! Looks up the IP address(es) associated with host name \a name, and @@ -197,7 +233,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, qRegisterMetaType<QHostInfo>(); - int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID + int id = nextId(); // generate unique ID if (name.isEmpty()) { if (!receiver) @@ -243,6 +279,67 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, } /*! + \fn int QHostInfo::lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function) + + \since 5.9 + + \overload + + Looks up the IP address(es) associated with host name \a name, and + returns an ID for the lookup. When the result of the lookup is + ready, the slot or signal \a function in \a receiver is called with + a QHostInfo argument. The QHostInfo object can then be inspected + to get the results of the lookup. + + \note There is no guarantee on the order the signals will be emitted + if you start multiple requests with lookupHost(). + + \sa abortHostLookup(), addresses(), error(), fromName() +*/ + +/*! + \fn int QHostInfo::lookupHost(const QString &name, Functor functor) + + \since 5.9 + + \overload + + Looks up the IP address(es) associated with host name \a name, and + returns an ID for the lookup. When the result of the lookup is + ready, the \a functor is called with a QHostInfo argument. The + QHostInfo object can then be inspected to get the results of the + lookup. + \note There is no guarantee on the order the signals will be emitted + if you start multiple requests with lookupHost(). + + \sa abortHostLookup(), addresses(), error(), fromName() +*/ + +/*! + \fn int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor) + + \since 5.9 + + \overload + + Looks up the IP address(es) associated with host name \a name, and + returns an ID for the lookup. When the result of the lookup is + ready, the \a functor is called with a QHostInfo argument. The + QHostInfo object can then be inspected to get the results of the + lookup. + + If \a context is destroyed before the lookup completes, the + \a functor will not be called. The \a functor will be run in the + thread of \a context. The context's thread must have a running Qt + event loop. + + \note There is no guarantee on the order the signals will be emitted + if you start multiple requests with lookupHost(). + + \sa abortHostLookup(), addresses(), error(), fromName() +*/ + +/*! Aborts the host lookup with the ID \a id, as returned by lookupHost(). \sa lookupHost(), lookupId() @@ -487,11 +584,66 @@ QString QHostInfo::localHostName() \sa hostName() */ +int QHostInfo::lookupHostImpl(const QString &name, + const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj) +{ +#if defined QHOSTINFO_DEBUG + qDebug("QHostInfo::lookupHost(\"%s\", %p, %p)", + name.toLatin1().constData(), receiver, slotObj); +#endif + + if (!QAbstractEventDispatcher::instance(QThread::currentThread())) { + qWarning("QHostInfo::lookupHost() called with no event dispatcher"); + return -1; + } + + qRegisterMetaType<QHostInfo>(); + + int id = nextId(); // generate unique ID + + if (Q_UNLIKELY(name.isEmpty())) { + QHostInfo hostInfo(id); + hostInfo.setError(QHostInfo::HostNotFound); + hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given")); + emit_results_ready(hostInfo, receiver, slotObj); + return id; + } + + QHostInfoLookupManager *manager = theHostInfoLookupManager(); + + if (Q_LIKELY(manager)) { + // the application is still alive + if (manager->cache.isEnabled()) { + // check cache first + bool valid = false; + QHostInfo info = manager->cache.get(name, &valid); + if (valid) { + info.setLookupId(id); + emit_results_ready(info, receiver, slotObj); + return id; + } + } + + // cache is not enabled or it was not in the cache, do normal lookup + QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id, receiver, slotObj); + manager->scheduleLookup(runnable); + } + return id; +} + QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i) : toBeLookedUp(hn), id(i) { setAutoDelete(true); } +QHostInfoRunnable::QHostInfoRunnable(const QString &hn, int i, const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj) : + toBeLookedUp(hn), id(i), resultEmitter(receiver, slotObj) +{ + setAutoDelete(true); +} + // the QHostInfoLookupManager will at some point call this via a QThreadPool void QHostInfoRunnable::run() { diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index 9b4a4853d9..4484d718bd 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -87,8 +87,71 @@ public: static QString localHostName(); static QString localDomainName(); +#ifdef Q_QDOC + template<typename PointerToMemberFunction> + static int QHostInfo::lookupHost(const QString &name, const QObject *receiver, + PointerToMemberFunction function); + template<typename Functor> + static int QHostInfo::lookupHost(const QString &name, Functor functor); + template<typename Functor> + static int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor); +#else + // lookupHost to a QObject slot + template <typename Func> + static inline int lookupHost(const QString &name, + const typename QtPrivate::FunctionPointer<Func>::Object *receiver, + Func slot) + { + typedef QtPrivate::FunctionPointer<Func> SlotType; + + typedef QtPrivate::FunctionPointer<void (*)(QHostInfo)> SignalType; + Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), + "The slot requires more arguments than the signal provides."); + Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, + typename SlotType::Arguments>::value), + "Signal and slot arguments are not compatible."); + Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, + typename SignalType::ReturnType>::value), + "Return type of the slot is not compatible " + "with the return type of the signal."); + + auto slotObj = new QtPrivate::QSlotObject<Func, typename SlotType::Arguments, void>(slot); + return lookupHostImpl(name, receiver, slotObj); + } + + // lookupHost to a callable (without context) + template <typename Func> + static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction && + !std::is_same<const char *, Func>::value, int>::type + lookupHost(const QString &name, Func slot) + { + return lookupHost(name, nullptr, slot); + } + + // lookupHost to a functor or function pointer (with context) + template <typename Func1> + static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction && + !std::is_same<const char*, Func1>::value, int>::type + lookupHost(const QString &name, QObject *context, Func1 slot) + { + typedef QtPrivate::FunctionPointer<Func1> SlotType; + + Q_STATIC_ASSERT_X(int(SlotType::ArgumentCount) <= 1, + "The slot must not require more than one argument"); + + auto slotObj = new QtPrivate::QFunctorSlotObject<Func1, 1, + typename QtPrivate::List<QHostInfo>, + void>(slot); + return lookupHostImpl(name, context, slotObj); + } +#endif // Q_QDOC + private: QScopedPointer<QHostInfoPrivate> d; + + static int lookupHostImpl(const QString &name, + const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj); }; QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index ba342bf533..dd46818a19 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -54,6 +54,7 @@ #include <QtNetwork/private/qtnetworkglobal_p.h> #include "QtCore/qcoreapplication.h" #include "private/qcoreapplication_p.h" +#include "private/qmetaobject_p.h" #include "QtNetwork/qhostinfo.h" #include "QtCore/qmutex.h" #include "QtCore/qwaitcondition.h" @@ -77,10 +78,47 @@ QT_BEGIN_NAMESPACE class QHostInfoResult : public QObject { Q_OBJECT + + QPointer<const QObject> receiver = nullptr; + QtPrivate::QSlotObjectBase *slotObj = nullptr; + +public: + QHostInfoResult() = default; + QHostInfoResult(const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) : + receiver(receiver), + slotObj(slotObj) + { + connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, + &QObject::deleteLater); + if (slotObj && receiver) + moveToThread(receiver->thread()); + } + public Q_SLOTS: inline void emitResultsReady(const QHostInfo &info) { - emit resultsReady(info); + if (slotObj) { + QHostInfo copy = info; + void *args[2] = { 0, reinterpret_cast<void *>(©) }; + slotObj->call(const_cast<QObject*>(receiver.data()), args); + slotObj->destroyIfLastRef(); + } else { + emit resultsReady(info); + } + } + +protected: + bool event(QEvent *event) + { + if (event->type() == QEvent::MetaCall) { + auto metaCallEvent = static_cast<QMetaCallEvent *>(event); + auto args = metaCallEvent->args(); + auto hostInfo = reinterpret_cast<QHostInfo *>(args[1]); + emitResultsReady(*hostInfo); + deleteLater(); + return true; + } + return QObject::event(event); } Q_SIGNALS: @@ -154,6 +192,8 @@ class QHostInfoRunnable : public QRunnable { public: QHostInfoRunnable(const QString &hn, int i); + QHostInfoRunnable(const QString &hn, int i, const QObject *receiver, + QtPrivate::QSlotObjectBase *slotObj); void run() Q_DECL_OVERRIDE; QString toBeLookedUp; diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 0be8a7f79e..11e8fa6264 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -1636,10 +1636,6 @@ QList<QNetworkProxy> QNetworkProxyFactory::proxyForQuery(const QNetworkProxyQuer } #ifndef QT_NO_DEBUG_STREAM -/*! - \since 5.0 - Outputs a QNetworkProxy details to a debug stream -*/ QDebug operator<<(QDebug debug, const QNetworkProxy &proxy) { QDebugStateSaver saver(debug); @@ -1688,6 +1684,21 @@ QDebug operator<<(QDebug debug, const QNetworkProxy &proxy) debug << '[' << scaps.join(QLatin1Char(' ')) << ']'; return debug; } + +QDebug operator<<(QDebug debug, const QNetworkProxyQuery &proxyQuery) +{ + QDebugStateSaver saver(debug); + debug.resetFormat().nospace() + << "ProxyQuery(" + << "type: " << proxyQuery.queryType() + << ", protocol: " << proxyQuery.protocolTag() + << ", peerPort: " << proxyQuery.peerPort() + << ", peerHostName: " << proxyQuery.peerHostName() + << ", localPort: " << proxyQuery.localPort() + << ", url: " << proxyQuery.url() + << ')'; + return debug; +} #endif QT_END_NAMESPACE diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h index 8fcb7e33cf..8699c313e9 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -56,6 +56,8 @@ class QNetworkConfiguration; class QNetworkProxyQueryPrivate; class Q_NETWORK_EXPORT QNetworkProxyQuery { + Q_GADGET + public: enum QueryType { TcpSocket, @@ -65,6 +67,7 @@ public: UrlRequest, SctpServer }; + Q_ENUM(QueryType) QNetworkProxyQuery(); explicit QNetworkProxyQuery(const QUrl &requestUrl, QueryType queryType = UrlRequest); @@ -222,6 +225,7 @@ public: #ifndef QT_NO_DEBUG_STREAM Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkProxy &proxy); +Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkProxyQuery &proxyQuery); #endif QT_END_NAMESPACE |