From 2277bfa0d62d052c5a1fa42425ed6ed23d1cc96d Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 28 Nov 2012 13:05:30 -0600 Subject: [PATCH 1/2] Fix a number of issues with the network-manager backend, including event loop recursion --- .../network-manager/network-manager.cpp | 143 +++++++++++++++--- .../network-manager/network-manager_p.h | 2 + tdecore/tdehardwaredevices.cpp | 12 +- tdecore/tdenetworkconnections.cpp | 4 +- tdecore/tdenetworkconnections.h | 6 +- 5 files changed, 136 insertions(+), 31 deletions(-) diff --git a/tdecore/networkbackends/network-manager/network-manager.cpp b/tdecore/networkbackends/network-manager/network-manager.cpp index 08bd57d6f..05aa97618 100644 --- a/tdecore/networkbackends/network-manager/network-manager.cpp +++ b/tdecore/networkbackends/network-manager/network-manager.cpp @@ -39,9 +39,12 @@ #define UPDATE_STRING_SETTING_IF_VALID(string, key, settingsMap) if (!string.isNull()) settingsMap[key] = convertDBUSDataToVariantData(TQT_DBusData::fromString(string)); \ else settingsMap.remove(key); -//#define NM_ASYNC_TIMEOUT_MS 1000 +#define NM_ASYNC_TIMEOUT_MS 1000 // Give the user 5 minutes to authenticate to DBUS before timing out -#define NM_ASYNC_TIMEOUT_MS (5*60*1000) +#define NM_ASYNC_SECRETS_INTERACTION_TIMEOUT_MS (5*60*1000) + +// #define WAIT_FOR_OPERATION_BEFORE_RETURNING 1 +#define USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS 1 TQ_UINT32 reverseIPV4ByteOrder(TQ_UINT32 address) { TQ_UINT32 ret; @@ -1341,6 +1344,17 @@ void TDENetworkConnectionManager_BackendNM_DBusSignalReceiver::dbusSignal(const } } } + else if (interface == NM_DBUS_DEVICE_SERVICE) { + if (path == m_parent->m_dbusDeviceString) { + if (member == "StateChanged") { + // Demarshal data + TQ_UINT32 new_state = message[0].toUInt32(); + TQ_UINT32 old_state = message[1].toUInt32(); + TQ_UINT32 reason = message[2].toUInt32(); + m_parent->internalProcessDeviceStateChanged(new_state, old_state, reason); + } + } + } } } @@ -1355,12 +1369,12 @@ TDENetworkConnectionManager_BackendNM::TDENetworkConnectionManager_BackendNM(TQS d->m_vpnProxy = new DBus::VPNPluginProxy(NM_VPN_DBUS_PLUGIN_SERVICE, NM_VPN_DBUS_PLUGIN_PATH); d->m_vpnProxy->setConnection(TQT_DBusConnection::systemBus()); - TQString dbusDeviceString = deviceInterfaceString(macAddress); - if (dbusDeviceString != "") { - d->m_networkDeviceProxy = new DBus::DeviceProxy(NM_DBUS_SERVICE, dbusDeviceString); + d->m_dbusDeviceString = deviceInterfaceString(macAddress); + if (d->m_dbusDeviceString != "") { + d->m_networkDeviceProxy = new DBus::DeviceProxy(NM_DBUS_SERVICE, d->m_dbusDeviceString); d->m_networkDeviceProxy->setConnection(TQT_DBusConnection::systemBus()); if (deviceType() == TDENetworkDeviceType::WiFi) { - d->m_wiFiDeviceProxy = new DBus::WiFiDeviceProxy(NM_DBUS_SERVICE, dbusDeviceString); + d->m_wiFiDeviceProxy = new DBus::WiFiDeviceProxy(NM_DBUS_SERVICE, d->m_dbusDeviceString); d->m_wiFiDeviceProxy->setConnection(TQT_DBusConnection::systemBus()); } } @@ -1428,7 +1442,16 @@ void TDENetworkConnectionManager_BackendNMPrivate::internalProcessVPNFailure(TQ_ void TDENetworkConnectionManager_BackendNMPrivate::internalProcessDeviceStateChanged(TQ_UINT32 newState, TQ_UINT32 oldState, TQ_UINT32 reason) { Q_UNUSED(oldState) - Q_UNUSED(reason) + + if (m_prevDeviceState == newState) return; + m_prevDeviceState = newState; + + if (newState == NM_DEVICE_STATE_FAILED) { + // FIXME + // This should provide a plain-text interpretation of the NetworkManager-specific error code + m_parent->internalNetworkDeviceEvent(TDENetworkDeviceEventType::Failure, TQString("Connection attempt failed!
NetworkManager returned error %1.").arg(reason)); + } + m_parent->internalNetworkDeviceStateChanged(nmDeviceStateToTDEDeviceState(newState), m_parent->m_macAddress); } @@ -1475,7 +1498,7 @@ void TDENetworkConnectionManager_BackendNMPrivate::internalProcessWiFiProperties } } else if (props.contains("Bitrate")) { - m_parent->internalNetworkDeviceEvent(TDENetworkDeviceEventType::BitRateChanged); + m_parent->internalNetworkDeviceEvent(TDENetworkDeviceEventType::BitRateChanged, TQString::null); } } } @@ -1499,8 +1522,8 @@ TDENetworkDeviceType::TDENetworkDeviceType TDENetworkConnectionManager_BackendNM else { // Query NM for the device type TQT_DBusError error; - TQString dbusDeviceString = deviceInterfaceString(m_macAddress); - DBus::DeviceProxy genericDevice(NM_DBUS_SERVICE, dbusDeviceString); + d->m_dbusDeviceString = deviceInterfaceString(m_macAddress); + DBus::DeviceProxy genericDevice(NM_DBUS_SERVICE, d->m_dbusDeviceString); genericDevice.setConnection(TQT_DBusConnection::systemBus()); TDENetworkDeviceType::TDENetworkDeviceType ret = nmDeviceTypeToTDEDeviceType(genericDevice.getDeviceType(error)); if (error.isValid()) { @@ -1519,6 +1542,18 @@ TDENetworkConnectionType::TDENetworkConnectionType TDENetworkConnectionManager_B TQ_UINT32 ret; TQT_DBusError error; +#ifndef USE_ASYNC_DBUS_CALLS + // Obtain connection settings from the path specified + DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, dbusPath); + connectionSettings.setConnection(TQT_DBusConnection::systemBus()); + TQT_DBusTQStringDataMap connectionSettingsMap; + ret = connectionSettings.GetSettings(connectionSettingsMap, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + if (ret) { +#else // USE_ASYNC_DBUS_CALLS // Obtain connection settings from the path specified DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, dbusPath); connectionSettings.setConnection(TQT_DBusConnection::systemBus()); @@ -1544,6 +1579,7 @@ TDENetworkConnectionType::TDENetworkConnectionType TDENetworkConnectionManager_B TQT_DBusTQStringDataMap connectionSettingsMap = d->nmConnectionSettingsAsyncSettingsResponse[asyncCallID]; d->nmConnectionSettingsAsyncCallWaiting.remove(asyncCallID); d->nmConnectionSettingsAsyncSettingsResponse.remove(asyncCallID); +#endif // USE_ASYNC_DBUS_CALLS // Parse settings to find connection type TQT_DBusTQStringDataMap::const_iterator it2; @@ -1766,6 +1802,18 @@ void TDENetworkConnectionManager_BackendNM::loadConnectionInformation() { printf("[network-manager comm debug] %s\n\r", (*it).data()); fflush(stdout); #endif // DEBUG_NETWORK_MANAGER_COMMUNICATIONS +#ifndef USE_ASYNC_DBUS_CALLS + // Obtain connection settings from the path specified + DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, (*it)); + connectionSettings.setConnection(TQT_DBusConnection::systemBus()); + TQT_DBusTQStringDataMap connectionSettingsMap; + ret = connectionSettings.GetSettings(connectionSettingsMap, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + if (ret) { +#else // USE_ASYNC_DBUS_CALLS // Obtain connection settings from the path specified DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, (*it)); connectionSettings.setConnection(TQT_DBusConnection::systemBus()); @@ -1791,6 +1839,7 @@ void TDENetworkConnectionManager_BackendNM::loadConnectionInformation() { TQT_DBusTQStringDataMap connectionSettingsMap = d->nmConnectionSettingsAsyncSettingsResponse[asyncCallID]; d->nmConnectionSettingsAsyncCallWaiting.remove(asyncCallID); d->nmConnectionSettingsAsyncSettingsResponse.remove(asyncCallID); +#endif // USE_ASYNC_DBUS_CALLS #ifdef DEBUG_NETWORK_MANAGER_COMMUNICATIONS printf("[network-manager comm debug] received DBUS object structure map follows:\n\r"); fflush(stdout); @@ -2886,6 +2935,17 @@ bool TDENetworkConnectionManager_BackendNM::loadConnectionSecretsForGroup(TQStri TQT_DBusTQStringDataMap connectionSecretsMap(TQT_DBusData::String); ret = d->m_networkManagerSettings->GetConnectionByUuid(uuid, existingConnection, error); if (ret) { +#ifndef USE_ASYNC_DBUS_CALLS + // Obtain connection settings from the path specified + DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, existingConnection); + connectionSettings.setConnection(TQT_DBusConnection::systemBus()); + ret = connectionSettings.GetSecrets(group, connectionSecretsMap, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + if (ret) { +#else // USE_ASYNC_DBUS_CALLS // Obtain connection secrets from the path specified DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, existingConnection); connectionSettings.setConnection(TQT_DBusConnection::systemBus()); @@ -2900,7 +2960,7 @@ bool TDENetworkConnectionManager_BackendNM::loadConnectionSecretsForGroup(TQStri // Wait for the asynchronous call to return... d->nmConnectionSettingsAsyncCallWaiting[asyncCallID] = true; TQTimer nmCallTimeoutTimer; - nmCallTimeoutTimer.start(NM_ASYNC_TIMEOUT_MS, TRUE); + nmCallTimeoutTimer.start(NM_ASYNC_SECRETS_INTERACTION_TIMEOUT_MS, TRUE); while (d->nmConnectionSettingsAsyncCallWaiting[asyncCallID]) { tqApp->processEvents(); if (!nmCallTimeoutTimer.isActive()) { @@ -2911,6 +2971,7 @@ bool TDENetworkConnectionManager_BackendNM::loadConnectionSecretsForGroup(TQStri connectionSecretsMap = d->nmConnectionSettingsAsyncSettingsResponse[asyncCallID]; d->nmConnectionSettingsAsyncCallWaiting.remove(asyncCallID); d->nmConnectionSettingsAsyncSettingsResponse.remove(asyncCallID); +#endif // USE_ASYNC_DBUS_CALLS #ifdef DEBUG_NETWORK_MANAGER_COMMUNICATIONS printf("[network-manager comm debug] received DBUS object structure map follows:\n\r"); fflush(stdout); @@ -3082,6 +3143,18 @@ bool TDENetworkConnectionManager_BackendNM::saveConnection(TDENetworkConnection* existing = false; ret = d->m_networkManagerSettings->GetConnectionByUuid(connection->UUID, existingConnection, error); if (ret) { +#ifndef USE_ASYNC_DBUS_CALLS + // Obtain connection settings from the path specified + DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, existingConnection); + connectionSettings.setConnection(TQT_DBusConnection::systemBus()); + connectionSettingsMap; + ret = connectionSettings.GetSettings(connectionSettingsMap, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + if (ret) { +#else // USE_ASYNC_DBUS_CALLS // Obtain connection settings from the path specified DBus::ConnectionSettingsInterface connectionSettings(NM_DBUS_SERVICE, existingConnection); connectionSettings.setConnection(TQT_DBusConnection::systemBus()); @@ -3105,9 +3178,10 @@ bool TDENetworkConnectionManager_BackendNM::saveConnection(TDENetworkConnection* } } connectionSettingsMap = d->nmConnectionSettingsAsyncSettingsResponse[asyncCallID]; - existing = true; d->nmConnectionSettingsAsyncCallWaiting.remove(asyncCallID); d->nmConnectionSettingsAsyncSettingsResponse.remove(asyncCallID); +#endif // USE_ASYNC_DBUS_CALLS + existing = true; } } @@ -4571,20 +4645,29 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag if ((d->m_networkManagerSettings) && (d->m_networkManagerProxy)) { ret = d->m_networkManagerSettings->GetConnectionByUuid(uuid, existingConnection, error); if (ret) { - TQString dbusDeviceString; if (m_macAddress == "") { - dbusDeviceString = "/"; + d->m_dbusDeviceString = "/"; } else { - dbusDeviceString = deviceInterfaceString(m_macAddress); + d->m_dbusDeviceString = deviceInterfaceString(m_macAddress); } +#ifndef USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS + TQT_DBusObjectPath active_connection; + ret = d->m_networkManagerProxy->ActivateConnection(existingConnection, TQT_DBusObjectPath(d->m_dbusDeviceString.ascii()), TQT_DBusObjectPath("/"), active_connection, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + return checkConnectionStatus(uuid); +#else // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS connect(d->m_networkManagerProxy, SIGNAL(ActivateConnectionAsyncReply(int, const TQT_DBusObjectPath&)), d, SLOT(processAddConnectionAsyncReply(int, const TQT_DBusObjectPath&))); int asyncCallID; - ret = d->m_networkManagerProxy->ActivateConnectionAsync(asyncCallID, existingConnection, TQT_DBusObjectPath(dbusDeviceString.ascii()), TQT_DBusObjectPath("/"), error); + ret = d->m_networkManagerProxy->ActivateConnectionAsync(asyncCallID, existingConnection, TQT_DBusObjectPath(d->m_dbusDeviceString.ascii()), TQT_DBusObjectPath("/"), error); if (ret && error.isValid()) { ret = 0; PRINT_ERROR(error.name()) } +#ifdef WAIT_FOR_OPERATION_BEFORE_RETURNING if (ret) { // Wait for the asynchronous call to return... d->nmConnectionSettingsAsyncCallWaiting[asyncCallID] = true; @@ -4606,6 +4689,10 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag PRINT_ERROR(error.name()) return checkConnectionStatus(uuid); } +#else + return checkConnectionStatus(uuid); +#endif +#endif // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS } else { PRINT_WARNING(TQString("connection for provided uuid '%1' was not found").arg(uuid)); @@ -4740,13 +4827,20 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag if ((d->m_networkManagerSettings) && (d->m_networkManagerProxy)) { existingConnection = getActiveConnectionPath(uuid); if (existingConnection.isValid()) { - TQString dbusDeviceString; if (m_macAddress == "") { - dbusDeviceString = "/"; + d->m_dbusDeviceString = "/"; } else { - dbusDeviceString = deviceInterfaceString(m_macAddress); + d->m_dbusDeviceString = deviceInterfaceString(m_macAddress); } +#ifndef USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS + ret = d->m_networkManagerProxy->DeactivateConnection(existingConnection, error); + if (ret && error.isValid()) { + ret = 0; + PRINT_ERROR(error.name()) + } + return checkConnectionStatus(uuid); +#else // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS connect(d->m_networkManagerProxy, SIGNAL(DeactivateConnectionAsyncReply(int)), d, SLOT(processConnectionSettingsUpdateAsyncReply(int))); int asyncCallID; ret = d->m_networkManagerProxy->DeactivateConnectionAsync(asyncCallID, existingConnection, error); @@ -4754,6 +4848,7 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag ret = 0; PRINT_ERROR(error.name()) } +#ifdef WAIT_FOR_OPERATION_BEFORE_RETURNING if (ret) { // Wait for the asynchronous call to return... d->nmConnectionSettingsAsyncCallWaiting[asyncCallID] = true; @@ -4774,6 +4869,10 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag PRINT_ERROR(error.name()) return checkConnectionStatus(uuid); } +#else + return checkConnectionStatus(uuid); +#endif +#endif // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS } else { PRINT_WARNING(TQString("connection for provided uuid '%1' was not found").arg(uuid)); @@ -5014,11 +5113,11 @@ TDENetworkHWNeighborList* TDENetworkConnectionManager_BackendNM::siteSurvey() { bool ret; TDENetworkDeviceType::TDENetworkDeviceType myDeviceType = deviceType(); - TQString dbusDeviceString = deviceInterfaceString(m_macAddress); + d->m_dbusDeviceString = deviceInterfaceString(m_macAddress); clearTDENetworkHWNeighborList(); if (myDeviceType == TDENetworkDeviceType::WiFi) { - DBus::WiFiDeviceProxy wiFiDevice(NM_DBUS_SERVICE, dbusDeviceString); + DBus::WiFiDeviceProxy wiFiDevice(NM_DBUS_SERVICE, d->m_dbusDeviceString); wiFiDevice.setConnection(TQT_DBusConnection::systemBus()); // FIXME // Should call wiFiDevice.RequestScanAsync first to rescan all access points @@ -5176,7 +5275,7 @@ TQStringList TDENetworkConnectionManager_BackendNM::defaultNetworkDevices() { } } -TDENetworkConnectionManager_BackendNMPrivate::TDENetworkConnectionManager_BackendNMPrivate(TDENetworkConnectionManager_BackendNM* parent) : m_networkManagerProxy(NULL), m_networkManagerSettings(NULL), m_networkDeviceProxy(NULL), m_wiFiDeviceProxy(NULL), m_vpnProxy(NULL), nonReentrantCallActive(false), m_parent(parent) { +TDENetworkConnectionManager_BackendNMPrivate::TDENetworkConnectionManager_BackendNMPrivate(TDENetworkConnectionManager_BackendNM* parent) : m_networkManagerProxy(NULL), m_networkManagerSettings(NULL), m_networkDeviceProxy(NULL), m_wiFiDeviceProxy(NULL), m_vpnProxy(NULL), nonReentrantCallActive(false), m_parent(parent), m_prevDeviceState(-1) { // Set up global signal handler m_dbusSignalConnection = new TQT_DBusConnection(TQT_DBusConnection::systemBus()); m_dbusSignalReceiver = new TDENetworkConnectionManager_BackendNM_DBusSignalReceiver(this); diff --git a/tdecore/networkbackends/network-manager/network-manager_p.h b/tdecore/networkbackends/network-manager/network-manager_p.h index b97499436..474f628bb 100644 --- a/tdecore/networkbackends/network-manager/network-manager_p.h +++ b/tdecore/networkbackends/network-manager/network-manager_p.h @@ -101,6 +101,7 @@ class TDENetworkConnectionManager_BackendNMPrivate : public TQObject NMAsyncSettingsResponseMap nmConnectionSettingsAsyncSettingsResponse; NMAddConnectionAsyncResponseMap nmAddConnectionAsyncResponse; bool nonReentrantCallActive; + TQString m_dbusDeviceString; public slots: void processConnectionSettingsAsyncReply(int, const TQT_DBusDataMap&); @@ -122,6 +123,7 @@ class TDENetworkConnectionManager_BackendNMPrivate : public TQObject TQMap m_accessPointProxyList; TQT_DBusConnection *m_dbusSignalConnection; TDENetworkConnectionManager_BackendNM_DBusSignalReceiver *m_dbusSignalReceiver; + int m_prevDeviceState; friend class TDENetworkConnectionManager_BackendNM_DBusSignalReceiver; }; diff --git a/tdecore/tdehardwaredevices.cpp b/tdecore/tdehardwaredevices.cpp index d4a10c340..e143e00d5 100644 --- a/tdecore/tdehardwaredevices.cpp +++ b/tdecore/tdehardwaredevices.cpp @@ -2724,7 +2724,7 @@ TDEGenericDeviceType::TDEGenericDeviceType readGenericDeviceTypeFromString(TQStr else if (query == "ThermalControl") { ret = TDEGenericDeviceType::ThermalControl; } - else if (query == "BlueTooth") { + else if (query == "Bluetooth") { ret = TDEGenericDeviceType::BlueTooth; } else if (query == "Bridge") { @@ -3215,6 +3215,11 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD )) { if (!device) device = new TDEStorageDevice(TDEGenericDeviceType::Disk); } + else if (devicetype == "host") { + if (devicesubsystem == "bluetooth") { + if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::BlueTooth); + } + } else if (devicetype.isNull()) { if (devicesubsystem == "acpi") { // If the ACPI device exposes a system path ending in /PNPxxxx:yy, the device type can be precisely determined @@ -3265,9 +3270,6 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::TextIO); } } - else if (devicesubsystem == "bluetooth") { - if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::BlueTooth); - } else if (devicesubsystem == "usb-serial") { if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Serial); } @@ -5288,7 +5290,7 @@ TQString TDEHardwareDevices::getFriendlyDeviceTypeStringFromType(TDEGenericDevic ret = i18n("Thermal Control"); } else if (query == TDEGenericDeviceType::BlueTooth) { - ret = i18n("BlueTooth"); + ret = i18n("Bluetooth"); } else if (query == TDEGenericDeviceType::Bridge) { ret = i18n("Bridge"); diff --git a/tdecore/tdenetworkconnections.cpp b/tdecore/tdenetworkconnections.cpp index 5f1f85414..82df5c8cc 100644 --- a/tdecore/tdenetworkconnections.cpp +++ b/tdecore/tdenetworkconnections.cpp @@ -844,8 +844,8 @@ void TDENetworkConnectionManager::internalAccessPointStatusChanged(TDEMACAddress emit(accessPointStatusChanged(BSSID, event)); } -void TDENetworkConnectionManager::internalNetworkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event) { - emit(networkDeviceEvent(event)); +void TDENetworkConnectionManager::internalNetworkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event, TQString message) { + emit(networkDeviceEvent(event, message)); } void TDENetworkConnectionManager::internalVpnEvent(TDENetworkVPNEventType::TDENetworkVPNEventType event, TQString message) { diff --git a/tdecore/tdenetworkconnections.h b/tdecore/tdenetworkconnections.h index 532618ab0..b1e02ce9d 100644 --- a/tdecore/tdenetworkconnections.h +++ b/tdecore/tdenetworkconnections.h @@ -213,6 +213,7 @@ namespace TDENetworkVPNEventType { namespace TDENetworkDeviceEventType { enum TDENetworkDeviceEventType { BitRateChanged, + Failure, Other, Last = Other }; @@ -1186,8 +1187,9 @@ class TDECORE_EXPORT TDENetworkConnectionManager : public TQObject /** * Emitted whenever a network device event occurs * The event type that caused the signal is available in @param event + * @param message contains additional information if available */ - void networkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event); + void networkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event, TQString message); /** * Emitted whenever a VPN-related event occurs @@ -1295,7 +1297,7 @@ class TDECORE_EXPORT TDENetworkConnectionManager : public TQObject * @internal This method must be called by the network backend whenever a device event occurs * It emits the appropriate signals to notify client applications of the network device event */ - void internalNetworkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event); + void internalNetworkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event, TQString message); /** * @internal This method must be called by the network backend whenever a VPN event occurs From 9e5d27963b3bf1b0a2d76ef165616fdfaf58b825 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 29 Nov 2012 20:07:31 -0600 Subject: [PATCH 2/2] Fix various performance and stability issues in the network-manager backend --- .../network-manager/network-manager.cpp | 31 ++++++- .../network-manager/network-manager.h | 1 + tdecore/tdenetworkconnections.cpp | 91 +++++++++++++++++-- tdecore/tdenetworkconnections.h | 40 +++++++- 4 files changed, 153 insertions(+), 10 deletions(-) diff --git a/tdecore/networkbackends/network-manager/network-manager.cpp b/tdecore/networkbackends/network-manager/network-manager.cpp index 05aa97618..e0b11481c 100644 --- a/tdecore/networkbackends/network-manager/network-manager.cpp +++ b/tdecore/networkbackends/network-manager/network-manager.cpp @@ -1332,7 +1332,7 @@ void TDENetworkConnectionManager_BackendNM_DBusSignalReceiver::dbusSignal(const TQString member = message.member(); TQString path = message.path(); -// printf("[DEBUG] In dbusSignal: sender: %s, member: %s, interface: %s, path: %s\n\r", sender.ascii(), member.ascii(), interface.ascii(), path.ascii()); fflush(stdout); +// printf("[DEBUG] In dbusSignal: sender: %s, member: %s, interface: %s, path: %s, parent path: %s\n\r", sender.ascii(), member.ascii(), interface.ascii(), path.ascii(), m_parent->m_dbusDeviceString.ascii()); fflush(stdout); if (interface == NM_VPN_DBUS_CONNECTION_SERVICE) { if (member == "VpnStateChanged") { @@ -1711,6 +1711,31 @@ TDENetworkDeviceInformation TDENetworkConnectionManager_BackendNM::deviceInforma return ret; } +TDENetworkDeviceInformation TDENetworkConnectionManager_BackendNM::deviceStatus() { + TQT_DBusError error; + TDENetworkDeviceInformation ret; + + if (d->m_networkDeviceProxy) { + ret.statusFlags = nmDeviceStateToTDEDeviceState(d->m_networkDeviceProxy->getState(error)); + ret.UUID = d->m_networkDeviceProxy->getUdi(error); + + // Get active connection UUID + TQT_DBusObjectPath connectionPath = d->m_networkDeviceProxy->getActiveConnection(error); + if (!error.isValid()) { + DBus::ActiveConnectionProxy activeConnection(NM_DBUS_SERVICE, connectionPath); + activeConnection.setConnection(TQT_DBusConnection::systemBus()); + ret.activeConnectionUUID = activeConnection.getUuid(error); + if (!error.isValid()) { + ret.activeConnectionUUID = TQString::null; + } + } + + ret.valid = true; + } + + return ret; +} + void TDENetworkConnectionManager_BackendNMPrivate::processConnectionSettingsAsyncReply(int asyncCallId, const TQT_DBusDataMap& settings) { nmConnectionSettingsAsyncCallWaiting[asyncCallId] = false; nmConnectionSettingsAsyncSettingsResponse[asyncCallId] = settings; @@ -4660,7 +4685,9 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag } return checkConnectionStatus(uuid); #else // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS +#ifdef WAIT_FOR_OPERATION_BEFORE_RETURNING connect(d->m_networkManagerProxy, SIGNAL(ActivateConnectionAsyncReply(int, const TQT_DBusObjectPath&)), d, SLOT(processAddConnectionAsyncReply(int, const TQT_DBusObjectPath&))); +#endif // WAIT_FOR_OPERATION_BEFORE_RETURNING int asyncCallID; ret = d->m_networkManagerProxy->ActivateConnectionAsync(asyncCallID, existingConnection, TQT_DBusObjectPath(d->m_dbusDeviceString.ascii()), TQT_DBusObjectPath("/"), error); if (ret && error.isValid()) { @@ -4841,7 +4868,9 @@ TDENetworkConnectionStatus::TDENetworkConnectionStatus TDENetworkConnectionManag } return checkConnectionStatus(uuid); #else // USE_ASYNC_DBUS_CONNECTION_COMMAND_CALLS +#ifdef WAIT_FOR_OPERATION_BEFORE_RETURNING connect(d->m_networkManagerProxy, SIGNAL(DeactivateConnectionAsyncReply(int)), d, SLOT(processConnectionSettingsUpdateAsyncReply(int))); +#endif // WAIT_FOR_OPERATION_BEFORE_RETURNING int asyncCallID; ret = d->m_networkManagerProxy->DeactivateConnectionAsync(asyncCallID, existingConnection, error); if (ret && error.isValid()) { diff --git a/tdecore/networkbackends/network-manager/network-manager.h b/tdecore/networkbackends/network-manager/network-manager.h index f06643b6e..2063a036b 100644 --- a/tdecore/networkbackends/network-manager/network-manager.h +++ b/tdecore/networkbackends/network-manager/network-manager.h @@ -159,6 +159,7 @@ class TDECORE_EXPORT TDENetworkConnectionManager_BackendNM : public TDENetworkCo virtual TDENetworkDeviceType::TDENetworkDeviceType deviceType(); virtual TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags backendStatus(); virtual TDENetworkDeviceInformation deviceInformation(); + virtual TDENetworkDeviceInformation deviceStatus(); virtual void loadConnectionInformation(); virtual void loadConnectionAllowedValues(TDENetworkConnection* connection); diff --git a/tdecore/tdenetworkconnections.cpp b/tdecore/tdenetworkconnections.cpp index 82df5c8cc..80f34b765 100644 --- a/tdecore/tdenetworkconnections.cpp +++ b/tdecore/tdenetworkconnections.cpp @@ -21,8 +21,12 @@ #include "config.h" +#include + #include +// #define DEBUG_SIGNAL_QUEUE 1 + #ifdef WITH_NETWORK_MANAGER_BACKEND #include "networkbackends/network-manager/network-manager.h" #endif // WITH_NETWORK_MANAGER_BACKEND @@ -684,11 +688,14 @@ TDEWiFiConnection::~TDEWiFiConnection() { /*================================================================================================*/ TDENetworkConnectionManager::TDENetworkConnectionManager(TQString macAddress) : TQObject(), m_connectionList(NULL), m_hwNeighborList(NULL), m_macAddress(macAddress), m_prevConnectionStatus(TDENetworkGlobalManagerFlags::Unknown) { - // + m_emissionTimer = new TQTimer(); + connect(m_emissionTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(emitQueuedSignals())); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); } TDENetworkConnectionManager::~TDENetworkConnectionManager() { - // + m_emissionTimer->stop(); + delete m_emissionTimer; } TQString TDENetworkConnectionManager::deviceMACAddress() { @@ -828,7 +835,13 @@ void TDENetworkConnectionManager::clearTDENetworkHWNeighborList() { } void TDENetworkConnectionManager::internalNetworkConnectionStateChanged(TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags newState) { - emit(networkConnectionStateChanged(m_prevConnectionStatus, newState)); + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 0; + queuedEvent.newState = newState; + queuedEvent.previousState = m_prevConnectionStatus; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); + m_prevConnectionStatus = newState; } @@ -836,24 +849,86 @@ void TDENetworkConnectionManager::internalNetworkDeviceStateChanged(TDENetworkCo if (!m_prevDeviceStatus.contains(hwAddress)) { m_prevDeviceStatus[hwAddress] = TDENetworkConnectionStatus::Invalid; } - emit(networkDeviceStateChanged(newState, m_prevDeviceStatus[hwAddress], hwAddress)); + + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 1; + queuedEvent.newConnStatus = newState; + queuedEvent.previousConnStatus = m_prevDeviceStatus[hwAddress]; + queuedEvent.hwAddress = hwAddress; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); + m_prevDeviceStatus[hwAddress] = newState; } void TDENetworkConnectionManager::internalAccessPointStatusChanged(TDEMACAddress BSSID, TDENetworkAPEventType::TDENetworkAPEventType event) { - emit(accessPointStatusChanged(BSSID, event)); + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 2; + queuedEvent.BSSID = BSSID; + queuedEvent.apevent = event; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); } void TDENetworkConnectionManager::internalNetworkDeviceEvent(TDENetworkDeviceEventType::TDENetworkDeviceEventType event, TQString message) { - emit(networkDeviceEvent(event, message)); + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 3; + queuedEvent.ndevent = event; + queuedEvent.message = message; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); } void TDENetworkConnectionManager::internalVpnEvent(TDENetworkVPNEventType::TDENetworkVPNEventType event, TQString message) { - emit(vpnEvent(event, message)); + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 4; + queuedEvent.vpnevent = event; + queuedEvent.message = message; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); } void TDENetworkConnectionManager::internalNetworkManagementEvent(TDENetworkGlobalEventType::TDENetworkGlobalEventType event) { - emit(networkManagementEvent(event)); + TDENetworkEventQueueEvent_Private queuedEvent; + queuedEvent.eventType = 5; + queuedEvent.globalevent = event; + m_globalEventQueueEventList.append(queuedEvent); + if (!m_emissionTimer->isActive()) m_emissionTimer->start(0, TRUE); +} + +void TDENetworkConnectionManager::emitQueuedSignals() { + if (!m_globalEventQueueEventList.isEmpty()) { +#ifdef DEBUG_SIGNAL_QUEUE + kdDebug() << "TDENetworkConnectionManager::emitQueuedSignals: Going to dequeue " << m_globalEventQueueEventList.count() << " events..." << endl; +#endif // DEBUG_SIGNAL_QUEUE + TDENetworkEventQueueEvent_PrivateList::Iterator it; + it = m_globalEventQueueEventList.begin(); + while (it != m_globalEventQueueEventList.end()) { + TDENetworkEventQueueEvent_Private event = (*it); + it = m_globalEventQueueEventList.remove(it); + if (event.eventType == 0) { + emit(networkConnectionStateChanged(event.newState, event.previousState)); + } + else if (event.eventType == 1) { + emit(networkDeviceStateChanged(event.newConnStatus, event.previousConnStatus, event.hwAddress)); + } + else if (event.eventType == 2) { + emit(accessPointStatusChanged(event.BSSID, event.apevent)); + } + else if (event.eventType == 3) { + emit(networkDeviceEvent(event.ndevent, event.message)); + } + else if (event.eventType == 4) { + emit(vpnEvent(event.vpnevent, event.message)); + } + else if (event.eventType == 5) { + emit(networkManagementEvent(event.globalevent)); + } + } +#ifdef DEBUG_SIGNAL_QUEUE + kdDebug() << "TDENetworkConnectionManager::emitQueuedSignals: " << m_globalEventQueueEventList.count() << " events remain in queue" << endl; +#endif // DEBUG_SIGNAL_QUEUE + } } /*================================================================================================*/ diff --git a/tdecore/tdenetworkconnections.h b/tdecore/tdenetworkconnections.h index b1e02ce9d..b8425196a 100644 --- a/tdecore/tdenetworkconnections.h +++ b/tdecore/tdenetworkconnections.h @@ -990,6 +990,29 @@ class TDECORE_EXPORT TDEModemConnection : public TDENetworkConnection typedef TQPtrList< TDENetworkConnection > TDENetworkConnectionList; +/** +* INTERNAL CLASS +*/ +class TDENetworkEventQueueEvent_Private +{ + public: + int eventType; + TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags newState; + TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags previousState; + TDENetworkConnectionStatus::TDENetworkConnectionStatus newConnStatus; + TDENetworkConnectionStatus::TDENetworkConnectionStatus previousConnStatus; + TDEMACAddress BSSID; + TQString message; + TQString hwAddress; + TDENetworkAPEventType::TDENetworkAPEventType apevent; + TDENetworkDeviceEventType::TDENetworkDeviceEventType ndevent; + TDENetworkVPNEventType::TDENetworkVPNEventType vpnevent; + TDENetworkGlobalEventType::TDENetworkGlobalEventType globalevent; +}; +typedef TQValueList TDENetworkEventQueueEvent_PrivateList; + +class TQTimer; + class TDECORE_EXPORT TDENetworkConnectionManager : public TQObject { Q_OBJECT @@ -1024,10 +1047,20 @@ class TDECORE_EXPORT TDENetworkConnectionManager : public TQObject virtual TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags backendStatus() = 0; /** - * @return A TDENetworkDeviceInformation object containing the current status of the network device. + * @return A TDENetworkDeviceInformation object containing the current configuration and status of the network device. */ virtual TDENetworkDeviceInformation deviceInformation() = 0; + /** + * @return A TDENetworkDeviceInformation object containing a (limited) current status of the network device. + * Only the following object fields are populated: + * statusFlags + * UUID + * activeConnectionUUID + * valid + */ + virtual TDENetworkDeviceInformation deviceStatus() = 0; + /** * Loads all connection information from the configuration backend * Secret information must be loaded separately via a call to @@ -1311,12 +1344,17 @@ class TDECORE_EXPORT TDENetworkConnectionManager : public TQObject */ void internalNetworkManagementEvent(TDENetworkGlobalEventType::TDENetworkGlobalEventType event); + protected slots: + void emitQueuedSignals(); + protected: TDENetworkConnectionList* m_connectionList; TDENetworkHWNeighborList* m_hwNeighborList; TQString m_macAddress; TDENetworkGlobalManagerFlags::TDENetworkGlobalManagerFlags m_prevConnectionStatus; TQMap m_prevDeviceStatus; + TQTimer* m_emissionTimer; + TDENetworkEventQueueEvent_PrivateList m_globalEventQueueEventList; }; class TDECORE_EXPORT TDEGlobalNetworkManager : public TQObject