/* * Copyright (C) 2018 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 #include #include "message.h" #include "messageengine.h" #include "network.h" #include "networkmessage.h" #include "responsemessage.h" #include "wifinetworkmodel.h" Network::Network (QUrl &url, QQmlContext *context, QObject * parent) : QObject(parent), m_mloop(nullptr), m_wifi(nullptr), m_wifiConnected(false), m_wifiEnabled(false), m_wifiStrength(0) { m_mloop = new MessageEngine(url); m_wifi = new WifiNetworkModel(); QSortFilterProxyModel *m_model = new QSortFilterProxyModel(); m_model->setSourceModel(m_wifi); m_model->setSortRole(WifiNetworkModel::WifiNetworkRoles::SsidRole); m_model->setSortCaseSensitivity(Qt::CaseInsensitive); m_model->sort(0); context->setContextProperty("WifiNetworkModel", m_model); QObject::connect(m_mloop, &MessageEngine::connected, this, &Network::onConnected); QObject::connect(m_mloop, &MessageEngine::disconnected, this, &Network::onDisconnected); QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &Network::onMessageReceived); QObject::connect(m_wifi, &WifiNetworkModel::strengthChanged, this, &Network::updateWifiStrength); } Network::~Network() { delete m_mloop; delete m_wifi; } void Network::connect(QString service) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("service", service); nmsg->createRequest("connect_service", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::disconnect(QString service) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("service", service); nmsg->createRequest("disconnect_service", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::remove(QString service) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("service", service); nmsg->createRequest("remove_service", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::input(int id, QString passphrase) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter, fields; parameter.insert("id", id); fields.insert("passphrase", passphrase); parameter.insert("fields", fields); nmsg->createRequest("agent_response", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::power(bool on) { if (on) enableTechnology("wifi"); else disableTechnology("wifi"); } void Network::enableTechnology(QString type) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("technology", type); nmsg->createRequest("enable_technology", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::disableTechnology(QString type) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("technology", type); nmsg->createRequest("disable_technology", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::scanServices(QString type) { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("technology", type); nmsg->createRequest("scan_services", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } bool Network::addService(QJsonObject service) { // Ignore services that are already added QString id = service.value("service").toString(); if (m_wifi->getNetwork(id)) return false; QJsonObject properties = service.value("properties").toObject(); // Ignore hidden SSIDs QString ssid = properties.value("name").toString(); if (ssid == "") return false; // Ignore technologies other than WiFi QString type = properties.value("type").toString(); if (type != "wifi") return false; // Initially support only IPv4 and the first security method found QString address = properties.value("ipv4").toObject().value("address").toString(); QString security = properties.value("security").toArray().at(0).toString(); QString state = properties.value("state").toString(); int strength = properties.value("strength").toInt(); WifiNetwork *network = new WifiNetwork(address, security, id, ssid, state, strength); m_wifi->addNetwork(network); if ((state == "ready") || (state == "online")) updateWifiStrength(strength); return true; } void Network::removeService(QJsonObject service) { QString id = service.value("service").toString(); WifiNetwork *network = m_wifi->getNetwork(id); if (network) m_wifi->removeNetwork(network); } void Network::addServices(QJsonArray services) { for (auto service : services) addService(service.toObject()); } void Network::getServices() { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; nmsg->createRequest("services", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::updateWifiStatus(QJsonObject properties) { if (properties.contains("connected")) { m_wifiConnected = properties.value("connected").toBool(); emit wifiConnectedChanged(m_wifiConnected); } if (properties.contains("powered")) { m_wifiEnabled = properties.value("powered").toBool(); emit wifiEnabledChanged(m_wifiEnabled); if (m_wifiEnabled) getServices(); } } void Network::updateWifiStrength(int strength) { m_wifiStrength = strength; emit wifiStrengthChanged(m_wifiStrength); } void Network::parseTechnologies(QJsonArray technologies) { for (auto value : technologies) { QJsonObject technology = value.toObject(); QJsonObject properties = technology.value("properties").toObject(); QString type = properties.value("type").toString(); if (type == "wifi") { updateWifiStatus(properties); if (m_wifiEnabled) getServices(); break; } } } void Network::getTechnologies() { NetworkMessage *nmsg = new NetworkMessage(); QJsonObject parameter; nmsg->createRequest("technologies", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } void Network::updateServiceProperties(QJsonObject data) { QString service = data.value("service").toString(); QJsonObject properties = data.value("properties").toObject(); m_wifi->updateProperties(service, properties); } void Network::processEvent(NetworkMessage *nmsg) { if (nmsg->eventName() == "agent") { QJsonObject agent = nmsg->eventData(); QJsonObject fields = agent.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 = agent.value("id").toInt(); emit inputRequest(id); } } else if (nmsg->eventName() == "services") { QJsonArray services = nmsg->eventData().value("values").toArray(); for (auto value : services) { QJsonObject service = value.toObject(); QString action = service.value("action").toString(); QString id = service.value("service").toString(); if (action == "changed") { addService(service); } else if (action == "removed") { removeService(service); } } } else if (nmsg->eventName() == "service_properties") { updateServiceProperties(nmsg->eventData()); } else if (nmsg->eventName() == "technology_properties") { QJsonObject technology = nmsg->eventData(); if (technology.value("technology").toString() == "wifi") { QJsonObject properties = technology.value("properties").toObject(); updateWifiStatus(properties); } } } void Network::processReply(ResponseMessage *rmsg) { if (rmsg->requestVerb() == "services") { addServices(rmsg->replyData().value("values").toArray()); } else if (rmsg->requestVerb() == "technologies") { parseTechnologies(rmsg->replyData().value("values").toArray()); } else if (rmsg->requestVerb() == "connect_service") { if (rmsg->replyStatus() == "failed" && rmsg->replyInfo().contains("invalid-key")) { emit invalidPassphrase(rmsg->requestData()["parameter"].toMap()["service"].toString()); } } } void Network::onMessageReceived(MessageType type, Message *msg) { if (msg->isEvent() && (type == NetworkEventMessage)) { processEvent(qobject_cast(msg)); } else if (msg->isReply() && (type == ResponseRequestMessage)) { processReply(qobject_cast(msg)); } msg->deleteLater(); } void Network::onConnected() { QStringListIterator eventIterator(events); NetworkMessage *nmsg; while (eventIterator.hasNext()) { nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("value", eventIterator.next()); nmsg->createRequest("subscribe", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } getTechnologies(); } void Network::onDisconnected() { QStringListIterator eventIterator(events); NetworkMessage *nmsg; while (eventIterator.hasNext()) { nmsg = new NetworkMessage(); QJsonObject parameter; parameter.insert("value", eventIterator.next()); nmsg->createRequest("unsubscribe", parameter); m_mloop->sendMessage(nmsg); delete nmsg; } m_wifi->removeAllNetworks(); }