mirror of https://github.com/nymea/nymea.git
221 lines
7.1 KiB
C++
221 lines
7.1 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.guru> *
|
|
* *
|
|
* This file is part of guh. *
|
|
* *
|
|
* Guh is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, version 2 of the License. *
|
|
* *
|
|
* Guh is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "cloudmanager.h"
|
|
#include "jsonhandler.h"
|
|
#include "guhcore.h"
|
|
|
|
#include <QJsonDocument>
|
|
#include <QJsonParseError>
|
|
|
|
namespace guhserver {
|
|
|
|
CloudManager::CloudManager(QObject *parent) :
|
|
TransportInterface(parent),
|
|
m_enabled(true),
|
|
m_authenticated(false)
|
|
{
|
|
m_cloudConnection = new CloudConnection(this);
|
|
connect(m_cloudConnection, &CloudConnection::authenticatedChanged, this, &CloudManager::onAuthenticatedChanged);
|
|
connect(m_cloudConnection, &CloudConnection::connectedChanged, this, &CloudManager::onConnectedChanged);
|
|
|
|
m_interface = new CloudInterface(this);
|
|
connect(m_cloudConnection, &CloudConnection::dataReceived, m_interface, &CloudInterface::dataReceived);
|
|
}
|
|
|
|
CloudManager::~CloudManager()
|
|
{
|
|
qCDebug(dcApplication) << "Shutting down \"Cloud Manager\"";
|
|
stopServer();
|
|
}
|
|
|
|
void CloudManager::connectToCloud(const QString &username, const QString &password)
|
|
{
|
|
m_cloudConnection->authenticator()->setUsername(username);
|
|
m_cloudConnection->authenticator()->setPassword(password);
|
|
|
|
m_cloudConnection->connectToCloud();
|
|
}
|
|
|
|
void CloudManager::sendData(const QUuid &clientId, const QVariantMap &data)
|
|
{
|
|
// Used from the JsonRpcServer
|
|
m_interface->sendApiData(m_tunnelClients.value(clientId), data);
|
|
}
|
|
|
|
void CloudManager::sendData(const QList<QUuid> &clients, const QVariantMap &data)
|
|
{
|
|
// Used from the JsonRpcServer
|
|
foreach (const QUuid &clientId, clients) {
|
|
sendData(clientId, data);
|
|
}
|
|
}
|
|
|
|
bool CloudManager::enabled() const
|
|
{
|
|
return m_enabled;
|
|
}
|
|
|
|
bool CloudManager::connected() const
|
|
{
|
|
return m_cloudConnection->connected();
|
|
}
|
|
|
|
bool CloudManager::active() const
|
|
{
|
|
return m_active;
|
|
}
|
|
|
|
bool CloudManager::authenticated() const
|
|
{
|
|
return m_authenticated;
|
|
}
|
|
|
|
bool CloudManager::startServer()
|
|
{
|
|
m_cloudConnection->connectToCloud();
|
|
return true;
|
|
}
|
|
|
|
bool CloudManager::stopServer()
|
|
{
|
|
m_cloudConnection->disconnectFromCloud();
|
|
return true;
|
|
}
|
|
|
|
void CloudManager::sendCloudData(const QVariantMap &data)
|
|
{
|
|
m_cloudConnection->sendData(QJsonDocument::fromVariant(data).toJson());
|
|
}
|
|
|
|
void CloudManager::onConnectionAuthentificationFinished(const bool &authenticated, const QUuid &connectionId)
|
|
{
|
|
qCDebug(dcCloud()) << "Cloud connection authenticated" << authenticated;
|
|
if (authenticated) {
|
|
m_authenticated = true;
|
|
m_connectionId = connectionId;
|
|
qCDebug(dcCloud()) << "Connection id:" << connectionId.toString();
|
|
|
|
// Get tunnel connections
|
|
m_interface->getTunnels();
|
|
|
|
} else {
|
|
m_authenticated = false;
|
|
authenticatedChanged();
|
|
}
|
|
}
|
|
|
|
void CloudManager::onTunnelAdded(const QUuid &tunnelId, const QUuid &serverId, const QUuid &clientId)
|
|
{
|
|
if (serverId == m_connectionId) {
|
|
qCDebug(dcCloud()) << "New tunnel connection from" << clientId.toString();
|
|
m_tunnelClients.insert(clientId, tunnelId);
|
|
emit clientConnected(clientId);
|
|
}
|
|
}
|
|
|
|
void CloudManager::onTunnelRemoved(const QUuid &tunnelId)
|
|
{
|
|
if (m_tunnelClients.values().contains(tunnelId)) {
|
|
QUuid clientId = m_tunnelClients.key(tunnelId);
|
|
m_tunnelClients.remove(clientId);
|
|
emit clientDisconnected(clientId);
|
|
if (m_tunnelClients.isEmpty()) {
|
|
qCDebug(dcCloud()) << "Remote connection inactive.";
|
|
setActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CloudManager::onCloudDataReceived(const QUuid &tunnelId, const QVariantMap &data)
|
|
{
|
|
if (m_tunnelClients.values().contains(tunnelId)) {
|
|
QUuid clientId = m_tunnelClients.key(tunnelId);
|
|
|
|
bool success;
|
|
int commandId = data.value("id").toInt(&success);
|
|
if (!success) {
|
|
qCWarning(dcCloud()) << "TunnelData: Error parsing command. Missing \"id\":" << data;
|
|
sendErrorResponse(clientId, commandId, "Error parsing command. Missing 'id'");
|
|
return;
|
|
}
|
|
|
|
QStringList commandList = data.value("method").toString().split('.');
|
|
if (commandList.count() != 2) {
|
|
qCWarning(dcCloud()) << "TunnelData: Error parsing method.\nGot:" << data.value("method").toString() << "\nExpected: \"Namespace.method\"";
|
|
return;
|
|
}
|
|
|
|
QString targetNamespace = commandList.first();
|
|
QString method = commandList.last();
|
|
|
|
JsonHandler *handler = GuhCore::instance()->jsonRPCServer()->handlers().value(targetNamespace);
|
|
if (!handler) {
|
|
sendErrorResponse(clientId, commandId, "No such namespace");
|
|
return;
|
|
}
|
|
if (!handler->hasMethod(method)) {
|
|
sendErrorResponse(clientId, commandId, "No such method");
|
|
return;
|
|
}
|
|
|
|
emit dataAvailable(clientId, targetNamespace, method, data);
|
|
}
|
|
}
|
|
|
|
void CloudManager::onConnectedChanged()
|
|
{
|
|
// Start authentication if connected
|
|
if (m_cloudConnection->connected()) {
|
|
m_interface->authenticateConnection(m_cloudConnection->authenticator()->token());
|
|
} else {
|
|
qCDebug(dcCloud()) << "Disconnected";
|
|
// Reset information
|
|
setAuthenticated(false);
|
|
setActive(false);
|
|
m_connectionId = QUuid();
|
|
|
|
if (m_runningAuthentication) {
|
|
m_runningAuthentication = false;
|
|
emit authenticationFinished(m_cloudConnection->error());
|
|
}
|
|
|
|
// Clean up all tunnels
|
|
foreach (const QUuid &clientId, m_tunnelClients.keys()) {
|
|
emit clientDisconnected(clientId);
|
|
}
|
|
m_tunnelClients.clear();
|
|
|
|
// Delete all replies
|
|
qDeleteAll(m_replies.values());
|
|
m_replies.clear();
|
|
}
|
|
}
|
|
|
|
void CloudManager::onAuthenticatedChanged()
|
|
{
|
|
if (!m_cloudConnection->authenticator()->authenticated()) {
|
|
m_authenticated = false;
|
|
emit authenticatedChanged();
|
|
}
|
|
}
|
|
|
|
}
|