/* * Copyright (C) 2022 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "networkeventhandler.h" #include "network.h" #include "networkadapter.h" NetworkEventHandler::NetworkEventHandler(Network *network, bool register_agent, QQmlContext *context, QObject * parent) : QObject(parent), m_network(network), m_agent(register_agent) { connman_add_manager_event_callback(manager_event_cb, this); connman_add_technology_property_event_callback(technology_event_cb, this); connman_add_service_property_event_callback(service_event_cb, this); if (register_agent) connman_add_agent_event_callback(agent_event_cb, this); } NetworkEventHandler::~NetworkEventHandler() { } bool NetworkEventHandler::populateAdapterProperties(GVariant *in, QVariantMap &out) { GVariantDict *props_dict = g_variant_dict_new(in); if (!props_dict) return false; gchar *p = NULL; gboolean value = FALSE; if (g_variant_dict_lookup(props_dict, "Connected", "b", &value)) out.insert(QString("Connected"), QVariant((bool) value)); if (g_variant_dict_lookup(props_dict, "Powered", "b", &value)) out.insert(QString("Powered"), QVariant((bool) value)); g_variant_dict_unref(props_dict); return true; } bool NetworkEventHandler::populateServiceProperties(GVariant *in, QVariantMap &out) { GVariantDict *props_dict = g_variant_dict_new(in); if (!props_dict) return false; gchar *p = NULL; if (g_variant_dict_lookup(props_dict, "Type", "&s", &p)) out.insert(QString("Type"), QVariant(QString(p))); if (g_variant_dict_lookup(props_dict, "Name", "&s", &p)) out.insert(QString("Name"), QVariant(QString(p))); if (g_variant_dict_lookup(props_dict, "State", "&s", &p)) out.insert(QString("State"), QVariant(QString(p))); guchar strength = 0; if (g_variant_dict_lookup(props_dict, "Strength", "y", &strength)) out.insert(QString("Strength"), QVariant((int) strength)); GVariant *v = NULL; if (g_variant_dict_lookup(props_dict, "IPv4", "@a{sv}", &v)) { GVariantDict *ip4_dict = g_variant_dict_new(v); QVariantMap ip4_map; if (g_variant_dict_lookup(ip4_dict, "Address", "&s", &p)) ip4_map.insert(QString("Address"), QVariant(QString(p))); if (g_variant_dict_lookup(ip4_dict, "Netmask", "&s", &p)) ip4_map.insert(QString("Netmask"), QVariant(QString(p))); if (g_variant_dict_lookup(ip4_dict, "Gateway", "&s", &p)) ip4_map.insert(QString("Gateway"), QVariant(QString(p))); if (g_variant_dict_lookup(ip4_dict, "Method", "&s", &p)) ip4_map.insert(QString("Method"), QVariant(QString(p))); g_variant_dict_unref(ip4_dict); g_variant_unref(v); if (!ip4_map.isEmpty()) out.insert(QString("IPv4"), QVariant(ip4_map)); } if (g_variant_dict_lookup(props_dict, "Nameservers", "&s", &v)) out.insert(QString("Nameservers"), QVariant(QString(p))); GVariantIter *array = NULL; if (g_variant_dict_lookup(props_dict, "Security", "as", &array)) { QVariantList security; while (g_variant_iter_loop(array, "&s", &p)) security.push_back(QVariant(QString(p))); if (!security.isEmpty()) out.insert(QString("Security"), QVariant(security)); g_variant_iter_free(array); } g_variant_dict_unref(props_dict); return !out.isEmpty(); } void NetworkEventHandler::handle_connect_event(const gchar *service, gboolean status, const gchar *error) { if (!status) qDebug() << "connect failed, error " << error; emit connectResponseReceived(QString(service), status, QString(error)); } void NetworkEventHandler::handle_manager_event(const gchar *path, connman_manager_event_t event, GVariant *properties) { #if LIBQTAPPFW_NETWORK_DEBUG QString props("NULL"); QString event_str(""); switch(event) { case CONNMAN_MANAGER_EVENT_TECHNOLOGY_ADD: event_str = "TECHNOLOGY_ADD"; break; case CONNMAN_MANAGER_EVENT_TECHNOLOGY_REMOVE: event_str = "TECHNOLOGY_REMOVE"; break; case CONNMAN_MANAGER_EVENT_SERVICE_CHANGE: event_str = "SERVICE_CHANGE"; break; case CONNMAN_MANAGER_EVENT_SERVICE_REMOVE: event_str = "SERVICE_REMOVE"; break; case CONNMAN_MANAGER_EVENT_PROPERTY_CHANGE: event_str = "PROPERTY_CHANGE"; break; } if (event != CONNMAN_MANAGER_EVENT_TECHNOLOGY_REMOVE && event != CONNMAN_MANAGER_EVENT_SERVICE_REMOVE) { gchar *p = g_variant_print(properties, TRUE); props = p; g_free(p); } qDebug() << "NetworkEventHandler::handle_manager_event: received " << event_str << ", path = " << path << ", properties = " << props; #endif switch(event) { case CONNMAN_MANAGER_EVENT_TECHNOLOGY_ADD: case CONNMAN_MANAGER_EVENT_TECHNOLOGY_REMOVE: break; case CONNMAN_MANAGER_EVENT_SERVICE_CHANGE: { QVariantMap props_map; if (populateServiceProperties(properties, props_map)) { emit serviceAdded(path, props_map); } } break; case CONNMAN_MANAGER_EVENT_SERVICE_REMOVE: emit serviceRemoved(QString(path)); break; case CONNMAN_MANAGER_EVENT_PROPERTY_CHANGE: break; default: break; } } void NetworkEventHandler::handle_technology_event(const gchar *technology, GVariant *property) { if (!(technology && property)) return; #if LIBQTAPPFW_NETWORK_DEBUG gchar *p = g_variant_print(property, TRUE); qDebug() << "NetworkEventHandler::handle_technology_event: technology = " << technology << ", property = " << p; g_free(p); #endif // Convert (sv) tuple to a a{sv} dict for parsing const gchar *key = NULL; GVariant *var = NULL; g_variant_get(property, "(sv)", &key, &var); if (!key) return; // Build QVariantMap for updateStatus QVariantMap props_map; if ((g_strcmp0(key, "Connected") == 0 || g_strcmp0(key, "Powered") == 0) && g_variant_is_of_type(var, G_VARIANT_TYPE_BOOLEAN)) { gboolean value; g_variant_get(var, "b", &value); props_map.insert(QString(key), QVariant((bool) value)); // Update properties emit adapterStatusChanged(QString(technology), props_map); } g_variant_unref(var); } void NetworkEventHandler::handle_service_event(const gchar *service, GVariant *property) { if (!(service && property)) return; #if LIBQTAPPFW_NETWORK_DEBUG gchar *p = g_variant_print(property, TRUE); qDebug() << "NetworkEventHandler::handle_service_event: service = " << service << ", property = " << p; g_free(p); #endif // Convert (sv) tuple to a a{sv} dict for updateProperties const gchar *key = NULL; GVariant *var = NULL; g_variant_get(property, "(sv)", &key, &var); if (!key) return; GVariantDict *props_dict = g_variant_dict_new(NULL); if (!props_dict) { qWarning() << "g_variant_dict_new failed"; return; } g_variant_dict_insert_value(props_dict, key, var); GVariant *props_var = g_variant_dict_end(props_dict); g_variant_dict_unref(props_dict); g_variant_unref(var); QVariantMap props_map; if (populateServiceProperties(props_var, props_map)) { // Update adapter properties emit servicePropertiesChanged(QString(service), props_map); } g_variant_unref(props_var); } void NetworkEventHandler::handle_agent_event(const gchar *service, const int id, GVariant *properties) { if (!(service && properties)) return; #if LIBQTAPPFW_NETWORK_DEBUG gchar *props = g_variant_print(properties, TRUE); qDebug() << "Network::handle_agent_event: properties = " << props; g_free(props); #endif GVariantDict *props_dict = g_variant_dict_new(properties); if (!props_dict) return; GVariant *v = NULL; QVariantMap props_map; if (g_variant_dict_lookup(props_dict, "Passphrase", "@a{sv}", &v)) { GVariantDict *passphrase_dict = g_variant_dict_new(v); gchar *p = NULL; if (g_variant_dict_lookup(passphrase_dict, "Type", "&s", &p)) props_map.insert(QString("Type"), QVariant(QString(p))); if (g_variant_dict_lookup(passphrase_dict, "Requirement", "&s", &p)) props_map.insert(QString("Requirement"), QVariant(QString(p))); g_variant_dict_unref(passphrase_dict); g_variant_unref(v); } g_variant_dict_unref(props_dict); if (!props_map.isEmpty()) emit inputRequested(id, props_map); }