summaryrefslogtreecommitdiffstats
path: root/src/network/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/kernel')
-rw-r--r--src/network/kernel/kernel.pri3
-rw-r--r--src/network/kernel/qdnslookup.cpp4
-rw-r--r--src/network/kernel/qhostaddress.cpp86
-rw-r--r--src/network/kernel/qhostaddress.h10
-rw-r--r--src/network/kernel/qhostinfo.cpp156
-rw-r--r--src/network/kernel/qhostinfo.h63
-rw-r--r--src/network/kernel/qhostinfo_p.h42
-rw-r--r--src/network/kernel/qnetworkproxy.cpp19
-rw-r--r--src/network/kernel/qnetworkproxy.h4
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 *>(&copy) };
+ 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