/* SPDX-FileCopyrightText: 2014 Jan Grulich SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "fakenetwork.h" #include "connection.h" #include "wireddevice.h" #include "wirelessdevice.h" #include #include #include #include "../manager.h" #include "connectionsettings.h" FakeNetwork::FakeNetwork(QObject *parent) : QObject(parent) , m_activatingConnection(QDBusObjectPath("/")) , m_connectivity(NetworkManager::Connectivity::NoConnectivity) , m_networkingEnabled(true) , m_primaryConnection(QDBusObjectPath("/")) , m_state(20) , m_version(QLatin1String("0.9.10.0")) , m_wimaxEnabled(true) , m_wimaxHardwareEnabled(true) , m_wirelessEnabled(true) , m_wirelessHardwareEnabled(true) , m_wwanEnabled(true) , m_wwanHardwareEnabled(true) , m_activeConnectionsCounter(0) , m_deviceCounter(0) , m_settings(new Settings(this)) { qDBusRegisterMetaType(); registerService(); connect(m_settings, &Settings::connectionAdded, this, &FakeNetwork::onConnectionAdded); connect(m_settings, &Settings::connectionRemoved, this, &FakeNetwork::onConnectionRemoved); } FakeNetwork::~FakeNetwork() { unregisterService(); qDeleteAll(m_devices); delete m_settings; } QDBusObjectPath FakeNetwork::activatingConnection() const { return m_activatingConnection; } QList FakeNetwork::activeConnections() const { return m_activeConnections.keys(); } uint FakeNetwork::connectivity() const { return m_connectivity; } QList FakeNetwork::devices() const { return m_devices.keys(); } bool FakeNetwork::networkingEnabled() const { return m_networkingEnabled; } QDBusObjectPath FakeNetwork::primaryConnection() const { return m_primaryConnection; } uint FakeNetwork::state() const { return m_state; } QString FakeNetwork::version() const { return m_version; } bool FakeNetwork::wimaxEnabled() const { return m_wimaxEnabled; } void FakeNetwork::setWimaxEnabled(bool enabled) { m_wimaxEnabled = enabled; QVariantMap map; map.insert(QLatin1String("WimaxEnabled"), m_wimaxEnabled); Q_EMIT PropertiesChanged(map); } bool FakeNetwork::wimaxHardwareEnabled() const { return m_wimaxHardwareEnabled; } void FakeNetwork::setWimaxHardwareEnabled(bool enabled) { m_wimaxHardwareEnabled = enabled; QVariantMap map; map.insert(QLatin1String("WimaxHardwareEnabled"), m_wimaxHardwareEnabled); Q_EMIT PropertiesChanged(map); } bool FakeNetwork::wirelessEnabled() const { return m_wirelessEnabled; } void FakeNetwork::setWirelessEnabled(bool enabled) { m_wirelessEnabled = enabled; QVariantMap map; map.insert(QLatin1String("WirelessEnabled"), m_wirelessEnabled); Q_EMIT PropertiesChanged(map); } bool FakeNetwork::wirelessHardwareEnabled() const { return m_wirelessHardwareEnabled; } void FakeNetwork::setWirelessHardwareEnabled(bool enabled) { m_wirelessHardwareEnabled = enabled; QVariantMap map; map.insert(QLatin1String("WirelessHardwareEnabled"), m_wirelessHardwareEnabled); Q_EMIT PropertiesChanged(map); } bool FakeNetwork::wwanEnabled() const { return m_wwanEnabled; } void FakeNetwork::setWwanEnabled(bool enabled) { m_wwanEnabled = enabled; QVariantMap map; map.insert(QLatin1String("WwanEnabled"), m_wwanEnabled); Q_EMIT PropertiesChanged(map); } bool FakeNetwork::wwanHardwareEnabled() const { return m_wwanHardwareEnabled; } void FakeNetwork::addDevice(Device *device) { QString newDevicePath = QString("/org/kde/fakenetwork/Devices/") + QString::number(m_deviceCounter++); device->setDevicePath(newDevicePath); m_devices.insert(QDBusObjectPath(newDevicePath), device); QDBusConnection::sessionBus().registerObject(newDevicePath, device, QDBusConnection::ExportScriptableContents); Q_EMIT DeviceAdded(QDBusObjectPath(newDevicePath)); } void FakeNetwork::removeDevice(Device *device) { m_devices.remove(QDBusObjectPath(device->devicePath())); QDBusConnection::sessionBus().unregisterObject(device->devicePath()); Q_EMIT DeviceRemoved(QDBusObjectPath(device->devicePath())); } void FakeNetwork::registerService() { QDBusConnection::sessionBus().registerService(QLatin1String("org.kde.fakenetwork")); QDBusConnection::sessionBus().registerObject(QLatin1String("/org/kde/fakenetwork"), this, QDBusConnection::ExportScriptableContents); QDBusConnection::sessionBus().registerObject(QLatin1String("/org/kde/fakenetwork/Settings"), m_settings, QDBusConnection::ExportScriptableContents); for (auto it = m_devices.cbegin(); it != m_devices.cend(); ++it) { const QDBusObjectPath &devicePath = it.key(); QDBusConnection::sessionBus().registerObject(devicePath.path(), it.value(), QDBusConnection::ExportScriptableContents); Q_EMIT DeviceAdded(devicePath); } } void FakeNetwork::unregisterService() { for (auto it = m_devices.cbegin(); it != m_devices.cend(); ++it) { const QDBusObjectPath &devicePath = it.key(); QDBusConnection::sessionBus().unregisterObject(devicePath.path()); Q_EMIT DeviceRemoved(devicePath); } QDBusConnection::sessionBus().unregisterObject(QLatin1String("/org/kde/fakenetwork/Settings")); QDBusConnection::sessionBus().unregisterObject(QLatin1String("/org/kde/fakenetwork")); QDBusConnection::sessionBus().unregisterService(QLatin1String("org.kde.fakenetwork")); } QDBusObjectPath FakeNetwork::ActivateConnection(const QDBusObjectPath &connection, const QDBusObjectPath &device, const QDBusObjectPath &specific_object) { QString newActiveConnectionPath = QString("/org/kde/fakenetwork/ActiveConnection/") + QString::number(m_activeConnectionsCounter++); ActiveConnection *newActiveConnection = new ActiveConnection(this); newActiveConnection->addDevice(device); newActiveConnection->setActiveConnectionPath(newActiveConnectionPath); newActiveConnection->setConnection(connection); newActiveConnection->setSpecificObject(specific_object); newActiveConnection->setState(NetworkManager::ActiveConnection::Activating); m_activeConnections.insert(QDBusObjectPath(newActiveConnectionPath), newActiveConnection); QDBusConnection::sessionBus().registerObject(newActiveConnectionPath, newActiveConnection, QDBusConnection::ExportScriptableContents); m_activatingConnection = QDBusObjectPath(newActiveConnectionPath); QVariantMap map; map.insert(QLatin1String("ActiveConnections"), QVariant::fromValue>(m_activeConnections.keys())); map.insert(QLatin1String("ActivatingConnection"), QVariant::fromValue(QDBusObjectPath(newActiveConnectionPath))); Q_EMIT PropertiesChanged(map); Device *usedDevice = static_cast(QDBusConnection::sessionBus().objectRegisteredAt(device.path())); if (usedDevice) { m_activatedDevice = usedDevice->devicePath(); // Start simulation of activation usedDevice->setActiveConnection(newActiveConnectionPath); usedDevice->setState(NetworkManager::Device::Preparing); QTimer::singleShot(100, this, SLOT(updateConnectingState())); } return QDBusObjectPath(newActiveConnectionPath); } void FakeNetwork::updateConnectingState() { QVariantMap deviceMap; Device *device = m_devices.value(QDBusObjectPath(m_activatedDevice)); if (device->state() == NetworkManager::Device::Preparing) { device->setState(NetworkManager::Device::ConfiguringHardware); } else if (device->state() == NetworkManager::Device::ConfiguringHardware) { device->setState(NetworkManager::Device::NeedAuth); } else if (device->state() == NetworkManager::Device::NeedAuth) { device->setState(NetworkManager::Device::ConfiguringIp); } else if (device->state() == NetworkManager::Device::ConfiguringIp) { device->setState(NetworkManager::Device::CheckingIp); } else if (device->state() == NetworkManager::Device::CheckingIp) { device->setState(NetworkManager::Device::Activated); ActiveConnection *activeConnection = static_cast(QDBusConnection::sessionBus().objectRegisteredAt(device->activeConnection().path())); if (activeConnection) { QVariantMap activeConnectionMap; activeConnectionMap.insert(QLatin1String("State"), NetworkManager::ActiveConnection::Activated); activeConnection->setState(NetworkManager::ActiveConnection::Activated); QDBusMessage message = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("PropertiesChanged")); message << activeConnectionMap; QDBusConnection::sessionBus().send(message); QDBusMessage message2 = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("StateChanged")); message2 << (uint)2 << (uint)1; // NM_ACTIVE_CONNECTION_STATE_ACTIVATED << NM_ACTIVE_CONNECTION_STATE_REASON_NONE QDBusConnection::sessionBus().send(message2); } // TODO: set dhcp4Config, dhcp6Config, ip4Config, ip6Config // IP Interface is usually same as interface device->setIpInterface(device->interface()); // Set some IP address device->setIpv4Address(1763189258); deviceMap.insert(QLatin1String("IpInterface"), device->ipInterface()); deviceMap.insert(QLatin1String("Ip4Address"), device->ip4Address()); deviceMap.insert(QLatin1String("ActiveConnection"), m_activatingConnection.path()); // Update FakeNetwork state, connectivity, primary connection m_connectivity = NetworkManager::Connectivity::Full; m_primaryConnection = m_activatingConnection; m_activatingConnection = QDBusObjectPath("/"); m_state = 70; QVariantMap networkMap; networkMap.insert(QLatin1String("ActivatingConnection"), QVariant::fromValue(m_activatingConnection)); networkMap.insert(QLatin1String("Connectivity"), NetworkManager::Connectivity::Full); networkMap.insert(QLatin1String("PrimaryConnection"), QVariant::fromValue(m_primaryConnection)); networkMap.insert(QLatin1String("State"), m_state); QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/org/kde/fakenetwork"), QLatin1String("org.kde.fakenetwork"), QLatin1String("PropertiesChanged")); message << networkMap; QDBusConnection::sessionBus().send(message); Q_EMIT StateChanged(m_state); } deviceMap.insert(QLatin1String("State"), device->state()); QDBusMessage message = QDBusMessage::createSignal(device->devicePath(), device->deviceInterface(), QLatin1String("PropertiesChanged")); message << deviceMap; QDBusConnection::sessionBus().send(message); if (device->state() != NetworkManager::Device::Activated) { QTimer::singleShot(100, this, SLOT(updateConnectingState())); } } uint FakeNetwork::CheckConnectivity() const { return m_connectivity; } void FakeNetwork::DeactivateConnection(const QDBusObjectPath &active_connection) { ActiveConnection *activeConnection = m_activeConnections.value(active_connection); if (activeConnection) { activeConnection->setState(NetworkManager::ActiveConnection::Deactivating); QVariantMap activeConnectionMap; activeConnectionMap.insert(QLatin1String("State"), NetworkManager::ActiveConnection::Deactivating); activeConnection->setState(NetworkManager::ActiveConnection::Activated); QDBusMessage message = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("PropertiesChanged")); message << activeConnectionMap; QDBusConnection::sessionBus().send(message); QDBusMessage message2 = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("StateChanged")); message2 << (uint)4 << (uint)2; // NM_ACTIVE_CONNECTION_STATE_DEACTIVATED << NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED QDBusConnection::sessionBus().send(message2); Device *device = m_devices.value(activeConnection->devices().first()); if (device) { m_deactivatedDevice = device->devicePath(); device->setState(NetworkManager::Device::Deactivating); QTimer::singleShot(100, this, SLOT(updateDeactivatingState())); } // Update FakeNetwork state, connectivity, primary connection m_connectivity = NetworkManager::Connectivity::NoConnectivity; m_primaryConnection = QDBusObjectPath("/"); m_state = 20; QVariantMap networkMap; networkMap.insert(QLatin1String("Connectivity"), m_connectivity); networkMap.insert(QLatin1String("PrimaryConnection"), QVariant::fromValue(m_primaryConnection)); networkMap.insert(QLatin1String("State"), m_state); message = QDBusMessage::createSignal(QLatin1String("/org/kde/fakenetwork"), QLatin1String("org.kde.fakenetwork"), QLatin1String("PropertiesChanged")); message << networkMap; QDBusConnection::sessionBus().send(message); Q_EMIT StateChanged(m_state); } } void FakeNetwork::updateDeactivatingState() { QVariantMap deviceMap; Device *device = m_devices.value(QDBusObjectPath(m_deactivatedDevice)); ActiveConnection *activeConnection = static_cast(QDBusConnection::sessionBus().objectRegisteredAt(device->activeConnection().path())); if (activeConnection) { QVariantMap activeConnectionMap; activeConnectionMap.insert(QLatin1String("State"), NetworkManager::ActiveConnection::Deactivated); activeConnection->setState(NetworkManager::ActiveConnection::Activated); QDBusMessage message = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("PropertiesChanged")); message << activeConnectionMap; QDBusConnection::sessionBus().send(message); QDBusMessage message2 = QDBusMessage::createSignal(activeConnection->activeConnectionPath(), QLatin1String("org.kde.fakenetwork.Connection.Active"), QLatin1String("StateChanged")); message2 << (uint)3 << (uint)2; // NM_ACTIVE_CONNECTION_STATE_DEACTIVATING << NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED QDBusConnection::sessionBus().send(message2); removeActiveConnection(QDBusObjectPath(activeConnection->activeConnectionPath())); } device->setActiveConnection(QLatin1String("/")); device->setState(NetworkManager::Device::Disconnected); // TODO: set dhcp4Config, dhcp6Config, ip4Config, ip6Config // IP Interface is usually same as interface device->setIpInterface(""); // Set some IP address device->setIpv4Address(0); deviceMap.insert(QLatin1String("ActiveConnection"), device->activeConnection().path()); deviceMap.insert(QLatin1String("IpInterface"), device->ipInterface()); deviceMap.insert(QLatin1String("Ip4Address"), device->ip4Address()); deviceMap.insert(QLatin1String("State"), device->state()); QDBusMessage message = QDBusMessage::createSignal(device->devicePath(), device->deviceInterface(), QLatin1String("PropertiesChanged")); message << deviceMap; QDBusConnection::sessionBus().send(message); } QDBusObjectPath FakeNetwork::GetDeviceByIpIface(const QString &iface) { Q_UNUSED(iface) // TODO return QDBusObjectPath(); } QList FakeNetwork::GetDevices() const { return m_devices.keys(); } void FakeNetwork::onConnectionAdded(const QDBusObjectPath &connection) { Connection *newConnection = static_cast(QDBusConnection::sessionBus().objectRegisteredAt(connection.path())); if (newConnection) { NMVariantMapMap settings = newConnection->GetSettings(); NetworkManager::ConnectionSettings::ConnectionType type = NetworkManager::ConnectionSettings::typeFromString(settings.value(QLatin1String("connection")).value(QLatin1String("type")).toString()); if (!m_devices.isEmpty()) { Device *selectedDevice = nullptr; for (Device *device : std::as_const(m_devices)) { if (type == NetworkManager::ConnectionSettings::Wired && device->deviceType() == NetworkManager::Device::Ethernet) { selectedDevice = device; device->addAvailableConnection(connection); break; } else if (type == NetworkManager::ConnectionSettings::Wireless && device->deviceType() == NetworkManager::Device::Wifi) { selectedDevice = device; // TODO break; } } if (selectedDevice) { QVariantMap map; map.insert(QLatin1String("AvailableConnections"), QVariant::fromValue>(selectedDevice->availableConnections())); QDBusMessage message = QDBusMessage::createSignal(selectedDevice->devicePath(), selectedDevice->deviceInterface(), QLatin1String("PropertiesChanged")); message << map; QDBusConnection::sessionBus().send(message); } } } } void FakeNetwork::onConnectionRemoved(const QDBusObjectPath &connection) { for (Device *device : std::as_const(m_devices)) { if (device && device->availableConnections().contains(connection)) { device->removeAvailableConnection(connection); QVariantMap map; map.insert(QLatin1String("AvailableConnections"), QVariant::fromValue>(device->availableConnections())); QDBusMessage message = QDBusMessage::createSignal(device->devicePath(), device->deviceInterface(), QLatin1String("PropertiesChanged")); message << map; QDBusConnection::sessionBus().send(message); } } } void FakeNetwork::removeActiveConnection(const QDBusObjectPath &activeConnection) { delete m_activeConnections.value(activeConnection); m_activeConnections.remove(activeConnection); QDBusConnection::sessionBus().unregisterObject(activeConnection.path()); QVariantMap map; map.insert(QLatin1String("ActiveConnections"), QVariant::fromValue>(m_activeConnections.keys())); Q_EMIT PropertiesChanged(map); } #include "moc_fakenetwork.cpp"