File indexing completed on 2023-12-03 12:27:02
0001 /* 0002 SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "networkstatus.h" 0008 #include "uiutils.h" 0009 0010 #include <QDBusConnection> 0011 #include <QDBusConnectionInterface> 0012 0013 #include <NetworkManagerQt/ActiveConnection> 0014 #include <NetworkManagerQt/Connection> 0015 0016 #include <KLocalizedString> 0017 0018 NetworkStatus::SortedConnectionType NetworkStatus::connectionTypeToSortedType(NetworkManager::ConnectionSettings::ConnectionType type) 0019 { 0020 switch (type) { 0021 case NetworkManager::ConnectionSettings::Adsl: 0022 return NetworkStatus::NetworkStatus::Adsl; 0023 break; 0024 case NetworkManager::ConnectionSettings::Bluetooth: 0025 return NetworkStatus::Bluetooth; 0026 break; 0027 case NetworkManager::ConnectionSettings::Cdma: 0028 return NetworkStatus::Cdma; 0029 break; 0030 case NetworkManager::ConnectionSettings::Gsm: 0031 return NetworkStatus::Gsm; 0032 break; 0033 case NetworkManager::ConnectionSettings::Infiniband: 0034 return NetworkStatus::Infiniband; 0035 break; 0036 case NetworkManager::ConnectionSettings::OLPCMesh: 0037 return NetworkStatus::OLPCMesh; 0038 break; 0039 case NetworkManager::ConnectionSettings::Pppoe: 0040 return NetworkStatus::Pppoe; 0041 break; 0042 case NetworkManager::ConnectionSettings::Vpn: 0043 return NetworkStatus::Vpn; 0044 break; 0045 case NetworkManager::ConnectionSettings::Wired: 0046 return NetworkStatus::Wired; 0047 break; 0048 case NetworkManager::ConnectionSettings::Wireless: 0049 return NetworkStatus::Wireless; 0050 break; 0051 case NetworkManager::ConnectionSettings::WireGuard: 0052 return NetworkStatus::Wireguard; 0053 break; 0054 default: 0055 return NetworkStatus::Other; 0056 break; 0057 } 0058 } 0059 0060 NetworkStatus::NetworkStatus(QObject *parent) 0061 : QObject(parent) 0062 { 0063 connect(NetworkManager::notifier(), &NetworkManager::Notifier::connectivityChanged, this, &NetworkStatus::changeActiveConnections); 0064 connect(NetworkManager::notifier(), &NetworkManager::Notifier::connectivityChanged, this, &NetworkStatus::connectivityChanged); 0065 connect(NetworkManager::notifier(), &NetworkManager::Notifier::statusChanged, this, &NetworkStatus::statusChanged); 0066 connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionsChanged, this, QOverload<>::of(&NetworkStatus::activeConnectionsChanged)); 0067 0068 activeConnectionsChanged(); 0069 statusChanged(NetworkManager::status()); 0070 0071 QDBusPendingReply<uint> pendingReply = NetworkManager::checkConnectivity(); 0072 auto callWatcher = new QDBusPendingCallWatcher(pendingReply); 0073 connect(callWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) { 0074 QDBusPendingReply<uint> reply = *watcher; 0075 if (reply.isValid()) { 0076 connectivityChanged((NetworkManager::Connectivity)reply.value()); 0077 } 0078 watcher->deleteLater(); 0079 }); 0080 } 0081 0082 NetworkStatus::~NetworkStatus() = default; 0083 0084 QUrl NetworkStatus::networkCheckUrl() 0085 { 0086 return QUrl(QStringLiteral("http://networkcheck.kde.org/")); 0087 } 0088 0089 QString NetworkStatus::activeConnections() const 0090 { 0091 return m_activeConnections; 0092 } 0093 0094 QString NetworkStatus::networkStatus() const 0095 { 0096 return m_networkStatus; 0097 } 0098 0099 NetworkManager::Connectivity NetworkStatus::connectivity() const 0100 { 0101 return NetworkManager::connectivity(); 0102 } 0103 0104 void NetworkStatus::activeConnectionsChanged() 0105 { 0106 for (const NetworkManager::ActiveConnection::Ptr &active : NetworkManager::activeConnections()) { 0107 connect(active.data(), &NetworkManager::ActiveConnection::default4Changed, this, &NetworkStatus::defaultChanged, Qt::UniqueConnection); 0108 connect(active.data(), &NetworkManager::ActiveConnection::default6Changed, this, &NetworkStatus::defaultChanged, Qt::UniqueConnection); 0109 connect(active.data(), &NetworkManager::ActiveConnection::stateChanged, this, &NetworkStatus::changeActiveConnections); 0110 } 0111 0112 changeActiveConnections(); 0113 } 0114 0115 void NetworkStatus::defaultChanged() 0116 { 0117 statusChanged(NetworkManager::status()); 0118 } 0119 0120 void NetworkStatus::statusChanged(NetworkManager::Status status) 0121 { 0122 const auto oldNetworkStatus = m_networkStatus; 0123 switch (status) { 0124 case NetworkManager::ConnectedLinkLocal: 0125 m_networkStatus = i18nc("A network device is connected, but there is only link-local connectivity", "Connected"); 0126 break; 0127 case NetworkManager::ConnectedSiteOnly: 0128 m_networkStatus = i18nc("A network device is connected, but there is only site-local connectivity", "Connected"); 0129 break; 0130 case NetworkManager::Connected: 0131 m_networkStatus = i18nc("A network device is connected, with global network connectivity", "Connected"); 0132 break; 0133 case NetworkManager::Asleep: 0134 m_networkStatus = i18nc("Networking is inactive and all devices are disabled", "Inactive"); 0135 break; 0136 case NetworkManager::Disconnected: 0137 m_networkStatus = i18nc("There is no active network connection", "Disconnected"); 0138 break; 0139 case NetworkManager::Disconnecting: 0140 m_networkStatus = i18nc("Network connections are being cleaned up", "Disconnecting"); 0141 break; 0142 case NetworkManager::Connecting: 0143 m_networkStatus = i18nc("A network device is connecting to a network and there is no other available network connection", "Connecting"); 0144 break; 0145 default: 0146 m_networkStatus = checkUnknownReason(); 0147 break; 0148 } 0149 0150 if (status == NetworkManager::ConnectedLinkLocal || status == NetworkManager::ConnectedSiteOnly || status == NetworkManager::Connected) { 0151 changeActiveConnections(); 0152 } else if (m_activeConnections != m_networkStatus) { 0153 m_activeConnections = m_networkStatus; 0154 Q_EMIT activeConnectionsChanged(m_activeConnections); 0155 } 0156 } 0157 0158 void NetworkStatus::changeActiveConnections() 0159 { 0160 if (NetworkManager::status() != NetworkManager::Connected && NetworkManager::status() != NetworkManager::ConnectedLinkLocal 0161 && NetworkManager::status() != NetworkManager::ConnectedSiteOnly) { 0162 return; 0163 } 0164 0165 QString activeConnections; 0166 const QString format = QStringLiteral("%1: %2"); 0167 0168 QList<NetworkManager::ActiveConnection::Ptr> activeConnectionList = NetworkManager::activeConnections(); 0169 std::sort(activeConnectionList.begin(), 0170 activeConnectionList.end(), 0171 [](const NetworkManager::ActiveConnection::Ptr &left, const NetworkManager::ActiveConnection::Ptr &right) { 0172 return NetworkStatus::connectionTypeToSortedType(left->type()) < NetworkStatus::connectionTypeToSortedType(right->type()); 0173 }); 0174 0175 for (const NetworkManager::ActiveConnection::Ptr &active : activeConnectionList) { 0176 if (!active->devices().isEmpty() && UiUtils::isConnectionTypeSupported(active->type())) { 0177 NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(active->devices().first()); 0178 if (device 0179 && ((device->type() != NetworkManager::Device::Generic && device->type() <= NetworkManager::Device::Team) 0180 || device->type() == 29) // TODO: Change to WireGuard enum value when it is added 0181 && device->interfaceName() != QLatin1String("lo")) { // TODO change to comparison with LocalHost enum value when it is added 0182 bool connecting = false; 0183 bool connected = false; 0184 QString conType; 0185 QString status; 0186 NetworkManager::VpnConnection::Ptr vpnConnection; 0187 0188 if (active->vpn()) { 0189 conType = i18n("VPN"); 0190 vpnConnection = active.objectCast<NetworkManager::VpnConnection>(); 0191 } else { 0192 conType = UiUtils::interfaceTypeLabel(device->type(), device); 0193 } 0194 0195 if (vpnConnection && active->vpn()) { 0196 if (vpnConnection->state() >= NetworkManager::VpnConnection::Prepare 0197 && vpnConnection->state() <= NetworkManager::VpnConnection::GettingIpConfig) { 0198 connecting = true; 0199 } else if (vpnConnection->state() == NetworkManager::VpnConnection::Activated) { 0200 connected = true; 0201 } 0202 } else { 0203 if (active->state() == NetworkManager::ActiveConnection::Activated) { 0204 connected = true; 0205 } else if (active->state() == NetworkManager::ActiveConnection::Activating) { 0206 connecting = true; 0207 } 0208 } 0209 0210 if (active->type() == NetworkManager::ConnectionSettings::ConnectionType::WireGuard) { 0211 conType = i18n("WireGuard"); 0212 connected = true; 0213 } 0214 0215 NetworkManager::Connection::Ptr connection = active->connection(); 0216 if (connecting) { 0217 status = i18n("Connecting to %1", connection->name()); 0218 } else if (connected) { 0219 switch (NetworkManager::connectivity()) { 0220 case NetworkManager::NoConnectivity: 0221 status = i18n("Connected to %1 (no connectivity)", connection->name()); 0222 break; 0223 case NetworkManager::Limited: 0224 status = i18n("Connected to %1 (limited connectivity)", connection->name()); 0225 break; 0226 case NetworkManager::Portal: 0227 status = i18n("Connected to %1 (log in required)", connection->name()); 0228 break; 0229 default: 0230 status = i18n("Connected to %1", connection->name()); 0231 break; 0232 } 0233 } 0234 0235 if (!activeConnections.isEmpty()) { 0236 activeConnections += QLatin1Char('\n'); 0237 } 0238 activeConnections += format.arg(conType, status); 0239 0240 connect(connection.data(), &NetworkManager::Connection::updated, this, &NetworkStatus::changeActiveConnections, Qt::UniqueConnection); 0241 } 0242 } 0243 } 0244 0245 if (m_activeConnections != activeConnections) { 0246 m_activeConnections = activeConnections; 0247 Q_EMIT activeConnectionsChanged(activeConnections); 0248 } 0249 } 0250 0251 QString NetworkStatus::checkUnknownReason() const 0252 { 0253 // Check if NetworkManager is running. 0254 if (!QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral(NM_DBUS_INTERFACE))) { 0255 return i18n("NetworkManager not running"); 0256 } 0257 0258 // Check for compatible NetworkManager version. 0259 if (NetworkManager::compareVersion(0, 9, 8) < 0) { 0260 return i18n("NetworkManager 0.9.8 required, found %1.", NetworkManager::version()); 0261 } 0262 0263 return i18nc("global connection state", "Unknown"); 0264 } 0265 0266 #include "moc_networkstatus.cpp"