summaryrefslogtreecommitdiffstats
path: root/network/network.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'network/network.cpp')
-rw-r--r--network/network.cpp554
1 files changed, 231 insertions, 323 deletions
diff --git a/network/network.cpp b/network/network.cpp
index 937266f..52cafad 100644
--- a/network/network.cpp
+++ b/network/network.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2021 Konsulko Group
+ * Copyright (C) 2018-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.
@@ -16,408 +16,316 @@
#include <QDebug>
#include <QtQml/QQmlEngine>
+#include <QThread>
+#include <connman-glib.h>
-#include "networkadapter.h"
+#include "wifiadapter.h"
+#include "wiredadapter.h"
#include "network.h"
+#include "networkeventhandler.h"
-
-Network::Network (bool register_agent, QQmlContext *context, QObject * parent) :
- QObject(parent)
+Network::Network(bool register_agent, QQmlContext *context, QObject * parent) :
+ QObject(parent),
+ m_agent(register_agent)
{
- m_adapters.append(new WifiAdapter(this, context, parent));
- m_adapters.append(new WiredAdapter(this, context, parent));
+ m_adapters.append(new WifiAdapter(this, context, parent));
+ m_adapters.append(new WiredAdapter(this, context, parent));
+
+ m_event_handler = new NetworkEventHandler(this, register_agent, context, parent);
+
+ // Hook up signals so updates can be made to happen from the UI thread as Qt requires
+ QObject::connect(m_event_handler, &NetworkEventHandler::adapterStatusChanged, this, &Network::updateAdapterStatus, Qt::QueuedConnection);
+ QObject::connect(m_event_handler, &NetworkEventHandler::servicePropertiesChanged, this, &Network::updateServiceProperties, Qt::QueuedConnection);
+ QObject::connect(m_event_handler, &NetworkEventHandler::serviceAdded, this, &Network::addService, Qt::QueuedConnection);
+ QObject::connect(m_event_handler, &NetworkEventHandler::serviceRemoved, this, &Network::removeService, Qt::QueuedConnection);
+ QObject::connect(m_event_handler, &NetworkEventHandler::inputRequested, this, &Network::requestInput, Qt::QueuedConnection);
+ QObject::connect(m_event_handler, &NetworkEventHandler::connectResponseReceived, this, &Network::handleConnectResponse, Qt::QueuedConnection);
+
+ connman_init(register_agent);
+
+ getTechnologies();
}
Network::~Network()
{
- while (!m_adapters.isEmpty())
- m_adapters.takeLast();
+ while (!m_adapters.isEmpty())
+ m_adapters.takeLast();
}
void Network::connect(QString service)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
+ QByteArray service_ba = service.toLocal8Bit();
+ const char *service_cstr = service_ba.data();
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- parameter.insert("service", service);
-
- nmsg->createRequest("network-manager", "connect_service", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ connman_service_connect(service_cstr, m_event_handler->service_connect_cb, m_event_handler);
}
void Network::disconnect(QString service)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
+ QByteArray service_ba = service.toLocal8Bit();
+ const char *service_cstr = service_ba.data();
- parameter.insert("service", service);
-
- nmsg->createRequest("network-manager", "disconnect_service", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ connman_service_disconnect(service_cstr);
}
void Network::remove(QString service)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
+ QByteArray service_ba = service.toLocal8Bit();
+ const char *service_cstr = service_ba.data();
- parameter.insert("service", service);
-
- nmsg->createRequest("network-manager", "remove_service", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ connman_service_remove(service_cstr);
}
void Network::power(bool on, QString type)
{
- if (on)
- enableTechnology(type);
- else
- disableTechnology(type);
+ if (on)
+ enableTechnology(type);
+ else
+ disableTechnology(type);
}
void Network::input(int id, QString passphrase)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter, fields;
-
- parameter.insert("id", id);
- fields.insert("passphrase", passphrase);
- parameter.insert("fields", fields);
-
- nmsg->createRequest("network-manager", "agent_response", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ QByteArray passphrase_ba = passphrase.toLocal8Bit();
+ const char *passphrase_cstr = passphrase_ba.data();
+
+ // e.g. ({'Passphrase': <'foo'>},)
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_add(&builder,
+ "{sv}",
+ "Passphrase",
+ g_variant_new_string(passphrase_cstr));
+
+ // Wrap in required tuple
+ GVariantBuilder builder2;
+ g_variant_builder_init(&builder2, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&builder2,
+ g_variant_builder_end(&builder));
+ GVariant *parameters = g_variant_builder_end(&builder2);
+
+ if (parameters) {
+ connman_agent_response(id, parameters);
+ } else {
+ qWarning() << "Could not build response for input request " << id;
+ }
}
void Network::configureAddress(QString service, QVariantList paramlist)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter, type, properties;
- QJsonArray values = QJsonArray::fromVariantList(paramlist);
-
- if (values.isEmpty() || values.count() < 4) {
- qWarning("Invalid addressing params");
- return;
- }
-
- properties.insert("method", values[0]);
- properties.insert("address", values[1]);
- properties.insert("netmask", values[2]);
- properties.insert("gateway", values[3]);
- type.insert("ipv4.configuration", properties);
- parameter.insert("properties", type);
- parameter.insert("service", service);
-
- nmsg->createRequest("network-manager", "set_property", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ if (service.isEmpty() || paramlist.size() < 4) {
+ qWarning("Invalid addressing params");
+ return;
+ }
+
+ QByteArray path_ba = service.toLocal8Bit();
+
+ GVariantDict *params_dict = g_variant_dict_new(NULL);
+ if (!params_dict) {
+ qWarning() << "g_variant_dict_new failed";
+ return;
+ }
+
+ QByteArray param_ba = paramlist[0].toString().toLocal8Bit();
+ g_variant_dict_insert(params_dict, "Method", "s", param_ba.data());
+ param_ba = paramlist[1].toString().toLocal8Bit();
+ g_variant_dict_insert(params_dict, "Address", "s", param_ba.data());
+ param_ba = paramlist[2].toString().toLocal8Bit();
+ g_variant_dict_insert(params_dict, "Netmask", "s", param_ba.data());
+ param_ba = paramlist[3].toString().toLocal8Bit();
+ g_variant_dict_insert(params_dict, "Gateway", "s", param_ba.data());
+ GVariant *parameters = g_variant_dict_end(params_dict);
+ g_variant_dict_unref(params_dict);
+
+ // Need to end up with something like:
+ // - path = ethernet_525400123502_cable
+ // - name = IPv4.Configuration
+ // - parameters = {'Method': <'manual'>, 'Gateway': <'10.0.2.2'>, 'Address': <'10.0.2.15'>, 'Netmask': <'255.255.255'>}
+ if (!connman_set_property(CONNMAN_PROPERTY_SERVICE,
+ path_ba.data(),
+ "IPv4.Configuration",
+ parameters)) {
+ qWarning() << "Could not configure address";
+ }
}
void Network::configureNameServer(QString service, QVariantList paramlist)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter, properties;
- QJsonArray values = QJsonArray::fromVariantList(paramlist);
-
- if (values.isEmpty() || values.count() < 2) {
- qWarning("Invalid nameserver params");
- return;
- }
-
- QStringList nslist = values[1].toString().split(' ');
- QJsonArray nameservers = QJsonArray::fromStringList(nslist);
-
- properties.insert("nameservers.configuration", nameservers);
- parameter.insert("properties", properties);
- parameter.insert("service", service);
-
- nmsg->createRequest("network-manager", "set_property", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ // paramlist will be 'manual|auto', 'server1'...
+ // NOTE: currently unclear what should happen for 'auto' case
+ if (service.isEmpty() || paramlist.size() < 2) {
+ qWarning("Invalid nameserver params");
+ return;
+ }
+
+ QByteArray path_ba = service.toLocal8Bit();
+
+ QStringList nslist = paramlist[1].toString().split(' ');
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
+ QStringList::const_iterator iter;
+ for (iter = nslist.constBegin(); iter != nslist.constEnd(); ++iter) {
+ g_variant_builder_add(&builder,
+ "s",
+ (*iter).toLocal8Bit().constData());
+ }
+ GVariant *parameters = g_variant_builder_end(&builder);
+
+ // Need to end up with something like:
+ // - path = ethernet_525400123502_cable
+ // - name = Nameservers.Configuration
+ // - value = ['8.8.8.8.8']
+ if (!connman_set_property(CONNMAN_PROPERTY_SERVICE,
+ path_ba.data(),
+ "Nameservers.Configuration",
+ parameters)) {
+ qWarning() << "Could not configure nameserver";
+ }
}
void Network::getServices()
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- nmsg->createRequest("network-manager", "services", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ GVariant *reply = NULL;
+ if(!connman_get_services(&reply)) {
+ qWarning() << "Network::getServices: connman_get_services failed!";
+ return;
+ }
+
+ GVariantIter *array = NULL;
+ g_variant_get(reply, "(a(oa{sv}))", &array);
+ const gchar *path = NULL;
+ GVariant *var = NULL;
+ while (g_variant_iter_next(array, "(o@a{sv})", &path, &var)) {
+ QString id = path;
+ id = id.mid(id.lastIndexOf("/") + 1);
+ QVariantMap props_map;
+ if (m_event_handler->populateServiceProperties(var, props_map)) {
+ QList<AdapterIf*>::iterator iter;
+ for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
+ if ((*iter)->addService(id, props_map))
+ break;
+ }
+ g_variant_unref(var);
+ }
+ g_variant_iter_free(array);
+ g_variant_unref(reply);
}
-AdapterIf* Network::findAdapter(QString type)
+AdapterIf* Network::findAdapter(const QString &type)
{
- QList<AdapterIf*>::iterator iter;
- for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
- if ((*iter)->getType() == type)
- return (*iter);
- return nullptr;
+ QList<AdapterIf*>::iterator iter;
+ for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
+ if ((*iter)->getType() == type)
+ return (*iter);
+ return nullptr;
}
-void Network::updateServiceProperties(QJsonObject data)
+void Network::scanServices(const QString &technology)
{
-#if 0
- QString service = data.value("service").toString();
- QJsonObject properties = data.value("properties").toObject();
- QList<AdapterIf*>::iterator iter;
- for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
- (*iter)->updateProperties(service, properties);
-#endif
-}
+ QByteArray technology_ba = technology.toLocal8Bit();
+ const char *technology_cstr = technology_ba.data();
-bool Network::addService(QJsonObject service)
-{
-#if 0
- QString id = service.value("service").toString();
- QJsonObject properties = service.value("properties").toObject();
- QList<AdapterIf*>::iterator iter;
- for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
- if ((*iter)->addService(id, properties))
- return true;
-#endif
- return false;
+ connman_technology_scan_services(technology_cstr);
}
-void Network::removeService(QJsonObject service)
+void Network::disableTechnology(const QString &technology)
{
-#if 0
- QString id = service.value("service").toString();
- QList<AdapterIf*>::iterator iter;
- for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
- (*iter)->removeService(id);
-#endif
-}
+ QByteArray technology_ba = technology.toLocal8Bit();
+ const char *technology_cstr = technology_ba.data();
-void Network::addServices(QJsonArray services)
-{
- for (auto service : services)
- addService(service.toObject());
+ connman_technology_disable(technology_cstr);
}
-void Network::scanServices(QString type)
+void Network::enableTechnology(const QString &technology)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- parameter.insert("technology", type);
- nmsg->createRequest("network-manager", "scan_services", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
-}
+ QByteArray technology_ba = technology.toLocal8Bit();
+ const char *technology_cstr = technology_ba.data();
-void Network::disableTechnology(QString type)
-{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- parameter.insert("technology", type);
- nmsg->createRequest("network-manager", "disable_technology", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ connman_technology_enable(technology_cstr);
}
-void Network::enableTechnology(QString type)
+void Network::getTechnologies()
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- parameter.insert("technology", type);
- nmsg->createRequest("network-manager", "enable_technology", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ GVariant *reply = NULL;
+ if(!connman_get_technologies(&reply))
+ return;
+
+ GVariantIter *array = NULL;
+ g_variant_get(reply, "(a(oa{sv}))", &array);
+ if (!array) {
+ g_variant_unref(reply);
+ return;
+ }
+ const gchar *path = NULL;
+ GVariant *properties = NULL;
+ while (g_variant_iter_next(array, "(o@a{sv})", &path, &properties)) {
+ GVariantDict *props_dict = g_variant_dict_new(properties);
+ gchar *type_cstr = NULL;
+ if (g_variant_dict_lookup(props_dict, "Type", "s", &type_cstr)) {
+ QString type(type_cstr);
+ AdapterIf* adapter = findAdapter(type);
+ if (adapter) {
+ QVariantMap props_map;
+ if (m_event_handler->populateAdapterProperties(properties, props_map))
+ adapter->updateStatus(props_map);
+ }
+ }
+ g_variant_dict_unref(props_dict);
+ g_variant_unref(properties);
+ }
+ g_variant_iter_free(array);
+ g_variant_unref(reply);
}
-void Network::parseTechnologies(QJsonArray technologies)
+void Network::updateAdapterStatus(const QString &technology, const QVariantMap &properties)
{
-#if 0
- for (auto value : technologies) {
- QJsonObject technology = value.toObject();
- QJsonObject properties = technology.value("properties").toObject();
- QString type = properties.value("type").toString();
-
- AdapterIf* adapter = findAdapter(type);
+ AdapterIf* adapter = findAdapter(technology);
if (adapter)
- adapter->updateStatus(properties);
- }
-#endif
+ adapter->updateStatus(properties);
}
-void Network::getTechnologies()
+void Network::updateServiceProperties(const QString &service, const QVariantMap &properties)
{
-#if 0
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
-
- nmsg->createRequest("network-manager", "technologies", parameter);
- m_mloop->sendMessage(std::move(msg));
-#endif
+ QList<AdapterIf*>::iterator iter;
+ for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
+ (*iter)->updateProperties(service, properties);
}
-#if 0
-void Network::processEvent(std::shared_ptr<Message> msg)
+void Network::addService(const QString &service, const QVariantMap &properties)
{
-
- std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg);
- QString ename = emsg->eventName();
- QString eapi = emsg->eventApi();
- QJsonObject data = emsg->eventData();
-
- if (eapi != "network-manager")
- return;
-
- if (ename == "agent") {
- QJsonObject fields = data.value("fields").toObject();
- QJsonObject passphrase = fields.value("passphrase").toObject();
- QString type = passphrase.value("type").toString();
- QString reqmt = passphrase.value("requirement").toString();
- if (((type == "psk") || (type == "wep")) && (reqmt == "mandatory")) {
- int id = data.value("id").toInt();
- emit inputRequest(id);
- }
- } else if (ename == "services") {
- QJsonArray services = data.value("values").toArray();
- for (auto value : services) {
- QJsonObject service = value.toObject();
- QString action = service.value("action").toString();
- if (action == "changed") {
- addService(service);
- } else if (action == "removed") {
- removeService(service);
- }
- }
- } else if (ename == "service_properties") {
- updateServiceProperties(data);
- } else if (ename == "technology_properties") {
- QJsonObject properties = data.value("properties").toObject();
- QString type = data.value("technology").toString();
- AdapterIf* adapter = findAdapter(type);
- if (adapter)
- adapter->updateStatus(properties);
- }
+ QList<AdapterIf*>::iterator iter;
+ for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
+ if ((*iter)->addService(service, properties))
+ break;
}
-void Network::processReply(std::shared_ptr<Message> msg)
+void Network::removeService(const QString &service)
{
- std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg);
- QString verb = rmsg->requestVerb();
- QJsonObject data = rmsg->replyData();
-
- if (verb == "services") {
- addServices(data.value("values").toArray());
- } else if (verb == "technologies") {
- parseTechnologies(data.value("values").toArray());
- } else if (verb == "connect_service") {
- if (rmsg->replyStatus() == "failed" && rmsg->replyInfo().contains("invalid-key")) {
- emit invalidPassphrase(rmsg->requestParameters()["service"].toString());
- }
- }
+ QList<AdapterIf*>::iterator iter;
+ for (iter = m_adapters.begin(); iter != m_adapters.end(); ++iter)
+ (*iter)->removeService(service);
}
-void Network::onMessageReceived(std::shared_ptr<Message> msg)
+void Network::requestInput(int id, const QVariantMap &properties)
{
- if (!msg)
- return;
+ QString type;
+ QString key = "Type";
+ if (properties.contains(key))
+ type = properties.value(key).toString();
- if (msg->isEvent())
- processEvent(msg);
- else if (msg->isReply())
- processReply(msg);
-}
-#endif
+ QString reqmt;
+ key = "Requirement";
+ if (properties.contains(key))
+ reqmt = properties.value(key).toString();
-void Network::onConnected()
-{
-#if 0
- QStringListIterator eventIterator(events);
-
- while (eventIterator.hasNext()) {
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
-
- CallMessage* nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
- parameter.insert("value", eventIterator.next());
- nmsg->createRequest("network-manager", "subscribe", parameter);
- m_mloop->sendMessage(std::move(msg));
- }
-#endif
- getTechnologies();
+ if (((type == "psk") || (type == "wep")) && (reqmt == "mandatory")) {
+ emit inputRequest(id);
+ }
}
-void Network::onDisconnected()
+void Network::handleConnectResponse(const QString &service, bool status, const QString &error)
{
-#if 0
- QStringListIterator eventIterator(events);
-
- while (eventIterator.hasNext()) {
- std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call);
- if (!msg)
- return;
- CallMessage *nmsg = static_cast<CallMessage*>(msg.get());
- QJsonObject parameter;
- parameter.insert("value", eventIterator.next());
- nmsg->createRequest("network-manager", "unsubscribe", parameter);
- m_mloop->sendMessage(std::move(msg));
- }
-#endif
- getTechnologies();
+ if (!status && error.contains("invalid-key")) {
+ emit invalidPassphrase(service);
+ }
}