From efac964bde3070d23031243f900dea0491df9862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Thu, 2 Feb 2017 17:12:37 +0200 Subject: [PATCH] Performance|Network|libcore: Keep local IP addresses cached On some platforms it takes a while to query the IP addresses of all the available network interfaces. Now this query is done in the background and the results are cached for quick access. --- doomsday/sdk/libcore/src/net/address.cpp | 6 +- doomsday/sdk/libcore/src/net/beacon.cpp | 1 - .../sdk/libcore/src/net/networkinterfaces.cpp | 97 +++++++++++++++++++ .../sdk/libcore/src/net/networkinterfaces.h | 57 +++++++++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 doomsday/sdk/libcore/src/net/networkinterfaces.cpp create mode 100644 doomsday/sdk/libcore/src/net/networkinterfaces.h diff --git a/doomsday/sdk/libcore/src/net/address.cpp b/doomsday/sdk/libcore/src/net/address.cpp index 3a74b629c6..b7ec234499 100644 --- a/doomsday/sdk/libcore/src/net/address.cpp +++ b/doomsday/sdk/libcore/src/net/address.cpp @@ -19,9 +19,9 @@ #include "de/Address" #include "de/String" +#include "networkinterfaces.h" #include -#include #include namespace de { @@ -171,9 +171,9 @@ bool Address::isHostLocal(QHostAddress const &host) // static if (host.isLoopback()) return true; QHostAddress const hostv6(host.toIPv6Address()); - foreach (QHostAddress addr, QNetworkInterface::allAddresses()) + foreach (QHostAddress addr, internal::NetworkInterfaces::get().allAddresses()) { - if (QHostAddress(addr.toIPv6Address()) == hostv6) + if (addr == hostv6) return true; } return false; diff --git a/doomsday/sdk/libcore/src/net/beacon.cpp b/doomsday/sdk/libcore/src/net/beacon.cpp index 08b46b0b9f..ed6c208852 100644 --- a/doomsday/sdk/libcore/src/net/beacon.cpp +++ b/doomsday/sdk/libcore/src/net/beacon.cpp @@ -22,7 +22,6 @@ #include "de/LogBuffer" #include #include -#include #include #include diff --git a/doomsday/sdk/libcore/src/net/networkinterfaces.cpp b/doomsday/sdk/libcore/src/net/networkinterfaces.cpp new file mode 100644 index 0000000000..82d05bdc18 --- /dev/null +++ b/doomsday/sdk/libcore/src/net/networkinterfaces.cpp @@ -0,0 +1,97 @@ +/** @file networkinterfaces.cpp Information about network interfaces. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "networkinterfaces.h" +#include "de/Task" +#include "de/TaskPool" + +#include +#include + +namespace de { +namespace internal { + +DENG2_PIMPL(NetworkInterfaces), public Lockable +{ + struct AddressQueryTask : public Task + { + NetworkInterfaces::Impl *d; + + AddressQueryTask(NetworkInterfaces::Impl *d) : d(d) {} + + void runTask() override + { + QList ipv6; + foreach (QHostAddress addr, QNetworkInterface::allAddresses()) + { + ipv6 << QHostAddress(addr.toIPv6Address()); + } + + // Submit the updated information. + { + DENG2_GUARD(d); + d->addresses = ipv6; + d->gotAddresses = true; + } + + qDebug() << "Local IP addresses:" << ipv6; + } + }; + + QList addresses; // lock before access + TaskPool tasks; + QTimer updateTimer; + bool gotAddresses = false; + + Impl(Public *i) : Base(i) + { + updateTimer.setInterval(1000 * 60 * 1); + updateTimer.setSingleShot(false); + QObject::connect(&updateTimer, &QTimer::timeout, [this] () + { + tasks.start(new AddressQueryTask(this)); + }); + updateTimer.start(); + tasks.start(new AddressQueryTask(this)); + } +}; + +NetworkInterfaces::NetworkInterfaces() + : d(new Impl(this)) +{} + +QList NetworkInterfaces::allAddresses() const +{ + if (!d->gotAddresses) + { + // Too early... + d->tasks.waitForDone(); + } + + DENG2_GUARD(d); + return d->addresses; +} + +NetworkInterfaces &NetworkInterfaces::get() // static +{ + static NetworkInterfaces nif; + return nif; +} + +} // namespace internal +} // namespace de diff --git a/doomsday/sdk/libcore/src/net/networkinterfaces.h b/doomsday/sdk/libcore/src/net/networkinterfaces.h new file mode 100644 index 0000000000..708512ef39 --- /dev/null +++ b/doomsday/sdk/libcore/src/net/networkinterfaces.h @@ -0,0 +1,57 @@ +/** @file networkinterfaces.h Information about network interfaces. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_NETWORKINTERFACES_H +#define LIBDENG2_NETWORKINTERFACES_H + +#include "de/libcore.h" +#include +#include + +namespace de { +namespace internal { + +/** + * Information abuot network interfaces. + * + * Maintains a quickly-accessible copy of the network interface data. + */ +class NetworkInterfaces +{ +public: + static NetworkInterfaces &get(); + +public: + NetworkInterfaces(); + + /** + * Returns a cached copy of the list of network addresses for all of the currently + * available network interfaces. Updated periodically in the background. + * + * @return Network interface addresses, in IPv6 format. + */ + QList allAddresses() const; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace internal +} // namespace de + +#endif // LIBDENG2_NETWORKINTERFACES_H