File indexing completed on 2024-05-12 17:00:16

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  * SPDX-FileCopyrightText: 2021 Alessio Bonfiglio <alessio.bonfiglio@mail.polimi.it>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006  */
0007 
0008 #include "NetworkManagerBackend.h"
0009 
0010 #include <numeric>
0011 
0012 #include <QString>
0013 #include <QTimer>
0014 
0015 #include <NetworkManagerQt/Manager>
0016 #include <NetworkManagerQt/WirelessDevice>
0017 #include <NetworkManagerQt/ModemDevice>
0018 
0019 // Update rate in ms
0020 static const int UpdateRate = 500;
0021 
0022 NetworkManagerDevice::NetworkManagerDevice(const QString &id, QSharedPointer<NetworkManager::Device> device)
0023     : NetworkDevice(id, id)
0024     , m_device(device)
0025 {
0026     connect(m_device.data(), &NetworkManager::Device::activeConnectionChanged, this, &NetworkManagerDevice::update);
0027     connect(m_device.data(), &NetworkManager::Device::ipV4ConfigChanged, this, &NetworkManagerDevice::update);
0028     connect(m_device.data(), &NetworkManager::Device::ipV6ConfigChanged, this, &NetworkManagerDevice::update);
0029 
0030     connect(this, &NetworkManagerDevice::nameChanged, this, [this]() {
0031         m_networkSensor->setPrefix(name());
0032         m_signalSensor->setPrefix(name());
0033         m_ipv4Sensor->setPrefix(name());
0034         m_ipv4GatewaySensor->setPrefix(name());
0035         m_ipv4SubnetMaskSensor->setPrefix(name());
0036         m_ipv4WithPrefixLengthSensor->setPrefix(name());
0037         m_ipv4DNSSensor->setPrefix(name());
0038         m_ipv6Sensor->setPrefix(name());
0039         m_ipv6GatewaySensor->setPrefix(name());
0040         m_ipv6SubnetMaskSensor->setPrefix(name());
0041         m_ipv6WithPrefixLengthSensor->setPrefix(name());
0042         m_ipv6DNSSensor->setPrefix(name());
0043         m_downloadSensor->setPrefix(name());
0044         m_uploadSensor->setPrefix(name());
0045         m_downloadBitsSensor->setPrefix(name());
0046         m_uploadBitsSensor->setPrefix(name());
0047         m_totalDownloadSensor->setPrefix(name());
0048         m_totalUploadSensor->setPrefix(name());
0049     });
0050 
0051     m_statistics = m_device->deviceStatistics();
0052 
0053     // We always want to have the refresh rate to be 1000ms but it's a global property. So we store
0054     // the oustide rate. override any changes and restore it when we are destroyed.
0055     m_initialStatisticsRate = m_statistics->refreshRateMs();
0056     connect(m_statistics.get(), &NetworkManager::DeviceStatistics::refreshRateMsChanged, this, [this] (uint rate) {
0057         // Unfortunately we always get a change signal even when disconnecting before the setter and
0058         // connecting afterwards, so we have to do this and assume the first signal after a call is
0059         // caused by it. Iniitally true because of the call below
0060         static bool updatingRefreshRate = true;
0061         if (!updatingRefreshRate) {
0062             m_initialStatisticsRate = rate;
0063             m_statistics->setRefreshRateMs(UpdateRate);
0064         }
0065         updatingRefreshRate = !updatingRefreshRate;
0066     });
0067 
0068     // We want to display speed in bytes per second, so use a fixed one-second
0069     // update interval here so we are independant of the actual update rate of
0070     // the daemon.
0071     m_statistics->setRefreshRateMs(UpdateRate);
0072 
0073     // Unfortunately, the statistics interface does not emit change signals if
0074     // no change happened. This makes the change signals rather useless for our
0075     // case because we also need to know when no change happened, so that we
0076     // can update rate sensors to show 0. So instead use a timer and query the
0077     // statistics every UpdateRate ms, updating the sensors as needed.
0078     m_statisticsTimer = std::make_unique<QTimer>();
0079     m_statisticsTimer->setInterval(UpdateRate);
0080     connect(m_statisticsTimer.get(), &QTimer::timeout, this, [this]() {
0081         auto newDownload = m_statistics->rxBytes();
0082         auto previousDownload = m_totalDownloadSensor->value().toULongLong();
0083         if (previousDownload > 0) {
0084             m_downloadSensor->setValue((newDownload - previousDownload) * (1000 / UpdateRate));
0085             m_downloadBitsSensor->setValue((newDownload - previousDownload) * (1000 / UpdateRate) * 8);
0086         }
0087         m_totalDownloadSensor->setValue(newDownload);
0088 
0089         auto newUpload = m_statistics->txBytes();
0090         auto previousUpload = m_totalUploadSensor->value().toULongLong();
0091         if (previousUpload > 0) {
0092             m_uploadSensor->setValue((newUpload - previousUpload) * (1000 / UpdateRate));
0093             m_uploadBitsSensor->setValue((newUpload - previousUpload) * (1000 / UpdateRate) * 8);
0094         }
0095         m_totalUploadSensor->setValue(newUpload);
0096     });
0097 
0098     std::vector<KSysGuard::SensorProperty*> statisticSensors{m_downloadSensor, m_downloadBitsSensor, m_totalDownloadSensor, m_uploadSensor, m_uploadBitsSensor, m_totalUploadSensor};
0099     for (auto property : statisticSensors) {
0100         connect(property, &KSysGuard::SensorProperty::subscribedChanged, this, [this, statisticSensors](bool subscribed) {
0101             if (subscribed && !m_statisticsTimer->isActive()) {
0102                 m_statisticsTimer->start();
0103             } else if (std::none_of(statisticSensors.begin(), statisticSensors.end(), [](auto property) { return property->isSubscribed(); })) {
0104                 m_statisticsTimer->stop();
0105                 m_totalDownloadSensor->setValue(0);
0106                 m_totalUploadSensor->setValue(0);
0107             }
0108         });
0109     }
0110 
0111     if (m_device->type() == NetworkManager::Device::Wifi) {
0112         m_wifiDevice = m_device->as<NetworkManager::WirelessDevice>();
0113         connect(m_wifiDevice, &NetworkManager::WirelessDevice::activeConnectionChanged, this, &NetworkManagerDevice::updateWifi);
0114         connect(m_wifiDevice, &NetworkManager::WirelessDevice::networkAppeared, this, &NetworkManagerDevice::updateWifi);
0115         connect(m_wifiDevice, &NetworkManager::WirelessDevice::networkDisappeared, this, &NetworkManagerDevice::updateWifi);
0116         updateWifi();
0117     }
0118 
0119     update();
0120 }
0121 
0122 NetworkManagerDevice::~NetworkManagerDevice()
0123 {
0124     disconnect(m_statistics.get(), nullptr, this, nullptr);
0125     m_statistics->setRefreshRateMs(m_initialStatisticsRate);
0126 }
0127 
0128 void NetworkManagerDevice::update()
0129 {
0130     if (!m_device->activeConnection()) {
0131         if (m_connected) {
0132             m_connected = false;
0133             if (m_statisticsTimer->isActive()) {
0134                 m_restoreTimer = true;
0135                 m_statisticsTimer->stop();
0136             } else {
0137                 m_restoreTimer = false;
0138             }
0139             Q_EMIT disconnected(this);
0140         }
0141         return;
0142     }
0143 
0144     if (m_device->activeConnection() && !m_connected) {
0145         m_connected = true;
0146         if (m_restoreTimer) {
0147             m_statisticsTimer->start();
0148         }
0149 
0150         Q_EMIT connected(this);
0151     }
0152 
0153     setName(m_device->activeConnection()->connection()->name());
0154     m_networkSensor->setValue(name());
0155 
0156     auto dnsAccumulationFunction = [](QString &a, const QHostAddress& b) { return std::move(a).append(", ").append(b.toString()); };
0157     if (m_device->ipV4Config().isValid()) {
0158         auto ipv4 = m_device->ipV4Config().addresses().at(0).ip().toString();
0159         m_ipv4Sensor->setValue(ipv4);
0160         m_ipv4GatewaySensor->setValue(m_device->ipV4Config().gateway());
0161         m_ipv4SubnetMaskSensor->setValue(m_device->ipV4Config().addresses().at(0).netmask().toString());
0162         m_ipv4WithPrefixLengthSensor->setValue(static_cast<QString>(ipv4 + '/' + QString::number(m_device->ipV4Config().addresses().at(0).prefixLength())));
0163         auto dnsList = m_device->ipV4Config().nameservers();
0164         auto dnsListString = QString();
0165         if(!dnsList.isEmpty()) {
0166             dnsListString = std::accumulate(std::next(dnsList.begin()), dnsList.end(), dnsList.at(0).toString(),
0167                                             dnsAccumulationFunction);
0168         }
0169         m_ipv4DNSSensor->setValue(dnsListString);
0170     } else {
0171         m_ipv4Sensor->setValue(QString{});
0172         m_ipv4GatewaySensor->setValue(QString{});
0173         m_ipv4SubnetMaskSensor->setValue(QString{});
0174         m_ipv4WithPrefixLengthSensor->setValue(QString{});
0175         m_ipv4DNSSensor->setValue(QString{});
0176     }
0177 
0178     if (m_device->ipV6Config().isValid()) {
0179         auto ipv6 = m_device->ipV6Config().addresses().at(0).ip().toString();
0180         m_ipv6Sensor->setValue(ipv6);
0181         m_ipv6GatewaySensor->setValue(m_device->ipV6Config().gateway());
0182         m_ipv6SubnetMaskSensor->setValue(m_device->ipV6Config().addresses().at(0).netmask().toString());
0183         m_ipv6WithPrefixLengthSensor->setValue(static_cast<QString>(ipv6 + '/' + QString::number(m_device->ipV6Config().addresses().at(0).prefixLength())));
0184         auto dnsList = m_device->ipV6Config().nameservers();
0185         auto dnsListString = QString();
0186         if(!dnsList.isEmpty()) {
0187             dnsListString = std::accumulate(std::next(dnsList.begin()), dnsList.end(), dnsList.at(0).toString(),
0188                                             dnsAccumulationFunction);
0189         }
0190         m_ipv6DNSSensor->setValue(dnsListString);
0191     } else {
0192         m_ipv6Sensor->setValue(QString{});
0193         m_ipv6GatewaySensor->setValue(QString{});
0194         m_ipv6SubnetMaskSensor->setValue(QString{});
0195         m_ipv6WithPrefixLengthSensor->setValue(QString{});
0196         m_ipv6DNSSensor->setValue(QString{});
0197     }
0198 }
0199 
0200 bool NetworkManagerDevice::isConnected() const
0201 {
0202     return m_connected;
0203 }
0204 
0205 void NetworkManagerDevice::updateWifi()
0206 {
0207     if (!m_device->activeConnection()) {
0208         return;
0209     }
0210 
0211     auto activeConnectionName = m_wifiDevice->activeConnection()->connection()->name();
0212     const auto networks = m_wifiDevice->networks();
0213     std::for_each(networks.begin(), networks.end(), [this, activeConnectionName](QSharedPointer<NetworkManager::WirelessNetwork> network) {
0214         if (network->ssid() == activeConnectionName) {
0215             connect(network.data(), &NetworkManager::WirelessNetwork::signalStrengthChanged, m_signalSensor, &KSysGuard::SensorProperty::setValue, Qt::UniqueConnection);
0216             m_signalSensor->setValue(network->signalStrength());
0217         } else {
0218             network->disconnect(m_signalSensor);
0219         }
0220     });
0221 }
0222 
0223 NetworkManagerBackend::NetworkManagerBackend(QObject* parent)
0224     : NetworkBackend(parent)
0225 {
0226 }
0227 
0228 NetworkManagerBackend::~NetworkManagerBackend()
0229 {
0230     qDeleteAll(m_devices);
0231 }
0232 
0233 bool NetworkManagerBackend::isSupported()
0234 {
0235     if (NetworkManager::status() == NetworkManager::Unknown) {
0236         return false;
0237     } else {
0238         return true;
0239     }
0240 }
0241 
0242 void NetworkManagerBackend::start()
0243 {
0244     connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &NetworkManagerBackend::onDeviceAdded);
0245     connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &NetworkManagerBackend::onDeviceRemoved);
0246 
0247     const auto devices = NetworkManager::networkInterfaces();
0248     for (const auto &device : devices) {
0249         onDeviceAdded(device->uni());
0250     }
0251 }
0252 
0253 void NetworkManagerBackend::stop()
0254 {
0255     NetworkManager::notifier()->disconnect(this);
0256 }
0257 
0258 void NetworkManagerBackend::onDeviceAdded(const QString& uni)
0259 {
0260     auto device = NetworkManager::findNetworkInterface(uni);
0261     if (!device) {
0262         return;
0263     }
0264 
0265     switch (device->type()) {
0266         case NetworkManager::Device::Ethernet:
0267         case NetworkManager::Device::Wifi:
0268         case NetworkManager::Device::Bluetooth:
0269         case NetworkManager::Device::Modem:
0270         case NetworkManager::Device::Adsl:
0271             break;
0272         default:
0273             // Non-hardware devices, ignore them.
0274             return;
0275     }
0276 
0277     if (m_devices.contains(uni)) {
0278         return;
0279     }
0280 
0281     auto nmDevice = new NetworkManagerDevice(device->interfaceName(), device);
0282     connect(nmDevice, &NetworkManagerDevice::connected, this, &NetworkManagerBackend::deviceAdded);
0283     connect(nmDevice, &NetworkManagerDevice::disconnected, this, &NetworkManagerBackend::deviceRemoved);
0284     m_devices.insert(uni, nmDevice);
0285 
0286     if (nmDevice->isConnected()) {
0287         Q_EMIT deviceAdded(nmDevice);
0288     }
0289 }
0290 
0291 void NetworkManagerBackend::onDeviceRemoved(const QString& uni)
0292 {
0293     if (!m_devices.contains(uni)) {
0294         return;
0295     }
0296 
0297     auto device = m_devices.take(uni);
0298 
0299     if (device->isConnected()) {
0300         Q_EMIT deviceRemoved(device);
0301     }
0302 
0303     delete device;
0304 }
0305