Adding SQLite

This commit is contained in:
stephb9959
2021-03-02 12:36:04 -08:00
parent 2d903bd6a0
commit af7a046b7f
33 changed files with 13851 additions and 549 deletions

View File

@@ -0,0 +1,52 @@
//
// Created by stephane bourque on 2021-03-01.
//
#include "DeviceStatusServer.h"
DeviceStatusServer * DeviceStatusServer::instance_ = nullptr;
DeviceStatusServer::DeviceStatusServer() noexcept:
SubSystemServer("DeviceStatus","DevStatus","devicestatus")
{
}
int DeviceStatusServer::start() {
std::lock_guard<std::mutex> guard(mutex_);
SubSystemServer::logger().information("Starting ");
return 0;
}
void DeviceStatusServer::stop() {
std::lock_guard<std::mutex> guard(mutex_);
SubSystemServer::logger().information("Stopping ");
}
void DeviceStatusServer::Connect(const std::string &SerialNumber, const std::string & address)
{
std::lock_guard<std::mutex> guard(mutex_);
}
void DeviceStatusServer::Disconnect(const std::string &SerialNumber) {
std::lock_guard<std::mutex> guard(mutex_);
}
const std::string DeviceStatusServer::LastStats(const std::string &SerialNumber) {
std::lock_guard<std::mutex> guard(mutex_);
return "";
}
void DeviceStatusServer::SetStats(const std::string &SerialNumber,const std::string &stats) {
std::lock_guard<std::mutex> guard(mutex_);
}

39
src/DeviceStatusServer.h Normal file
View File

@@ -0,0 +1,39 @@
//
// Created by stephane bourque on 2021-03-01.
//
#ifndef UCENTRAL_DEVICESTATUSSERVER_H
#define UCENTRAL_DEVICESTATUSSERVER_H
#include "SubSystemServer.h"
class DeviceStatusServer : public SubSystemServer{
public:
DeviceStatusServer() noexcept;
int start();
void stop();
static DeviceStatusServer *instance() {
if(instance_== nullptr) {
instance_ = new DeviceStatusServer;
}
return instance_;
}
std::string process_message(const char *msg);
void Connect(const std::string &SerialNumber, const std::string & address);
void Disconnect(const std::string &SerialNumber);
const std::string LastStats(const std::string &SerialNumber);
void SetStats(const std::string &SerialNumber,const std::string &stats);
Logger & logger() { return SubSystemServer::logger(); };
private:
static DeviceStatusServer * instance_;
std::mutex mutex_;
};
#endif //UCENTRAL_DEVICESTATUSSERVER_H

View File

@@ -0,0 +1,44 @@
//
// Created by stephane bourque on 2021-02-12.
//
#include <iostream>
#include <fstream>
#include "uCentral.h"
#include "PropertiesFileServerList.h"
void PropertiesFileServerList::initialize() {
auto i=0;
bool good=true;
while(good) {
std::string root{prefix_ + ".host." + std::to_string(i) + "."};
std::string address{root + "address"};
if(uCentral::instance().config().getString(address,"") == "") {
good = false;
}
else {
std::string port{root + "port"};
std::string key{root + "key"};
std::string key_password{root + "key.password"};
std::string cert{root + "cert"};
PropertiesFileServerEntry entry( uCentral::instance().config().getString(address,""),
uCentral::instance().config().getInt(port,0),
uCentral::instance().config().getString(key,""),
uCentral::instance().config().getString(cert,""),
uCentral::instance().config().getString(key_password,""));
list_.push_back(entry);
i++;
}
}
// uCentral::instance().config().
}
const PropertiesFileServerEntry & PropertiesFileServerList::operator[](int index)
{
return list_[index];
}

View File

@@ -0,0 +1,58 @@
//
// Created by stephane bourque on 2021-02-12.
//
#ifndef UCENTRAL_PROPERTIESFILESERVERLIST_H
#define UCENTRAL_PROPERTIESFILESERVERLIST_H
#include <string>
#include <memory>
#include <vector>
#include <iterator>
class PropertiesFileServerEntry {
public:
PropertiesFileServerEntry(const std::string &address,
const uint32_t port,
const std::string &key_file,
const std::string &cert_file,
const std::string &key_file_password = "" ) :
address_(address),
port_(port),
key_file_(key_file),
cert_file_(cert_file),
key_file_password_(key_file_password) {};
const std::string & address() const { return address_; };
const uint32_t port() const { return port_; };
const std::string & key_file() const { return key_file_; };
const std::string & cert_file() const { return cert_file_; };
const std::string & key_file_password() const { return key_file_password_; };
private:
std::string address_;
std::string cert_file_;
std::string key_file_;
std::string key_file_password_;
uint32_t port_;
};
class PropertiesFileServerList {
public:
PropertiesFileServerList(const std::string &prefix):prefix_(prefix) {};
void initialize();
const PropertiesFileServerEntry & operator[](int);
inline std::vector<PropertiesFileServerEntry>::iterator begin() noexcept { return list_.begin(); };
inline std::vector<PropertiesFileServerEntry>::iterator end() noexcept { return list_.end(); };
inline std::vector<PropertiesFileServerEntry>::const_iterator cbegin() const noexcept { return list_.cbegin(); };
inline std::vector<PropertiesFileServerEntry>::const_iterator cend() const noexcept { return list_.cend(); };
const uint32_t size() const { return list_.size(); };
private:
std::string prefix_;
std::vector<PropertiesFileServerEntry> list_;
};
#endif //UCENTRAL_PROPERTIESFILESERVERLIST_H

33
src/SubSystemServer.cpp Normal file
View File

@@ -0,0 +1,33 @@
//
// Created by stephane bourque on 2021-03-01.
//
#include "SubSystemServer.h"
SubSystemServer::SubSystemServer( const std::string &Name,
const std::string & LoggingPrefix,
const std::string & SubSystemConfigPrefix )
: name_(Name),
logger_(Logger::get(LoggingPrefix)),
servers_(SubSystemConfigPrefix)
{}
void SubSystemServer::initialize(Application & self)
{
logger_.information("Initializing...");
servers_.initialize();
}
void SubSystemServer::uninitialize()
{
// add your own uninitialization code here
}
void SubSystemServer::reinitialize(Application & self)
{
// add your own reinitialization code here
}
void SubSystemServer::defineOptions(OptionSet& options)
{
}

50
src/SubSystemServer.h Normal file
View File

@@ -0,0 +1,50 @@
//
// Created by stephane bourque on 2021-03-01.
//
#ifndef UCENTRAL_SUBSYSTEMSERVER_H
#define UCENTRAL_SUBSYSTEMSERVER_H
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/IntValidator.h"
#include "Poco/AutoPtr.h"
#include "Poco/Logger.h"
using Poco::Util::Application;
using Poco::Util::ServerApplication;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
using Poco::Util::IntValidator;
using Poco::AutoPtr;
using Poco::Logger;
#include "PropertiesFileServerList.h"
class SubSystemServer : public Poco::Util::Application::Subsystem {
public:
SubSystemServer(const std::string &name, const std::string & LoggingName, const std::string & SubSystemPrefix );
virtual int start() = 0;
virtual void stop() = 0;
void initialize(Application &self);
void uninitialize();
void reinitialize(Application & self);
void defineOptions(OptionSet &options);
const char *name() const { return name_.c_str(); };
const PropertiesFileServerEntry & host(int index) { return servers_[index]; };
Logger & logger() { return logger_;};
private:
std::string name_;
Logger & logger_;
PropertiesFileServerList servers_;
};
#endif //UCENTRAL_SUBSYSTEMSERVER_H

View File

@@ -5,7 +5,7 @@
#include <string>
#include "Api.h"
#include "../app.h"
#include "../uCentral.h"
#include "Poco//Net/DNS.h"
@@ -14,12 +14,12 @@ namespace TIP::API {
TIP::API::API *TIP::API::API::instance_ = 0;
void API::Init() {
username_ = App::instance().config().getString("tip.api.login.username");
password_ = App::instance().config().getString("tip.api.login.password");
api_host_ = App::instance().config().getString("tip.api.host");
api_port_ = App::instance().config().getInt("tip.api.port");
ssc_host_ = App::instance().config().getString("tip.ssc.host");
ssc_port_ = App::instance().config().getInt("tip.ssc.port");
username_ = uCentral::instance().config().getString("tip.api.login.username");
password_ = uCentral::instance().config().getString("tip.api.login.password");
api_host_ = uCentral::instance().config().getString("tip.api.host");
api_port_ = uCentral::instance().config().getInt("tip.api.port");
ssc_host_ = uCentral::instance().config().getString("tip.gateway.host.0.address");
ssc_port_ = uCentral::instance().config().getInt("tip.gateway.host.0.port");
}
void API::Logout() {
@@ -58,8 +58,16 @@ namespace TIP::API {
TIP::API::API::instance()->Logout();
}
const std::string & SSC_Host() { return TIP::API::API::instance()->ssc_host(); }
uint64_t SSC_Port() { return TIP::API::API::instance()->ssc_port(); }
const std::string & AccessToken() {
return TIP::API::API::instance()->access_token();
};
const std::string & SSC_Host() {
return TIP::API::API::instance()->ssc_host();
}
uint64_t SSC_Port() {
return TIP::API::API::instance()->ssc_port();
}
}

View File

@@ -71,13 +71,27 @@ namespace TIP::API {
bool Login();
void Logout();
void Init();
const std::string & ssc_host() const { return ssc_host_; }
uint64_t ssc_port() const { return ssc_port_; }
const std::string &access_token() const { return token_.access_token(); };
[[nodiscard]] const std::string & ssc_host() const { return ssc_host_; }
[[nodiscard]] uint64_t ssc_port() const { return ssc_port_; }
[[nodiscard]] const std::string &access_token() const { return token_.access_token(); };
[[nodiscard]] const std::string &refresh_token() const { return token_.refresh_token(); };
[[nodiscard]] const std::string &id_token() const { return token_.id_token(); };
[[nodiscard]] const std::string &token_type() const { return token_.token_type(); };
[[nodiscard]] unsigned int expires_in() const { return token_.expires_in(); };
[[nodiscard]] unsigned int idle_timeout() const { return token_.idle_timeout(); };
[[nodiscard]] bool read_access() const { return token_.read_access(); };
[[nodiscard]] bool readWrite_access() const { return token_.readWrite_access(); };
[[nodiscard]] bool readWriteCreate_access() const { return token_.readWriteCreate_access(); };
[[nodiscard]] bool delete_access() const { return token_.delete_access(); };
[[nodiscard]] bool portalLogin_access() const { return token_.portalLogin_access(); };
private:
void Init();
static API *instance_;
std::string api_host_; // TIP portal server name: default to wlan-ui.wlan.local
unsigned int api_port_;
@@ -91,6 +105,7 @@ namespace TIP::API {
bool Login();
void Logout();
const std::string & AccessToken();
const std::string & SSC_Host();
uint64_t SSC_Port();
}

View File

@@ -2,7 +2,7 @@
// Created by stephane bourque on 2021-02-17.
//
#include "EquipmentGatewayRecord.h"
#include "Routing.h"
#include "Poco/JSON/Parser.h"
namespace TIP::Routing {
@@ -39,9 +39,9 @@ namespace TIP::Routing {
bool CreateRoutingGateway(const TIP::Routing::EquipmentGatewayRecord & R) {
Poco::Net::HTTPSClientSession session(TIP::API::SSC_Host(),TIP::API::SSC_Port());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_POST,
std::string("/api/routing/gateway"),
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::JSON::Object obj;
R.to_JSON(obj);
@@ -66,9 +66,10 @@ namespace TIP::Routing {
TIP::Routing::EquipmentGatewayRecord R;
Poco::Net::HTTPSClientSession session(TIP::API::SSC_Host(),TIP::API::SSC_Port());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_DELETE,
std::string("/api/routing/gateway?gatewayId=") + std::to_string(Id),
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_DELETE,
std::string("/api/routing/gateway?gatewayId=")
+ std::to_string(Id),
Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("application/json");
session.sendRequest(request);
@@ -84,9 +85,10 @@ namespace TIP::Routing {
EquipmentGatewayRecord R;
Poco::Net::HTTPSClientSession session(TIP::API::SSC_Host(),TIP::API::SSC_Port());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway?gatewayId=") + std::to_string(Id),
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway?gatewayId=")
+ std::to_string(Id),
Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("application/json");
session.sendRequest(request);
@@ -102,9 +104,10 @@ namespace TIP::Routing {
std::vector<TIP::Routing::EquipmentGatewayRecord> R;
Poco::Net::HTTPSClientSession session(TIP::API::SSC_Host(),TIP::API::SSC_Port());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway/byType?gatewayType=") + Type,
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway/byType?gatewayType=")
+ Type,
Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("application/json");
session.sendRequest(request);
@@ -120,9 +123,10 @@ namespace TIP::Routing {
std::vector<TIP::Routing::EquipmentGatewayRecord> R;
Poco::Net::HTTPSClientSession session(TIP::API::SSC_Host(),TIP::API::SSC_Port());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway/byHostname?hostname=") + host,
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_GET,
std::string("/api/routing/gateway/byHostname?hostname=")
+ host,
Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("application/json");
session.sendRequest(request);
@@ -134,5 +138,52 @@ namespace TIP::Routing {
return R;
}
bool EquipmentRoutingRecord::to_JSON(Poco::JSON::Object &obj) const
{
obj.set("id", id_);
obj.set("equipmentId", equipmentId_);
obj.set("customerId", customerId_);
obj.set("gatewayId", gatewayId_);
return true;
}
bool EquipmentRoutingRecord::from_stream(std::istream &response) {
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr Obj = parser.parse(response).extract<Poco::JSON::Object::Ptr>();
return EquipmentRoutingRecord::from_object(Obj);
}
bool EquipmentRoutingRecord::from_object(Poco::JSON::Object::Ptr Obj) {
Poco::DynamicStruct ds = *Obj;
id_ = ds["id"];
equipmentId_ = ds["equipmentId"];
customerId_ = ds["customerId"];
gatewayId_ = ds["gatewayId"];
createdTimestamp_ = ds["createdTimestamp"];
lastModifiedTimestamp_ = ds["lastModifiedTimestamp"];
return true;
}
bool CreateEquipmentRoutingRecord(const EquipmentRoutingRecord &R) {
return false;
}
bool DeleteEquipmentRoutingRecord(uint64_t id) {
return false;
}
bool UpdateEquipmentRoutingRecord(const EquipmentRoutingRecord &R) {
return false;
}
EquipmentRoutingRecord GetEquipmentRoutingById(uint64_t Id) {
EquipmentRoutingRecord E;
return E;
}
}

View File

@@ -2,8 +2,8 @@
// Created by stephane bourque on 2021-02-17.
//
#ifndef UCENTRAL_EQUIPMENTGATEWAYRECORD_H
#define UCENTRAL_EQUIPMENTGATEWAYRECORD_H
#ifndef UCENTRAL_ROUTING_H
#define UCENTRAL_ROUTING_H
#include "Poco/JSON/Parser.h"
#include "Poco/Net/HTTPSClientSession.h"
@@ -30,7 +30,6 @@ namespace TIP::Routing {
}
bool to_JSON(Poco::JSON::Object &obj) const;
bool from_stream(std::istream &response);
bool from_object(Poco::JSON::Object::Ptr Obj);
@@ -66,6 +65,38 @@ namespace TIP::Routing {
std::vector<TIP::Routing::EquipmentGatewayRecord> GetRoutingGatewaysByHost(const std::string &host);
std::vector<TIP::Routing::EquipmentGatewayRecord> GetRoutingGatewaysByType(const std::string & Type = "CEGW");
class EquipmentRoutingRecord {
public:
[[nodiscard]] uint64_t id() const { return id_; };
[[nodiscard]] uint64_t equipmentId() const { return equipmentId_; };
[[nodiscard]] uint32_t customerId() const { return customerId_; };
[[nodiscard]] uint64_t gatewayId() const { return gatewayId_; };
[[nodiscard]] uint64_t createdTimestamp() const { return createdTimestamp_; };
[[nodiscard]] uint64_t lastModifiedTimestamp() const { return lastModifiedTimestamp_; };
void id(uint64_t v) { id_ = v ; };
void equipmentId(uint64_t v) { equipmentId_ = v ; };
void customerId(uint32_t v) { customerId_ = v; };
void gatewayId(uint64_t v) { gatewayId_ = v; };
bool to_JSON(Poco::JSON::Object &obj) const;
bool from_stream(std::istream &response);
bool from_object(Poco::JSON::Object::Ptr Obj);
private:
uint64_t id_;
uint64_t equipmentId_;
uint32_t customerId_;
uint64_t gatewayId_;
uint64_t createdTimestamp_;
uint64_t lastModifiedTimestamp_;
};
bool CreateEquipmentRoutingRecord(const EquipmentRoutingRecord &R);
bool UpdateEquipmentRoutingRecord(const EquipmentRoutingRecord &R);
bool DeleteEquipmentRoutingRecord(uint64_t id);
EquipmentRoutingRecord GetEquipmentRoutingRecordById(uint64_t id);
}
#endif //UCENTRAL_EQUIPMENTGATEWAYRECORD_H
#endif //UCENTRAL_ROUTING_H

View File

@@ -30,7 +30,18 @@ namespace TIP::WebToken {
public:
bool from_JSON(std::istream &response);
const std::string &access_token() const { return access_token_; };
[[nodiscard]] const std::string &access_token() const { return access_token_; };
[[nodiscard]] const std::string &refresh_token() const { return refresh_token_; };
[[nodiscard]] const std::string &id_token() const { return id_token_; };
[[nodiscard]] const std::string &token_type() const { return token_type_; };
[[nodiscard]] unsigned int expires_in() const { return expires_in_; };
[[nodiscard]] unsigned int idle_timeout() const { return idle_timeout_; };
[[nodiscard]] bool read_access() const { return acl_template_.Read_; };
[[nodiscard]] bool readWrite_access() const { return acl_template_.ReadWrite_; };
[[nodiscard]] bool readWriteCreate_access() const { return acl_template_.ReadWriteCreate_; };
[[nodiscard]] bool delete_access() const { return acl_template_.Delete_; };
[[nodiscard]] bool portalLogin_access() const { return acl_template_.PortalLogin_; };
private:
std::string access_token_;

20
src/TIPGWServer.cpp Normal file
View File

@@ -0,0 +1,20 @@
//
// Created by stephane bourque on 2021-02-12.
//
#include "TIPGWServer.h"
TIPGWServer * TIPGWServer::instance_= nullptr;
TIPGWServer::TIPGWServer() noexcept:
SubSystemServer("TIPGWServer","TIPGWServer","tip.gateway")
{
}
int TIPGWServer::start() {
SubSystemServer::logger().information("Starting.");
return 0;
}
void TIPGWServer::stop() {
SubSystemServer::logger().information("Stopping.");
}

View File

@@ -2,8 +2,10 @@
// Created by stephane bourque on 2021-02-12.
//
#ifndef UCENTRAL_UCENTRALSERVER_H
#define UCENTRAL_UCENTRALSERVER_H
#ifndef UCENTRAL_TIPGWSERVER_H
#define UCENTRAL_TIPGWSERVER_H
#include "PropertiesFileServerList.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
@@ -13,9 +15,7 @@
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/IntValidator.h"
#include "Poco/AutoPtr.h"
#include <iostream>
#include <sstream>
#include "Poco/Logger.h"
using Poco::Util::Application;
using Poco::Util::ServerApplication;
@@ -26,22 +26,30 @@ using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
using Poco::Util::IntValidator;
using Poco::AutoPtr;
using Poco::Logger;
#include "SubSystemServer.h"
class UCentralGW: public Poco::Util::Subsystem
class TIPGWServer: public SubSystemServer
{
public:
UCentralGW();
TIPGWServer() noexcept;
int start();
void stop();
Logger & logger() { return SubSystemServer::logger(); };
static TIPGWServer *instance() {
if(instance_== nullptr) {
instance_ = new TIPGWServer;
}
return instance_;
}
protected:
const char *name() const { return "uCentralGW"; };
void initialize(Application &self);
void uninitialize();
void reinitialize(Application& self);
void defineOptions(OptionSet &options);
private:
bool helpRequested_;
static TIPGWServer *instance_;
};
#endif //UCENTRAL_UCENTRALSERVER_H
#endif //UCENTRAL_TIPGWSERVER_H

View File

@@ -1,231 +0,0 @@
//
// Created by stephane bourque on 2021-02-15.
//
#include "app.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/IntValidator.h"
#include <iostream>
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
using Poco::Util::IntValidator;
using Poco::AutoPtr;
#include "common.h"
#include "ucentralServer.h"
#include "TIP/Api.h"
#include "TIP/EquipmentGatewayRecord.h"
App::App():helpRequested_(false)
{
}
void App::initialize(Application& self)
{
// logging_channel_.assign(new FileChannel);
addSubsystem(new UCentralGW);
loadConfiguration(); // load default configuration files, if present
Application::initialize(self);
// add your own initialization code here
}
void App::uninitialize()
{
// add your own uninitialization code here
Application::uninitialize();
}
void App::reinitialize(Application& self)
{
Application::reinitialize(self);
// add your own reinitialization code here
}
void App::defineOptions(OptionSet& options)
{
Application::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(OptionCallback<App>(this, &App::handleHelp)));
options.addOption(
Option("file", "f", "specify the configuration file")
.required(false)
.repeatable(true)
.argument("file")
.callback(OptionCallback<App>(this, &App::handleConfig)));
options.addOption(
Option("debug", "d", "run in debug mode")
.required(false)
.repeatable(true)
.callback(OptionCallback<App>(this, &App::handleDebug)));
options.addOption(
Option("port", "p", "bind to port")
.required(false)
.repeatable(false)
.argument("value")
.validator(new IntValidator(0,9999))
.callback(OptionCallback<App>(this, &App::handlePort)));
}
void App::handleHelp(const std::string& name, const std::string& value)
{
helpRequested_ = true;
displayHelp();
stopOptionsProcessing();
}
void App::handleDebug(const std::string& name, const std::string& value)
{
defineProperty(value);
}
void App::handlePort(const std::string& name, const std::string& value)
{
defineProperty(value);
}
void App::handleConfig(const std::string& name, const std::string& value)
{
std::cout << "Configuration file name: " << value << std::endl;
loadConfiguration(value);
}
void App::displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A uCentral gateway implementation for TIP.");
helpFormatter.format(std::cout);
}
void App::defineProperty(const std::string& def)
{
std::string name;
std::string value;
std::string::size_type pos = def.find('=');
if (pos != std::string::npos)
{
name.assign(def, 0, pos);
value.assign(def, pos + 1, def.length() - pos);
}
else name = def;
config().setString(name, value);
}
int App::main(const ArgVec& args)
{
if (!helpRequested_)
{
// logging_channel_-> setProperty("path",App::instance().config().getString("logging.path"));
// logging_channel_-> setProperty("rotation",App::instance().config().getString("logging.rotation"));
// logging_channel_-> setProperty("archive", "timestamp");
// AutoPtr<Formatter> Ftr(new AppLogFormatter);
// AutoPtr<FormattingChannel> FC( new FormattingChannel(Ftr,logging_channel_));
// Logger::root().setChannel(FC);
DBG
Logger& logger = Logger::get("App");
logger.information("Command line:");
std::ostringstream ostr;
for(auto &it: args)
{
// ostr << it << ' ';
}
logger.information(ostr.str());
logger.information("Arguments to main():");
for(auto &it: args)
{
// logger().information(it);
}
logger.information("Application properties:");
printProperties("");
std::cout << "1st login" << std::endl;
TIP::API::Login();
std::vector<TIP::Routing::EquipmentGatewayRecord> gateways;
for(auto i: gateways)
{
std::cout << "Gateway: " << i.id() << std::endl;
}
gateways = TIP::Routing::GetRoutingGatewaysByType();
for(auto i: gateways)
{
std::cout << "ID: " << i.id() << "@" << i.hostname() << std::endl;
}
std::cout << "ID: " << gateways[0].id() << std::endl;
TIP::Routing::EquipmentGatewayRecord E = TIP::Routing::GetRoutingGateway(1691801527873612933);
std::cout << "Hostname: " << E.hostname() << std::endl;
gateways = TIP::Routing::GetRoutingGatewaysByHost("10.1.124.61");
std::cout << "ID: " << gateways[0].id() << std::endl;
TIP::Routing::EquipmentGatewayRecord rr = gateways[0];
rr.hostname("10.3.111.3");
rr.ipAddr("10.3.111.3");
rr.port( 9911);
TIP::Routing::CreateRoutingGateway(rr);
gateways = TIP::Routing::GetRoutingGatewaysByHost("10.3.111.3");
std::cout << "ID: " << gateways[0].id() << " Host: " << gateways[0].hostname() << std::endl;
TIP::Routing::DeleteRoutingGateway(gateways[0].id());
}
return Application::EXIT_OK;
}
void App::printProperties(const std::string& base)
{
AbstractConfiguration::Keys keys;
config().keys(base, keys);
if (keys.empty())
{
if (config().hasProperty(base))
{
std::string msg;
msg.append(base);
msg.append(" = ");
msg.append(config().getString(base));
logger().information(msg);
}
}
else
{
for(auto &it: keys)
{
std::string fullKey = base;
if (!fullKey.empty()) fullKey += '.';
fullKey.append(it);
printProperties(fullKey);
}
}
}

View File

@@ -1,27 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
#include <iostream>
#include <memory>
#include <fstream>
#include <string>
#include <vector>
#include "yaml-cpp/yaml.h"
#include "config.h"
uConfig::Config *uConfig::Config::instance_ = 0;
bool uConfig::Config::init(const char *filename) {
filename_ = filename;
cfg_ = std::make_shared<YAML::Node>(YAML::LoadFile(filename_));
return true;
}
bool uConfig::init(const char *filename) {
return uConfig::Config::instance()->init(filename);
}

View File

@@ -1,45 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
#ifndef UCENTRAL_CONFIG_H
#define UCENTRAL_CONFIG_H
#include <string>
#include <memory>
#include "yaml-cpp/yaml.h"
namespace uConfig {
bool init(const char * filename);
class Config {
public:
Config() {
}
bool init(const char *filename);
auto get(const char *node_name, const char *sub_node) { return (*cfg_)[node_name][sub_node]; }
template<typename T> T get(const char *node_name, const char *sub_node) { return (*cfg_)[node_name][sub_node].as<T>(); }
static Config *instance() {
if(!instance_)
instance_ = new Config;
return instance_;
}
private:
static Config *instance_;
std::string filename_;
std::shared_ptr<YAML::Node> cfg_;
};
template<typename T> T get(const char *node_name, const char *sub_node)
{
return uConfig::Config::instance()->get<T>(node_name,sub_node);
}
}
#endif //UCENTRAL_CONFIG_H

View File

@@ -1,8 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
// This is the implementation of the tipapi/gw/equipment-gateway-service-openapi.yaml
#include "gateway.h"

View File

@@ -1,8 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
#ifndef UCENTRAL_GATEWAY_H
#define UCENTRAL_GATEWAY_H
#endif //UCENTRAL_GATEWAY_H

View File

@@ -1,5 +1,5 @@
#include <iostream>
#include "app.h"
#include "uCentral.h"
POCO_APP_MAIN(App)
POCO_SERVER_MAIN(uCentral)

9
src/openapi_local_defs.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef OPEN_API_LOCAL_DEFS_H
#define OPEN_API_LOCAL_DEFS_H
typedef std::string FullDateRFC3339;
typedef std::string BinaryString;
typedef std::string Base64String;
typedef std::string DateTimeRFC3339;
#endif

File diff suppressed because it is too large Load Diff

11375
src/portal-services-openapi.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
#include <string>
#include "tipApi.h"
#include "app.h"
void TIPAPI::init() {
initialized_ = true ;
key_filename_ = App::instance().config().getString("tip.key_filename") ;
cert_filename_ = App::instance().config().getString("tip.cert_filename");
cacert_filename_ = App::instance().config().getString("tip.cacert_filename");
key_filename_password_ = App::instance().config().getString("tip.key_password");
Poco::Net::SSLManager::instance().initializeClient(new MyPassPhraseHandler, 0, 0);
ctx_ptr_ = new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE,
key_filename_,
cert_filename_,
cacert_filename_,
Poco::Net::Context::VERIFY_NONE);
Poco::Net::SSLManager::instance().initializeClient(new MyPassPhraseHandler, new MyInvalidCertificateHandler, ctx_ptr_);
}
bool TIPAPI::login() {
if(!initialized_)
init();
Poco::Net::HTTPSClientSession session( App::instance().config().getString("tipapi.host"),
App::instance().config().getInt("tipapi.port"), ctx_ptr_);
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/management/v1/oauth2/token", Poco::Net::HTTPMessage::HTTP_1_1);
request.setContentType("application/json");
Poco::JSON::Object obj;
obj.set("userId", App::instance().config().getString("tiplogin.username"));
obj.set("password", App::instance().config().getString("tiplogin.password"));
std::stringstream ss;
obj.stringify(ss);
request.setContentLength(ss.str().size());
std::ostream& o = session.sendRequest(request);
obj.stringify(o);
Poco::Net::HTTPResponse response;
std::istream& s = session.receiveResponse(response);
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr ret = parser.parse(s).extract<Poco::JSON::Object::Ptr>();
access_token_ = ret->get("access_token").toString();
std::cout << "ACCESS_TOKEN: " << access_token_ << std::endl;
return true;
}

View File

@@ -1,87 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
// This implements the various calls to the tipController
#ifndef UCENTRAL_TIPAPI_H
#define UCENTRAL_TIPAPI_H
#include <string>
#include "Poco/JSON/JSON.h"
#include "Poco/JSON/Object.h"
#include "Poco/URI.h"
#include "Poco/JSON/Parser.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/NetSSL.h"
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Net/KeyFileHandler.h"
#include "Poco/Net/InvalidCertificateHandler.h"
#include "common.h"
class MyPassPhraseHandler : public Poco::Net::KeyFileHandler {
public:
MyPassPhraseHandler()
:Poco::Net::KeyFileHandler(false){
};
~MyPassPhraseHandler() {};
void onPrivateKeyRequested( const void * pSender, std::string & privateKey ) {
std::cout << "Private key: " << privateKey << std::endl;
privateKey = "mypassword";
}
private:
};
class MyInvalidCertificateHandler : public Poco::Net::InvalidCertificateHandler
{
public:
MyInvalidCertificateHandler() : Poco::Net::InvalidCertificateHandler(false) {};
~MyInvalidCertificateHandler() {};
void onInvalidCertificate(const void * pSender,Poco::Net::VerificationErrorArgs & errorCert)
{
std::cout << "CERT: ignoring cert." << std::endl;
errorCert.setIgnoreError(true);
}
private:
};
class TIPAPI {
public:
TIPAPI():initialized_(false) {
}
~TIPAPI() {
if(initialized_)
Poco::Net::SSLManager::instance().shutdown();
}
bool login();
void init();
private:
bool initialized_;
std::string portal_host_; // TIP portal server name: default to wlan-ui.wlan.local
std::string username_; // TIP user name: default to "support@example.com"
std::string password_; // TIP user password: default to "support"
unsigned int tip_port_; // TIP portal management port: default to 9051
std::string access_token_; // Token obtained during login
std::string key_filename_;
std::string cert_filename_;
std::string cacert_filename_;
std::string key_filename_password_;
bool use_ssl_;
Poco::Net::Context * ctx_ptr_;
};
#endif //UCENTRAL_TIPAPI_H

164
src/uCentral.cpp Normal file
View File

@@ -0,0 +1,164 @@
//
// Created by stephane bourque on 2021-02-15.
//
#include "uCentral.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/IntValidator.h"
#include <iostream>
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
using Poco::Util::IntValidator;
using Poco::AutoPtr;
#include "TIPGWServer.h"
#include "uCentralRESTAPIServer.h"
#include "uCentralWebSocketServer.h"
#include "uStorageService.h"
#include "DeviceStatusServer.h"
#include "TIP/Api.h"
#include "TIP/Routing.h"
uCentral::uCentral():helpRequested_(false)
{
}
void uCentral::initialize(Application& self)
{
// logging_channel_.assign(new FileChannel);
loadConfiguration(); // load default configuration files, if present
addSubsystem(TIPGWServer::instance());
addSubsystem(uCentralRESTAPIServer::instance());
addSubsystem(uCentralWebSocketServer::instance());
addSubsystem(uStorageService::instance());
ServerApplication::initialize(self);
logger().information("Starting...");
// add your own initialization code here
}
void uCentral::uninitialize()
{
// add your own uninitialization code here
Application::uninitialize();
}
void uCentral::reinitialize(Application& self)
{
Application::reinitialize(self);
// add your own reinitialization code here
}
void uCentral::defineOptions(OptionSet& options)
{
Application::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(OptionCallback<uCentral>(this, &uCentral::handleHelp)));
options.addOption(
Option("file", "f", "specify the configuration file")
.required(false)
.repeatable(true)
.argument("file")
.callback(OptionCallback<uCentral>(this, &uCentral::handleConfig)));
options.addOption(
Option("debug", "d", "run in debug mode")
.required(false)
.repeatable(true)
.callback(OptionCallback<uCentral>(this, &uCentral::handleDebug)));
options.addOption(
Option("port", "p", "bind to port")
.required(false)
.repeatable(false)
.argument("value")
.validator(new IntValidator(0,9999))
.callback(OptionCallback<uCentral>(this, &uCentral::handlePort)));
}
void uCentral::handleHelp(const std::string& name, const std::string& value)
{
helpRequested_ = true;
displayHelp();
stopOptionsProcessing();
}
void uCentral::handleDebug(const std::string& name, const std::string& value)
{
defineProperty(value);
}
void uCentral::handlePort(const std::string& name, const std::string& value)
{
defineProperty(value);
}
void uCentral::handleConfig(const std::string& name, const std::string& value)
{
std::cout << "Configuration file name: " << value << std::endl;
loadConfiguration(value);
}
void uCentral::displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A uCentral gateway implementation for TIP.");
helpFormatter.format(std::cout);
}
void uCentral::defineProperty(const std::string& def)
{
std::string name;
std::string value;
std::string::size_type pos = def.find('=');
if (pos != std::string::npos)
{
name.assign(def, 0, pos);
value.assign(def, pos + 1, def.length() - pos);
}
else name = def;
config().setString(name, value);
}
int uCentral::main(const ArgVec& args)
{
if (!helpRequested_)
{
Logger& logger = Logger::get("App");
uStorageService::instance()->start();
DeviceStatusServer::instance()->start();
TIPGWServer::instance()->start();
uCentralRESTAPIServer::instance()->start();
uCentralWebSocketServer::instance()->start();
waitForTerminationRequest();
TIPGWServer::instance()->stop();
uCentralRESTAPIServer::instance()->stop();
uCentralWebSocketServer::instance()->stop();
DeviceStatusServer::instance()->stop();
uStorageService::instance()->stop();
}
return Application::EXIT_OK;
}

View File

@@ -2,10 +2,10 @@
// Created by stephane bourque on 2021-02-15.
//
#ifndef UCENTRAL_APP_H
#define UCENTRAL_APP_H
#ifndef UCENTRAL_UCENTRAL_H
#define UCENTRAL_UCENTRAL_H
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
@@ -18,11 +18,12 @@
#include "Poco/FormattingChannel.h"
#include "Poco/Formatter.h"
#include "Poco/Message.h"
#include "Poco/Data/Session.h"
#include "Poco/Data/SQLite/Connector.h"
#include <iostream>
#include <sstream>
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
@@ -38,6 +39,10 @@ using Poco::FileChannel;
using Poco::AutoPtr;
using Poco::Message;
#include "TIPGWServer.h"
#include "uCentralWebSocketServer.h"
#include "uCentralRESTAPIServer.h"
class AppLogFormatter : public Formatter {
public:
void format(const Message &msg, std::string & text )
@@ -46,10 +51,11 @@ public:
}
private:
};
class App: public Application
class uCentral: public Poco::Util::ServerApplication
{
public:
App();
uCentral();
protected:
void initialize(Application& self);
@@ -71,4 +77,4 @@ private:
};
#endif //UCENTRAL_APP_H
#endif //UCENTRAL_UCENTRAL_H

View File

@@ -0,0 +1,24 @@
//
// Created by stephane bourque on 2021-02-28.
//
#include "uCentralRESTAPIServer.h"
uCentralRESTAPIServer * uCentralRESTAPIServer::instance_ = nullptr;
uCentralRESTAPIServer::uCentralRESTAPIServer() noexcept:
SubSystemServer("RESTAPIServer","RESTAPIServer","ucentral.restapi")
{
}
int uCentralRESTAPIServer::start() {
SubSystemServer::logger().information("Starting ");
return 0;
}
void uCentralRESTAPIServer::stop() {
SubSystemServer::logger().information("Stopping ");
}

View File

@@ -0,0 +1,32 @@
//
// Created by stephane bourque on 2021-02-28.
//
#ifndef UCENTRAL_UCENTRALRESTAPISERVER_H
#define UCENTRAL_UCENTRALRESTAPISERVER_H
#include "SubSystemServer.h"
class uCentralRESTAPIServer : public SubSystemServer {
public:
uCentralRESTAPIServer() noexcept;
int start();
void stop();
Logger & logger() { return SubSystemServer::logger(); };
static uCentralRESTAPIServer *instance() {
if(instance_== nullptr) {
instance_ = new uCentralRESTAPIServer;
}
return instance_;
}
private:
static uCentralRESTAPIServer * instance_;
};
#endif //UCENTRAL_UCENTRALRESTAPISERVER_H

View File

@@ -0,0 +1,229 @@
//
// Created by stephane bourque on 2021-02-28.
//
#include "uCentralWebSocketServer.h"
#include "uStorageService.h"
uCentralWebSocketServer * uCentralWebSocketServer::instance_= nullptr;
uCentralWebSocketServer::uCentralWebSocketServer() noexcept:
SubSystemServer("WebSocketServer","WebSocketServer","ucentral.websocket")
{
}
int uCentralWebSocketServer::start() {
// SubSystemServer::logger().information
std::string l{"Starting: " +
SubSystemServer::host(0).address() + ":" + std::to_string(SubSystemServer::host(0).port()) +
" key:" + SubSystemServer::host(0).key_file() + " cert:" + SubSystemServer::host(0).cert_file()};
std::cout << "LOGGING: " << l << std::endl;
SecureServerSocket sock( SubSystemServer::host(0).port(),
64,
new Context(Poco::Net::Context::TLS_SERVER_USE,
SubSystemServer::host(0).key_file(),
SubSystemServer::host(0).cert_file(),
""));
server_ = new HTTPServer( new RequestHandlerFactory, sock, new HTTPServerParams);
server_->start();
return 0;
}
void uCentralWebSocketServer::stop() {
SubSystemServer::logger().information("Stopping ");
server_->stop();
}
std::string default_config() {
return std::string{"{\"cfg\": {\"uuid\":1613927736,\"steer\":{\"enabled\":1,\"network\":\"wan\",\"debug_level\":0},\"stats\":{\"interval\":60,\"neighbours\":1,\"traffic\":1,\"wifiiface\":1,\"wifistation\":1,\"pids\":1,\"serviceprobe\":1,\"lldp\":1,\"system\":1,\"poe\":1},\"phy\":[{\"band\":\"2\",\"cfg\":{\"disabled\":0,\"country\":\"DE\",\"channel\":6,\"txpower\":30,\"beacon_int\":100,\"htmode\":\"HE40\",\"hwmode\":\"11g\",\"chanbw\":20}},{\"band\":\"5\",\"cfg\":{\"mimo\":\"4x4\",\"disabled\":0,\"country\":\"DE\",\"channel\":0,\"htmode\":\"HE80\"}},{\"band\":\"5u\",\"cfg\":{\"disabled\":0,\"country\":\"DE\",\"channel\":100,\"htmode\":\"VHT80\"}},{\"band\":\"5l\",\"cfg\":{\"disabled\":0,\"country\":\"DE\",\"channel\":36,\"htmode\":\"VHT80\"}}],\"ssid\":[{\"band\":[\"2\"],\"cfg\":{\"ssid\":\"uCentral-Guest\",\"encryption\":\"psk2\",\"key\":\"OpenWifi\",\"mode\":\"ap\",\"isolate\":1,\"network\":\"guest\",\"ieee80211r\":1,\"ieee80211v\":1,\"ieee80211k\":1,\"ft_psk_generate_local\":1,\"ft_over_ds\":1,\"mobility_domain\":\"4f57\"}},{\"band\":[\"5l\",\"5\"],\"cfg\":{\"ssid\":\"uCentral-NAT.200\",\"encryption\":\"psk2\",\"key\":\"OpenWifi\",\"mode\":\"ap\",\"network\":\"nat200\",\"ieee80211r\":1,\"ieee80211v\":1,\"ieee80211k\":1,\"ft_psk_generate_local\":1,\"ft_over_ds\":1,\"mobility_domain\":\"4f51\"}},{\"band\":[\"5l\",\"5\"],\"cfg\":{\"ssid\":\"uCentral-EAP\",\"encryption\":\"wpa2\",\"server\":\"148.251.188.218\",\"port\":1812,\"auth_secret\":\"uSyncRad1u5\",\"mode\":\"ap\",\"network\":\"lan\",\"ieee80211r\":1,\"ieee80211v\":1,\"ieee80211k\":1,\"ft_psk_generate_local\":1,\"ft_over_ds\":1,\"mobility_domain\":\"4f51\"}},{\"band\":[\"5l\",\"5\"],\"cfg\":{\"ssid\":\"uCentral\",\"encryption\":\"psk2\",\"key\":\"OpenWifi\",\"mode\":\"ap\",\"network\":\"wan\",\"ieee80211r\":1,\"ieee80211v\":1,\"ieee80211k\":1,\"ft_psk_generate_local\":1,\"ft_over_ds\":1,\"mobility_domain\":\"4f51\"}}],\"network\":[{\"mode\":\"wan\",\"cfg\":{\"proto\":\"dhcp\"}},{\"mode\":\"gre\",\"cfg\":{\"vid\":\"50\",\"peeraddr\":\"50.210.104.108\"}},{\"mode\":\"nat\",\"vlan\":200,\"cfg\":{\"proto\":\"static\",\"ipaddr\":\"192.168.16.1\",\"netmask\":\"255.255.255.0\",\"mtu\":1500,\"ip6assign\":60,\"dhcp\":{\"start\":10,\"limit\":100,\"leasetime\":\"6h\"},\"leases\":[{\"ip\":\"192.168.100.2\",\"mac\":\"00:11:22:33:44:55\",\"hostname\":\"test\"},{\"ip\":\"192.168.100.3\",\"mac\":\"00:11:22:33:44:56\",\"hostname\":\"test2\"}]}},{\"mode\":\"guest\",\"cfg\":{\"proto\":\"static\",\"ipaddr\":\"192.168.12.11\",\"dhcp\":{\"start\":10,\"limit\":100,\"leasetime\":\"6h\"}}}],\"ntp\":{\"enabled\":1,\"enable_server\":1,\"server\":[\"0.openwrt.pool.ntp.org\",\"1.openwrt.pool.ntp.org\"]},\"ssh\":{\"enable\":1,\"Port\":22},\"system\":{\"timezone\":\"CET-1CEST,M3.5.0,M10.5.0/3\"},\"log\":{\"_log_proto\":\"udp\",\"_log_ip\":\"192.168.11.23\",\"_log_port\":12345,\"_log_hostname\":\"foo\",\"_log_size\":128},\"rtty\":{\"host\":\"websocket.usync.org\",\"token\":\"7049cb6b7949ba06c6b356d76f0f6275\",\"interface\":\"wan\"}}}"};
}
std::string uCentralWebSocketServer::process_message(const std::string &m, ConnectionState &conn)
{
Parser parser;
Poco::Dynamic::Var result = parser.parse(m);
Poco::JSON::Object::Ptr object = result.extract<Poco::JSON::Object::Ptr>();
Poco::DynamicStruct ds = *object;
std::string SerialNumber = ds["serial"].toString();
std::cout << "SERIAL: " << SerialNumber << std::endl;
conn.SerialNumber = SerialNumber;
if(ds.contains("state") && ds.contains("serial"))
{
logger().information(SerialNumber + ": updating statistics.");
std::cout << "STATE_MSG 1 " << std::endl ;
std::string NewStatistics{ds["state"].toString()};
uStorageService::instance()->AddStatisticsData(conn.SerialNumber,conn.CfgUUID,NewStatistics);
std::cout << "STATE_MSG 2 " << std::endl ;
}
else if(ds.contains("capab") && ds.contains("serial"))
{
logger().information(SerialNumber + ": updating capabilities.");
conn.SerialNumber = ds["serial"].toString();
std::string NewCapabilities{ds["capab"].toString()};
uStorageService::instance()->UpdateDeviceCapabilities(conn.SerialNumber,NewCapabilities);
}
else if(ds.contains("uuid") && ds.contains("serial") && ds.contains("active")) {
conn.CfgUUID = ds["uuid"];
std::cout << "UUID of config" << ds["uuid"].toString() << std::endl;
return default_config();
}
else if(ds.contains("uuid") && ds.contains("serial")) {
conn.CfgUUID = ds["uuid"];
std::cout << "UUID of config" << ds["uuid"].toString() << std::endl;
return default_config();
}
else if(ds.contains("log")) {
std::string log = ds["log"].toString();
logger().warning("DEVICE-LOG(" + SerialNumber + "):" + log);
}
else
{
std::cout << "UNKNOWN_MESSAGE: " << m << std::endl;
}
return "";
}
void PageRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
std::ostream& ostr = response.send();
ostr << "<html>";
ostr << "<head>";
ostr << "<title>WebSocketServer</title>";
ostr << "<script type=\"text/javascript\">";
ostr << "function WebSocketTest()";
ostr << "{";
ostr << " if (\"WebSocket\" in window)";
ostr << " {";
ostr << " var ws = new WebSocket(\"ws://" << request.serverAddress().toString() << "/ws\");";
ostr << " ws.onopen = function()";
ostr << " {";
ostr << " ws.send(\"Hello, world!\");";
ostr << " };";
ostr << " ws.onmessage = function(evt)";
ostr << " { ";
ostr << " var msg = evt.data;";
ostr << " alert(\"Message received: \" + msg);";
ostr << " ws.close();";
ostr << " };";
ostr << " ws.onclose = function()";
ostr << " { ";
ostr << " alert(\"WebSocket closed.\");";
ostr << " };";
ostr << " }";
ostr << " else";
ostr << " {";
ostr << " alert(\"This browser does not support WebSockets.\");";
ostr << " }";
ostr << "}";
ostr << "</script>";
ostr << "</head>";
ostr << "<body>";
ostr << " <h1>WebSocket Server</h1>";
ostr << " <p><a href=\"javascript:WebSocketTest()\">Run WebSocket Script</a></p>";
ostr << "</body>";
ostr << "</html>";
}
void WebSocketRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
Application& app = Application::instance();
try
{
WebSocket ws(request, response);
std::string Address{ws.peerAddress().toString()};
std::cout << "Connection from: " << Address << std::endl;
ConnectionState conn{ .SerialNumber{""},
.Address{Address},
.messages=0,
.CfgUUID=0,
.RX=0,
.TX=0};
uCentralWebSocketServer::instance()->logger().information("WebSocket connection established from .");
char buffer[32000];
int flags;
int n;
do
{
ws.peerAddress().toString();
memset(buffer,0,sizeof(buffer));
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
conn.messages++;
uCentralWebSocketServer::instance()->logger().information(Poco::format("Frame received (length=%d, flags=0x%x).", n, unsigned(flags)));
std::string m{buffer};
conn.RX += m.size();
std::string return_document = uCentralWebSocketServer::instance()->process_message(m,conn);
conn.TX += return_document.size();
if( !return_document.empty()) {
// std::cout << "RETURN:" << return_document << std::endl;
ws.sendFrame(return_document.c_str(), return_document.size(), flags);
}
}
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
std::cout << "ENDING CONNECTION..." << std::endl;
uCentralWebSocketServer::instance()->logger().information("WebSocket connection closed.");
}
catch (WebSocketException& exc)
{
uCentralWebSocketServer::instance()->logger().log(exc);
switch (exc.code())
{
case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
response.set("Sec-WebSocket-Version", WebSocket::WEBSOCKET_VERSION);
// fallthrough
case WebSocket::WS_ERR_NO_HANDSHAKE:
case WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
response.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
response.setContentLength(0);
response.send();
break;
}
}
}
HTTPRequestHandler* RequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request)
{
uCentralWebSocketServer::instance()->logger().information("Request from "
+ request.clientAddress().toString()
+ ": "
+ request.getMethod()
+ " "
+ request.getURI()
+ " "
+ request.getVersion());
for (HTTPServerRequest::ConstIterator it = request.begin(); it != request.end(); ++it)
{
uCentralWebSocketServer::instance()->logger().information(it->first + ": " + it->second);
}
if(request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
return new WebSocketRequestHandler;
else
return new PageRequestHandler;
}

View File

@@ -0,0 +1,93 @@
//
// Created by stephane bourque on 2021-02-28.
//
#ifndef UCENTRAL_UCENTRALWEBSOCKETSERVER_H
#define UCENTRAL_UCENTRALWEBSOCKETSERVER_H
#include "SubSystemServer.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/Context.h"
#include "Poco/JSON/Parser.h"
#include "Poco/DynamicAny.h"
using Poco::Net::ServerSocket;
using Poco::Net::SecureServerSocket;
using Poco::Net::WebSocket;
using Poco::Net::Context;
using Poco::Net::WebSocketException;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::JSON::Parser;
struct ConnectionState {
uint64_t messages;
std::string SerialNumber;
std::string Address;
uint64_t CfgUUID;
uint64_t TX, RX;
};
class uCentralWebSocketServer : public SubSystemServer {
public:
uCentralWebSocketServer() noexcept;
int start();
void stop();
static uCentralWebSocketServer *instance() {
if(instance_== nullptr) {
instance_ = new uCentralWebSocketServer;
}
return instance_;
}
std::string process_message(const std::string &message, ConnectionState &conn);
Logger & logger() { return SubSystemServer::logger(); };
private:
static uCentralWebSocketServer * instance_;
HTTPServer * server_;
};
class PageRequestHandler: public HTTPRequestHandler
/// Return a HTML document with some JavaScript creating
/// a WebSocket connection.
{
public:
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response);
};
class WebSocketRequestHandler: public HTTPRequestHandler
/// Handle a WebSocket connection.
{
public:
void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response);
};
class RequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request);
};
#endif //UCENTRAL_UCENTRALWEBSOCKETSERVER_H

192
src/uStorageService.cpp Normal file
View File

@@ -0,0 +1,192 @@
//
// Created by stephane bourque on 2021-03-01.
//
#include "uStorageService.h"
#include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/DateTime.h"
#include "uCentral.h"
using namespace Poco::Data::Keywords;
using Poco::Data::Session;
using Poco::Data::Statement;
using Poco::Data::RecordSet;
uStorageService * uStorageService::instance_= nullptr;
uStorageService::uStorageService() noexcept:
SubSystemServer("Storage","storage","storage")
{
}
int uStorageService::start() {
SubSystemServer::logger().information("Starting.");
Poco::Data::SQLite::Connector::registerConnector();
std::string TableLocation = uCentral::instance().config().getString("sqlite.location") + "/devices.db";
session_ = std::shared_ptr<Poco::Data::Session>(new Poco::Data::Session("SQLite",TableLocation));
*session_ << "CREATE TABLE IF NOT EXISTS Statistics (SerialNumber VARCHAR(30), CfgUUID INTEGER, Stats BLOB, Recorded DATETIME)", now;
*session_ << "CREATE INDEX IF NOT EXISTS serial ON Statistics (SerialNumber ASC, Recorded ASC)", now;
*session_ << "CREATE TABLE IF NOT EXISTS Devices (SerialNumber VARCHAR(30) UNIQUE PRIMARY KEY, MAC VARCHAR(30), CfgUUID INTEGER, Configuration BLOB, Created DATETIME, Updated DATETIME, LastDownloaded DATETIME ) WITHOUT ROWID" , now ;
*session_ << "CREATE TABLE IF NOT EXISTS Capabilities (SerialNumber VARCHAR(30) PRIMARY KEY, Capabilities BLOB, Created DATETIME, Updated DATETIME) WITHOUT ROWID" , now ;
Poco::Data::SQLite::Connector::registerConnector();
return 0;
}
void uStorageService::stop() {
SubSystemServer::logger().information("Stopping.");
}
bool uStorageService::AddStatisticsData(std::string &SerialNumber, uint64_t CfgUUID, std::string &NewStats)
{
std::lock_guard<std::mutex> guard(mutex_);
Poco::DateTime Now;
*session_ << "INSERT INTO Statistics VALUES(?, ?, ?, ?)",
use(SerialNumber),
use(CfgUUID),
use(NewStats),
use(Now), now;
return true;
}
bool uStorageService::GetStatisticsData(std::string &SerialNumber, uint32_t From, uint32_t To, std::vector<uCentralStatistics> &Stats)
{
return false;
}
bool uStorageService::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration ){
std::lock_guard<std::mutex> guard(mutex_);
return false;
}
bool uStorageService::CreateDevice(uCentralDevice & DeviceDetails){
std::lock_guard<std::mutex> guard(mutex_);
std::string SerialNumber;
*session_ << "SELECT SerialNumber FROM Devices WHERE SerialNumber=?" ,
into(SerialNumber),
use(DeviceDetails.SerialNumber), now;
if(SerialNumber.empty())
{
*session_ << "INSERT INTO Devices VALUES(?, ?, ?, ?, ?, ?, ?)",
use(DeviceDetails.SerialNumber),
use(DeviceDetails.MAC),
use(DeviceDetails.UUID),
use(DeviceDetails.Configuration),
use(DeviceDetails.CreationTimestamp),
use(DeviceDetails.ModifiedTimestamp),
use(DeviceDetails.LastDownloadTimeStamp), now;
return true;
}
return false;
}
bool uStorageService::DeleteDevice(std::string &SerialNumber){
std::lock_guard<std::mutex> guard(mutex_);
*session_ << "DELETE FROM Devices WHERE SerialNumber=?",
use(SerialNumber), now;
return true;
}
bool uStorageService::GetDevice(std::string &SerialNUmber, uCentralDevice &DeviceDetails)
{
std::lock_guard<std::mutex> guard(mutex_);
*session_ << "SELECT SerialNumber, MAC, CfgUUID, Configuration, Created, Updated, LastDownloaded FROM Devices WHERE SerialNumber=?" ,
into(DeviceDetails.SerialNumber),
into(DeviceDetails.MAC),
into(DeviceDetails.UUID),
into(DeviceDetails.Configuration),
into(DeviceDetails.CreationTimestamp),
into(DeviceDetails.ModifiedTimestamp),
into(DeviceDetails.LastDownloadTimeStamp),
use(SerialNUmber), now;
if(DeviceDetails.SerialNumber.empty())
return false;
return true;
}
bool uStorageService::UpdateDeviceCapabilities(std::string &SerialNumber, std::string &Capabs)
{
std::lock_guard<std::mutex> guard(mutex_);
std::string SS;
*session_ << "SELECT SerialNumber FROM Capabilities WHERE SerialNumber=?" , into(SS), use(SerialNumber),now ;
Poco::DateTime Now;
if(SS.empty()) {
std::cout << "Adding capabilities for " << SerialNumber << std::endl;
*session_ << "INSERT INTO Capabilities VALUES(?, ?, ?, ?)" ,
use(SerialNumber),
use(Capabs),
use(Now),
use(Now), now;
std::cout << "Done adding capabilities for " << SerialNumber << std::endl;
}
else {
std::cout << "Updating capabilities for " << SerialNumber << std::endl;
*session_ << "UPDATE Capabilities SET Capabilities=?, Updated=? WHERE SerialNumber=?" ,
use(Capabs),
use(Now),
use(SerialNumber), now;
std::cout << "Done updating capabilities for " << SerialNumber << std::endl;
}
return true;
}
bool uStorageService::GetDeviceCapabilities(std::string &SerialNUmber, uCentralCapabilities & Caps)
{
*session_ << "SELECT SerialNumber, Capabilities, Created, Updated FROM Capabilities WHERE SerialNumber=?" ,
into(Caps.SerialNumber),
into(Caps.Caps),
into(Caps.CreationTimestamp),
into(Caps.LastUpdatedTimestamp),
use(SerialNUmber), now;
if(Caps.SerialNumber.empty())
return false;
return true;
}
bool uStorageService::NewerConfiguration(std::string &SerialNumber, uint64_t CurrentConfig, std::string &NewConfig, uint64_t & UUID){
std::lock_guard<std::mutex> guard(mutex_);
std::string SS;
*session_ << "SELECT SerialNumber, CfgUUID, Configuration FROM Capabilities WHERE SerialNumber=?" ,
into(SS),
into(UUID),
into(NewConfig),
use(SerialNumber),now ;
if(SS.empty() || CurrentConfig >= UUID)
return false;
return true;
}

74
src/uStorageService.h Normal file
View File

@@ -0,0 +1,74 @@
//
// Created by stephane bourque on 2021-03-01.
//
#ifndef UCENTRAL_USTORAGESERVICE_H
#define UCENTRAL_USTORAGESERVICE_H
#include "SubSystemServer.h"
#include "Poco/Data/Session.h"
#include "Poco/Data/SQLite/SQLite.h"
struct uCentralDevice {
std::string SerialNumber;
std::string MAC;
uint64_t UUID;
std::string Configuration;
uint64_t CreationTimestamp;
uint64_t ModifiedTimestamp;
uint64_t LastDownloadTimeStamp;
};
struct uCentralStatistics {
std::string SerialNumber;
uint64_t UUID;
std::string StatsRecord;
uint64_t CreationTimestamp;
};
struct uCentralCapabilities {
std::string SerialNumber;
std::string Caps;
uint64_t CreationTimestamp;
uint64_t LastUpdatedTimestamp;
};
class uStorageService : public SubSystemServer {
public:
uStorageService() noexcept;
int start();
void stop();
Logger & logger() { return SubSystemServer::logger(); };
bool AddStatisticsData(std::string &SerialNUmber, uint64_t CfgUUID, std::string &NewStats);
bool GetStatisticsData(std::string &SerialNUmber, uint32_t From, uint32_t To, std::vector<uCentralStatistics> &Stats);
bool UpdateDeviceConfiguration(std::string &SerialNUmber, std::string &Configuration );
bool CreateDevice(uCentralDevice &);
bool GetDevice(std::string &SerialNUmber, uCentralDevice & );
bool DeleteDevice(std::string &SerialNUmber);
bool UpdateDevice(uCentralDevice &);
bool NewerConfiguration(std::string &SerialNumber, uint64_t CurrentConfig, std::string &NewConfig, uint64_t &);
bool UpdateDeviceCapabilities(std::string &SerialNUmber, std::string &State );
bool GetDeviceCapabilities(std::string &SerialNUmber, uCentralCapabilities & );
static uStorageService *instance() {
if(instance_== nullptr) {
instance_ = new uStorageService;
}
return instance_;
}
private:
static uStorageService *instance_;
std::shared_ptr<Poco::Data::Session> session_;
std::mutex mutex_;
};
#endif //UCENTRAL_USTORAGESERVICE_H

View File

@@ -1,28 +0,0 @@
//
// Created by stephane bourque on 2021-02-12.
//
#include "ucentralServer.h"
#include "common.h"
UCentralGW::UCentralGW(): helpRequested_(false)
{
}
void UCentralGW::initialize(Application & self)
{
}
void UCentralGW::uninitialize()
{
// add your own uninitialization code here
}
void UCentralGW::reinitialize(Application & self)
{
// add your own reinitialization code here
}
void UCentralGW::defineOptions(OptionSet& options)
{
}