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