Compare commits

..

1 Commits

Author SHA1 Message Date
TIP Automation User
3eb45c219c Chg: update image tag in helm values to v3.0.0-RC1 2023-11-27 17:38:10 +00:00
87 changed files with 1578 additions and 7399 deletions

4
.gitignore vendored
View File

@@ -21,12 +21,10 @@ _deps
/docker-compose/.env
/docker-compose/.env_*
/cmake-build/
/uploads/
test_scripts/curl/token.json
.vscode/c_cpp_properties.json
test_scripts/curl/result.json
*.swp
helm/charts/*
!helm/charts/.gitkeep
/portal-test/
/src/ow_version.h

2
.idea/.gitignore generated vendored
View File

@@ -6,5 +6,3 @@
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
# GitHub Copilot persisted chat sessions
/copilot/chatSessions

3
.idea/misc.xml generated
View File

@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9 (wlan-cloud-ucentralgw)" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="CidrRootsConfiguration">
<excludeRoots>

View File

@@ -1,5 +1,5 @@
# Building from source
In order to build OWGW, you will need to install its dependencies, which includes the following:
In order to build the OWGW, you will need to install its dependencies, which includes the following:
- cmake
- boost
- POCO 1.10.1 or later
@@ -12,43 +12,43 @@ In order to build OWGW, you will need to install its dependencies, which include
The build is done in 2 parts. The first part is to build a local copy of the framework tailored to your environment. This
framework is called [Poco](https://github.com/pocoproject/poco). The version used in this project has a couple of fixes
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/Telecominfraproject/wlan-cloud-lib-poco). Building
from the master copy needed for cmake. Please use the version of this [Poco fix](https://github.com/AriliaWireless/poco). Building
Poco may take several minutes depending on the platform you are building on.
## Ubuntu
These instructions have proven to work on Ubuntu 20.4.
```bash
sudo apt install git cmake g++ libssl-dev libmariadb-dev \
libpq-dev libaprutil1-dev apache2-dev libboost-all-dev \
librdkafka-dev // default-libmysqlclient-dev \
nlohmann-json-dev
sudo apt install git cmake g++ libssl-dev libmariadb-dev
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
sudo apt install librdkafka-dev // default-libmysqlclient-dev
sudo apt install nlohmann-json-dev
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
cd ~
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
cd poco
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
cd ~
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
cd cppkafka
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
cd ~
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
cd valijson
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
cd fmtlib
@@ -57,59 +57,56 @@ cd cmake-build
cmake ..
make
make install
cd ../..
cd ~
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
cd wlan-cloud-ucentralgw
mkdir cmake-build
cd cmake-build
cmake ..
make -j 8
cd ../..
```
## Fedora
The following instructions have proven to work on Fedora 33
```bash
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel \
yaml-cpp-devel lua-devel
sudo yum install cmake g++ openssl-devel mysql-devel mysql apr-util-devel boost boost-devel
sudo yum install yaml-cpp-devel lua-devel
sudo dnf install postgresql.x86_64 librdkafka-devel
sudo dnf install postgresql-devel json-devel
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
cd poco
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
cd cppkafka
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
cd ~
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
cd valijson
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
cd ~
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
cd wlan-cloud-ucentralgw
mkdir cmake-build
cd cmake-build
cmake ..
make
cd ../..
```
## macOS Build
@@ -128,7 +125,7 @@ brew install openssl \
nlohmann-json \
fmt
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
git clone https://github.com/AriliaWireless/poco --branch poco-tip-v2
pushd poco
mkdir cmake-build
push cmake-build
@@ -138,7 +135,7 @@ sudo cmake --build . --target install
popd
popd
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch tip-v1 cppkafka
git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1
pushd cppkafka
mkdir cmake-build
pushd cmake-build
@@ -148,10 +145,10 @@ sudo cmake --build . --target install
popd
popd
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch tip-v1 valijson
pushd valijson
git clone https://github.com/AriliaWireless/valijson --branch tip-v1
cd valijson
mkdir cmake-build
pushd cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
@@ -174,23 +171,20 @@ support. You can build with only SQLite support by not installing the packages f
adding -DSMALL_BUILD=1 on the cmake build line.
```bash
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev \
libboost-all-dev libyaml-cpp-dev
git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch poco-tip-v1 poco
sudo apt install git cmake g++ libssl-dev libaprutil1-dev apache2-dev libboost-all-dev libyaml-cpp-dev
git clone https://github.com/stephb9959/poco
cd poco
mkdir cmake-build
cd cmake-build
cmake ..
cmake --build . --config Release
sudo cmake --build . --target install
cd ../..
cd ~
git clone https://github.com/Telecominfraproject/wlan-cloud-ucentralgw
cd wlan-cloud-ucentralgw
mkdir cmake-build
cd cmake-build
cmake -DSMALL_BUILD=1 ..
make
cd ../..
```

View File

@@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 3.13)
project(owgw VERSION 3.1.0)
project(owgw VERSION 3.0.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_STANDARD 17)
if(UNIX AND APPLE)
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
@@ -149,7 +148,6 @@ add_executable( owgw
src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h
src/RESTAPI/RESTAPI_regulatory.cpp src/RESTAPI/RESTAPI_regulatory.h
src/RESTAPI/RESTAPI_radiussessions_handler.cpp src/RESTAPI/RESTAPI_radiussessions_handler.h
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
@@ -177,7 +175,7 @@ add_executable( owgw
src/SDKcalls.cpp
src/SDKcalls.h
src/StateUtils.cpp src/StateUtils.h
src/AP_WS_Reactor_Pool.h
src/AP_WS_ReactorPool.h
src/AP_WS_Connection.h
src/AP_WS_Connection.cpp
src/TelemetryClient.h src/TelemetryClient.cpp
@@ -213,8 +211,7 @@ add_executable( owgw
src/RegulatoryInfo.cpp src/RegulatoryInfo.h
src/RADIUSSessionTracker.cpp src/RADIUSSessionTracker.h
src/libs/Scheduler.h src/libs/InterruptableSleep.h src/libs/ctpl_stl.h src/libs/Cron.h
src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h
src/AP_WS_LookForUpgrade.cpp)
src/GenericScheduler.cpp src/GenericScheduler.h src/framework/default_device_types.h src/AP_WS_Process_rebootLog.cpp src/AP_WS_ConfigAutoUpgrader.cpp src/AP_WS_ConfigAutoUpgrader.h src/RESTAPI/RESTAPI_default_firmwares.cpp src/RESTAPI/RESTAPI_default_firmwares.h src/RESTAPI/RESTAPI_default_firmware.cpp src/RESTAPI/RESTAPI_default_firmware.h src/storage/storage_def_firmware.cpp src/firmware_revision_cache.h src/sdks/sdk_fms.h)
if(NOT SMALL_BUILD)

View File

@@ -17,8 +17,8 @@ FROM build-base AS poco-build
ARG POCO_VERSION
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-poco/git/refs/tags/${POCO_VERSION} version.json
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-poco --branch ${POCO_VERSION} /poco
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
WORKDIR /poco
RUN mkdir cmake-build
@@ -31,8 +31,8 @@ FROM build-base AS cppkafka-build
ARG CPPKAFKA_VERSION
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
WORKDIR /cppkafka
RUN mkdir cmake-build
@@ -45,8 +45,8 @@ FROM build-base AS valijson-build
ARG VALIJASON_VERSION
ADD https://api.github.com/repos/Telecominfraproject/wlan-cloud-lib-valijson/git/refs/tags/${VALIJASON_VERSION} version.json
RUN git clone https://github.com/Telecominfraproject/wlan-cloud-lib-valijson --branch ${VALIJASON_VERSION} /valijson
ADD https://api.github.com/repos/AriliaWireless/valijson/git/refs/tags/${VALIJASON_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/valijson --branch ${VALIJASON_VERSION} /valijson
WORKDIR /valijson
RUN mkdir cmake-build

View File

@@ -355,39 +355,6 @@ The device should answer:
- 1 : the device is busy but will reboot soon. `text` may indicate why.
- 2 : the device will not reboot. `text` contains information as to why.
#### Controller wants to power-cycle PoE port(s)
Controller sends this command to power-cycle 1 or more PoE ports
```json
{ "jsonrpc" : "2.0" ,
"method" : "powercycle" ,
"params" : {
"serial" : <serial number> ,
"ports" : [ { "name" : "Ethernet1", "cycle" : 5000}, { "name" : "Ethernet8", "cycle" : 10000 } ],
"when" : Optional - <UTC time when to reboot, 0 mean immediately, this is a suggestion>
},
"id" : <some number>
}
```
The device should answer:
```json
{ "jsonrpc" : "2.0" ,
"result" : {
"serial" : <serial number> ,
"status" : {
"error" : 0 or an error number,
"text" : [ "Error 1" , "Error 2" ],
"when" : <time when this will be performed as UTC seconds>,
},
"id" : <same id from request>
}
```
###### Error codes
- 0 : is rebooting at `when` seconds.
- 1 : the device is busy but will reboot soon. `text` may indicate why.
- 2 : the device will not reboot. `text` contains information as to why.
#### Controller wants the device to upgrade its firmware
Controller sends this command when it believes the device should upgrade its firmware.
```json

2
build
View File

@@ -1 +1 @@
3
10

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images:
owgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
tag: v3.1.0
tag: v3.0.0-RC1
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io

View File

@@ -1,85 +0,0 @@
{
"ethernet": [
{
"select-ports": [
"Ethernet0",
"Ethernet1",
"Ethernet2",
"Ethernet3",
"Ethernet4",
"Ethernet5",
"Ethernet6",
"Ethernet7"
],
"speed": 2500,
"duplex": "full",
"enabled": true,
"poe": {
"admin-mode": true,
"power-limit": 60000
}
},
{
"select-ports": [
"Ethernet8",
"Ethernet9"
],
"speed": 10000,
"duplex": "full",
"media": "sfp-forced-1000sfp"
}
],
"interfaces": [
{
"name": "VLAN1",
"vlan": {
"id": 1
},
"ipv4": {
"addressing": "dynamic"
},
"ethernet": [
{
"select-ports": [
"Ethernet0",
"Ethernet1",
"Ethernet2",
"Ethernet3",
"Ethernet4",
"Ethernet5",
"Ethernet6",
"Ethernet7",
"Ethernet8",
"Ethernet9"
],
"vlan-tag": "un-tagged"
}
]
}
],
"metrics": {
"dhcp-snooping": {
"filters": [
"ack",
"discover",
"offer",
"request",
"solicit",
"reply",
"renew"
]
},
"health": {
"interval": 60
},
"statistics": {
"interval": 120,
"types": []
}
},
"unit": {
"leds-active": true,
"usage-threshold": 95
},
"uuid": 1678263900
}

View File

@@ -42,10 +42,12 @@ components:
schemas:
DeviceType:
type: string
default: ap
default: AP
enum:
- ap
- switch
- AP
- SWITCH
- IOT
- MESH
DeviceRestrictionsKeyInfo:
type: object
@@ -155,9 +157,6 @@ components:
lastRecordedContact:
type: integer
format: int64
blackListed:
type: boolean
readOnly: true
DeviceWithStatus:
type: object
@@ -282,9 +281,6 @@ components:
format: float
connectReason:
type: string
blackListed:
type: boolean
readOnly: true
DeviceList:
type: object
@@ -549,12 +545,6 @@ components:
lastModified:
type: integer
format: int64
platform:
type: string
enum:
- ap
- switch
default: ap
DefaultConfigurationList:
properties:
@@ -1576,30 +1566,6 @@ components:
format: base64
description: This is a base64 encoded string of the certificate bundle (the current bundle .tar.gz file from the PKI portal)
PowerCycleRequest:
type: object
properties:
serial:
type: string
when:
type: integer
format: int64
ports:
type: array
items:
type: object
properties:
name:
type: string
example:
- Ethernet0
cycle:
type: integer
default: 10000
minimum: 1
maximum: 60000
description: off time in milliseconds
paths:
/devices:
get:
@@ -1691,22 +1657,6 @@ paths:
type: integer
default: 70
required: false
- in: query
description: return only devices matching a certain platform of AP or SWITCH
name: platform
schema:
type: string
default: ALL
enum:
- all
- ap
- switch
required: false
- in: query
description: only devices which are not provisioned
name: includeProvisioned
schema:
type: boolean
responses:
200:
description: List devices
@@ -3056,34 +3006,6 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/powercycle:
post:
tags:
- Commands
summary: Perform PoE power cycle for some PoE ports.
operationId: performPowerCycle
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Certificate update details
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/PowerCycleRequest'
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/ouis:
get:
tags:

View File

@@ -145,7 +145,7 @@ storage.type.sqlite.db = devices.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 250
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}

View File

@@ -9,14 +9,14 @@
namespace OpenWifi {
int AP_WS_ConfigAutoUpgradeAgent::Start() {
int AP_WS_ConfigAutoUpgrader::Start() {
poco_notice(Logger(), "Starting...");
QueueManager_.start(*this);
return 0;
}
void AP_WS_ConfigAutoUpgradeAgent::Stop() {
void AP_WS_ConfigAutoUpgrader::Stop() {
poco_notice(Logger(), "Stopping...");
Running_ = false;
Queue_.wakeUpAll();
@@ -24,7 +24,7 @@ namespace OpenWifi {
poco_notice(Logger(), "Stopped...");
}
void AP_WS_ConfigAutoUpgradeAgent::run() {
void AP_WS_ConfigAutoUpgrader::run() {
Utils::SetThreadName("auto:cfgmgr");
Running_ = true;

View File

@@ -28,14 +28,14 @@ namespace OpenWifi {
std::uint64_t pending_config_=0;
};
class AP_WS_ConfigAutoUpgradeAgent : public SubSystemServer, Poco::Runnable {
class AP_WS_ConfigAutoUpgrader : public SubSystemServer, Poco::Runnable {
public:
int Start() final;
void Stop() final;
void run() final;
static auto instance() {
static auto instance = new AP_WS_ConfigAutoUpgradeAgent;
static auto instance = new AP_WS_ConfigAutoUpgrader;
return instance;
}
@@ -126,12 +126,12 @@ namespace OpenWifi {
mutable std::mutex CacheMutex_;
std::map<std::uint64_t, ConfigurationCacheEntry> Cache_;
AP_WS_ConfigAutoUpgradeAgent() noexcept
AP_WS_ConfigAutoUpgrader() noexcept
: SubSystemServer("AutoConfigUpgrade", "AUTO-CFG-MGR", "auto.config.updater") {
}
};
inline auto AP_WS_ConfigAutoUpgradeAgent() { return AP_WS_ConfigAutoUpgradeAgent::instance(); }
inline auto AP_WS_ConfigAutoUpgrader() { return AP_WS_ConfigAutoUpgrader::instance(); }
} // namespace OpenWifi

View File

@@ -2,49 +2,56 @@
// Created by stephane bourque on 2022-02-03.
//
#include "AP_WS_Connection.h"
#include <Poco/Base64Decoder.h>
#include <Poco/Net/Context.h>
#include <Poco/Net/HTTPServerRequestImpl.h>
#include <Poco/Net/HTTPServerResponseImpl.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/SSLException.h>
#include <Poco/Net/SecureStreamSocketImpl.h>
#include <Poco/Net/WebSocketImpl.h>
#include "Poco/Base64Decoder.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/HTTPServerRequestImpl.h"
#include "Poco/Net/HTTPServerResponseImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/WebSocketImpl.h"
#include "Poco/zlib.h"
#include <framework/KafkaManager.h>
#include <framework/MicroServiceFuncs.h>
#include <framework/utils.h>
#include <framework/ow_constants.h>
#include "AP_WS_Server.h"
#include "CentralConfig.h"
#include "CommandManager.h"
#include "ConfigurationCache.h"
#include "StorageService.h"
#include "TelemetryStream.h"
#include <fmt/format.h>
#include "GWKafkaEvents.h"
#include "UI_GW_WebSocketNotifications.h"
#include "framework/KafkaManager.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
#include <AP_WS_Connection.h>
#include <AP_WS_Server.h>
#include <CentralConfig.h>
#include <CommandManager.h>
#include <StorageService.h>
#include <RADIUSSessionTracker.h>
#include <RADIUS_proxy_server.h>
#include <GWKafkaEvents.h>
#include <UI_GW_WebSocketNotifications.h>
#include "fmt/format.h"
#include "framework/ow_constants.h"
#include "RADIUSSessionTracker.h"
#include "RADIUS_proxy_server.h"
namespace OpenWifi {
#define DBL \
{ \
std::cout << __LINE__ << " ID: " << ConnectionId_ << " Ser: " << SerialNumber_ \
<< std::endl; \
}
void AP_WS_Connection::LogException(const Poco::Exception &E) {
poco_information(Logger_, fmt::format("EXCEPTION({}): {}", CId_, E.displayText()));
}
AP_WS_Connection::AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response,
uint64_t session_id, Poco::Logger &L,
std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
: Logger_(L) {
Reactor_ = R.first;
DbSession_ = R.second;
State_.sessionId = session_id;
uint64_t connection_id, Poco::Logger &L,
Poco::Net::SocketReactor &R)
: Logger_(L), Reactor_(R) {
State_.sessionId = connection_id;
WS_ = std::make_unique<Poco::Net::WebSocket>(request, response);
auto TS = Poco::Timespan(360, 0);
@@ -54,86 +61,29 @@ namespace OpenWifi {
WS_->setNoDelay(false);
WS_->setKeepAlive(true);
WS_->setBlocking(false);
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
AP_WS_Server()->IncrementConnectionCount();
}
void AP_WS_Connection::Start() {
Reactor_.addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable));
Reactor_.addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown));
Reactor_.addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
Registered_ = true;
LastContact_ = Utils::Now();
Reactor_->addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable));
Reactor_->addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown));
Reactor_->addEventHandler(*WS_,
Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
}
AP_WS_Connection::~AP_WS_Connection() {
std::lock_guard G(ConnectionMutex_);
AP_WS_Server()->DecrementConnectionCount();
EndConnection();
poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
State_.sessionId));
}
static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
try {
Poco::JSON::Object Disconnect;
Poco::JSON::Object Details;
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
Details.set(uCentralProtocol::UUID,uuid);
Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
} catch (...) {
}
}
void AP_WS_Connection::EndConnection() {
bool expectedValue=false;
if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {
if(!SerialNumber_.empty() && State_.LastContact!=0) {
StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
}
if (Registered_) {
Registered_ = false;
Reactor_->removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable));
Reactor_->removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown));
Reactor_->removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
Registered_=false;
}
WS_->close();
if(!SerialNumber_.empty()) {
DeviceDisconnectionCleanup(SerialNumber_, uuid_);
}
AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
}
Valid_ = true;
uuid_ = MicroServiceRandom(std::numeric_limits<std::uint64_t>::max()-1);
}
bool AP_WS_Connection::ValidatedDevice() {
if(Dead_)
return false;
if (DeviceValidated_)
return true;
if (!Valid_)
return false;
std::lock_guard Lock(ConnectionMutex_);
try {
auto SockImpl = dynamic_cast<Poco::Net::WebSocketImpl *>(WS_->impl());
auto SS =
@@ -148,6 +98,7 @@ namespace OpenWifi {
poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Connection is "
"NOT secure. Device is not allowed.",
CId_, State_.sessionId));
EndConnection();
return false;
}
@@ -160,6 +111,7 @@ namespace OpenWifi {
Logger_,
fmt::format("TLS-CONNECTION({}): Session={} No certificates available..", CId_,
State_.sessionId));
EndConnection();
return false;
}
@@ -170,19 +122,11 @@ namespace OpenWifi {
fmt::format("TLS-CONNECTION({}): Session={} Device certificate is not "
"valid. Device is not allowed.",
CId_, State_.sessionId));
EndConnection();
return false;
}
CN_ = Poco::trim(Poco::toLower(PeerCert.commonName()));
if(!Utils::ValidSerialNumber(CN_)) {
poco_trace(Logger_,
fmt::format("TLS-CONNECTION({}): Session={} Invalid serial number: CN={}", CId_,
State_.sessionId, CN_));
return false;
}
SerialNumber_ = CN_;
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
State_.VerifiedCertificate = GWObjects::VALID_CERTIFICATE;
poco_trace(Logger_,
fmt::format("TLS-CONNECTION({}): Session={} Valid certificate: CN={}", CId_,
@@ -192,27 +136,31 @@ namespace OpenWifi {
poco_warning(Logger_, fmt::format("TLS-CONNECTION({}): Session={} Sim Device {} is "
"not allowed. Disconnecting.",
CId_, State_.sessionId, CN_));
EndConnection();
return false;
}
if(AP_WS_Server::IsSim(SerialNumber_)) {
if(AP_WS_Server::IsSim(CN_)) {
State_.VerifiedCertificate = GWObjects::SIMULATED;
Simulated_ = true;
}
std::string reason, author;
std::uint64_t created;
if (!CN_.empty() && StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
if (!CN_.empty() && StorageService()->IsBlackListed(CN_, reason, author, created)) {
DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
poco_warning(
Logger_,
fmt::format(
"TLS-CONNECTION({}): Session={} Device {} is black listed. Disconnecting.",
CId_, State_.sessionId, CN_));
EndConnection();
return false;
}
State_.certificateExpiryDate = PeerCert.expiresOn().timestamp().epochTime();
SerialNumber_ = CN_;
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
poco_trace(Logger_,
fmt::format("TLS-CONNECTION({}): Session={} CN={} Completed. (t={})", CId_,
@@ -276,14 +224,149 @@ namespace OpenWifi {
return false;
}
void AP_WS_Connection::DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
try {
Poco::JSON::Object Disconnect;
Poco::JSON::Object Details;
Details.set(uCentralProtocol::SERIALNUMBER, SerialNumber);
Details.set(uCentralProtocol::TIMESTAMP, Utils::Now());
Details.set(uCentralProtocol::UUID,uuid);
Disconnect.set(uCentralProtocol::DISCONNECTION, Details);
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber, Disconnect);
} catch (...) {
}
}
AP_WS_Connection::~AP_WS_Connection() {
Valid_ = false;
EndConnection();
}
void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid) {
if (KafkaManager()->Enabled()) {
NotifyKafkaDisconnect(SerialNumber, uuid);
}
RADIUSSessionTracker()->DeviceDisconnect(SerialNumber);
GWWebSocketNotifications::SingleDevice_t N;
N.content.serialNumber = SerialNumber;
GWWebSocketNotifications::DeviceDisconnected(N);
}
void AP_WS_Connection::EndConnection(bool DeleteSession) {
Valid_ = false;
if (!Dead_.test_and_set()) {
if(!SerialNumber_.empty() && State_.LastContact!=0) {
StorageService()->SetDeviceLastRecordedContact(SerialNumber_, State_.LastContact);
}
if (Registered_) {
Registered_ = false;
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ReadableNotification>(
*this, &AP_WS_Connection::OnSocketReadable));
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ShutdownNotification>(
*this, &AP_WS_Connection::OnSocketShutdown));
Reactor_.removeEventHandler(
*WS_, Poco::NObserver<AP_WS_Connection, Poco::Net::ErrorNotification>(
*this, &AP_WS_Connection::OnSocketError));
}
WS_->close();
if(!SerialNumber_.empty()) {
std::thread Cleanup(DeviceDisconnectionCleanup,SerialNumber_, uuid_);
Cleanup.detach();
}
bool SessionDeleted = false;
if(DeleteSession)
SessionDeleted = AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
if (SessionDeleted || !DeleteSession) {
GWWebSocketNotifications::SingleDevice_t N;
N.content.serialNumber = SerialNumber_;
GWWebSocketNotifications::DeviceDisconnected(N);
}
}
}
bool AP_WS_Connection::LookForUpgrade(const uint64_t UUID, uint64_t &UpgradedUUID) {
// A UUID of zero means ignore updates for that connection.
if (UUID == 0)
return false;
uint64_t GoodConfig = ConfigurationCache().CurrentConfig(SerialNumberInt_);
if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
UpgradedUUID = UUID;
return false;
}
GWObjects::Device D;
if (StorageService()->GetDevice(SerialNumber_, D)) {
if(D.pendingUUID!=0 && UUID==D.pendingUUID) {
// so we sent an upgrade to a device, and now it is completing now...
UpgradedUUID = D.pendingUUID;
StorageService()->CompleteDeviceConfigurationChange(SerialNumber_);
return true;
}
// This is the case where the cache is empty after a restart. So GoodConfig will 0. If
// the device already has the right UUID, we just return.
if (D.UUID == UUID) {
UpgradedUUID = UUID;
ConfigurationCache().Add(SerialNumberInt_, UUID);
return false;
}
Config::Config Cfg(D.Configuration);
if (UUID > D.UUID) {
// so we have a problem, the device has a newer config than we have. So we need to
// make sure our config is newer.
D.UUID = UUID + 2;
UpgradedUUID = D.UUID;
}
Cfg.SetUUID(D.UUID);
D.Configuration = Cfg.get();
State_.PendingUUID = UpgradedUUID = D.UUID;
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroServiceCreateUUID();
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
Cmd.Status = uCentralProtocol::PENDING;
Cmd.Command = uCentralProtocol::CONFIGURE;
Poco::JSON::Parser P;
auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::UUID, D.UUID);
Params.set(uCentralProtocol::WHEN, 0);
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
std::ostringstream O;
Poco::JSON::Stringifier::stringify(Params, O);
Cmd.Details = O.str();
poco_information(Logger_,
fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
CId_, UUID, D.UUID));
bool Sent;
StorageService()->AddCommand(SerialNumber_, Cmd,
Storage::CommandExecutionType::COMMAND_EXECUTED);
CommandManager()->PostCommand(
CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
Notification.content.serialNumber = D.SerialNumber;
Notification.content.oldUUID = UUID;
Notification.content.newUUID = UpgradedUUID;
GWWebSocketNotifications::DeviceConfigurationChange(Notification);
return true;
}
return false;
}
void AP_WS_Connection::ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc) {
@@ -364,7 +447,7 @@ namespace OpenWifi {
std::string reason, author;
std::uint64_t created;
if (StorageService()->IsBlackListed(SerialNumberInt_, reason, author, created)) {
if (StorageService()->IsBlackListed(Serial, reason, author, created)) {
DeviceBlacklistedKafkaEvent KE(Utils::SerialNumberToInt(CN_), Utils::Now(), reason, author, created, CId_);
Poco::Exception E(
fmt::format("BLACKLIST({}): device is blacklisted and not allowed to connect.",
@@ -495,17 +578,17 @@ namespace OpenWifi {
}
bool AP_WS_Connection::SetWebSocketTelemetryReporting(
std::uint64_t RPCID, std::uint64_t Interval, std::uint64_t LifeTime,
uint64_t RPCID, uint64_t Interval, uint64_t LifeTime,
const std::vector<std::string> &TelemetryTypes) {
std::unique_lock Lock(TelemetryMutex_);
TelemetryWebSocketRefCount_++;
TelemetryInterval_ = TelemetryInterval_
? (Interval < (std::uint64_t)TelemetryInterval_ ? Interval : (std::uint64_t )TelemetryInterval_)
? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
: Interval;
auto TelemetryWebSocketTimer = LifeTime + Utils::Now();
TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > (std::uint64_t)TelemetryWebSocketTimer_
? (std::uint64_t)TelemetryWebSocketTimer
: (std::uint64_t)TelemetryWebSocketTimer_;
TelemetryWebSocketTimer_ = TelemetryWebSocketTimer > TelemetryWebSocketTimer_
? TelemetryWebSocketTimer
: TelemetryWebSocketTimer_;
UpdateCounts();
if (!TelemetryReporting_) {
TelemetryReporting_ = true;
@@ -521,11 +604,11 @@ namespace OpenWifi {
std::unique_lock Lock(TelemetryMutex_);
TelemetryKafkaRefCount_++;
TelemetryInterval_ = TelemetryInterval_
? (Interval < (std::uint64_t)TelemetryInterval_ ? (std::uint64_t)Interval : (std::uint64_t)TelemetryInterval_)
? (Interval < TelemetryInterval_ ? Interval : TelemetryInterval_)
: Interval;
auto TelemetryKafkaTimer = LifeTime + Utils::Now();
TelemetryKafkaTimer_ =
TelemetryKafkaTimer > (std::uint64_t)TelemetryKafkaTimer_ ? (std::uint64_t)TelemetryKafkaTimer : (std::uint64_t)TelemetryKafkaTimer_;
TelemetryKafkaTimer > TelemetryKafkaTimer_ ? TelemetryKafkaTimer : TelemetryKafkaTimer_;
UpdateCounts();
if (!TelemetryReporting_) {
TelemetryReporting_ = true;
@@ -561,50 +644,49 @@ namespace OpenWifi {
void AP_WS_Connection::OnSocketShutdown(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
poco_trace(Logger_, fmt::format("SOCKET-SHUTDOWN({}): Closing.", CId_));
// std::lock_guard G(ConnectionMutex_);
return EndConnection();
}
void AP_WS_Connection::OnSocketError(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
poco_trace(Logger_, fmt::format("SOCKET-ERROR({}): Closing.", CId_));
// std::lock_guard G(ConnectionMutex_);
return EndConnection();
}
void AP_WS_Connection::OnSocketReadable(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
if (Dead_) // we are dead, so we do not process anything.
if (!Valid_)
return;
std::lock_guard G(ConnectionMutex_);
if (!AP_WS_Server()->Running())
return EndConnection();
State_.LastContact = LastContact_ = Utils::Now();
if (AP_WS_Server()->Running() && (DeviceValidated_ || ValidatedDevice())) {
try {
return ProcessIncomingFrame();
} catch (const Poco::Exception &E) {
Logger_.log(E);
} catch (const std::exception &E) {
std::string W = E.what();
poco_information(
Logger_, fmt::format("std::exception caught: {}. Connection terminated with {}",
W, CId_));
} catch (...) {
poco_information(
Logger_, fmt::format("Unknown exception for {}. Connection terminated.", CId_));
}
if (!ValidatedDevice())
return;
try {
return ProcessIncomingFrame();
} catch (const Poco::Exception &E) {
Logger_.log(E);
return EndConnection();
} catch (const std::exception &E) {
std::string W = E.what();
poco_information(
Logger_,
fmt::format("std::exception caught: {}. Connection terminated with {}", W, CId_));
return EndConnection();
} catch (...) {
poco_information(Logger_,
fmt::format("Unknown exception for {}. Connection terminated.", CId_));
return EndConnection();
}
EndConnection();
}
void AP_WS_Connection::ProcessIncomingFrame() {
Poco::Buffer<char> IncomingFrame(0);
bool KillConnection=false;
try {
int Op, flags;
int Op, flags;
auto IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
@@ -624,81 +706,83 @@ namespace OpenWifi {
State_.LastContact = Utils::Now();
switch (Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: {
poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
case Poco::Net::WebSocket::FRAME_OP_PING: {
poco_trace(Logger_, fmt::format("WS-PING({}): received. PONG sent back.", CId_));
WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
if (KafkaManager()->Enabled()) {
Poco::JSON::Object PingObject;
Poco::JSON::Object PingDetails;
PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
PingDetails.set(uCentralProtocol::UUID, uuid_);
PingDetails.set("locale", State_.locale);
PingObject.set(uCentralProtocol::PING, PingDetails);
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
}
} break;
if (KafkaManager()->Enabled()) {
Poco::JSON::Object PingObject;
Poco::JSON::Object PingDetails;
PingDetails.set(uCentralProtocol::FIRMWARE, State_.Firmware);
PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_);
PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_);
PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_);
PingDetails.set(uCentralProtocol::TIMESTAMP, Utils::Now());
PingDetails.set(uCentralProtocol::UUID, uuid_);
PingDetails.set("locale", State_.locale);
PingObject.set(uCentralProtocol::PING, PingDetails);
poco_trace(Logger_,fmt::format("Sending PING for {}", SerialNumber_));
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_,PingObject);
}
return;
} break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
} break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
poco_trace(Logger_, fmt::format("PONG({}): received and ignored.", CId_));
return;
} break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
poco_trace(Logger_,
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
CId_, IncomingSize, flags, IncomingFrame.begin()));
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
poco_trace(Logger_,
fmt::format("FRAME({}): Frame received (length={}, flags={}). Msg={}",
CId_, IncomingSize, flags, IncomingFrame.begin()));
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(IncomingFrame.begin());
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(IncomingFrame.begin());
auto IncomingJSON = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
IncomingJSON->has(uCentralProtocol::PARAMS)) {
ProcessJSONRPCEvent(IncomingJSON);
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
IncomingJSON->has(uCentralProtocol::ID)) {
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
IncomingFrame.begin()));
ProcessJSONRPCResult(IncomingJSON);
} else {
poco_warning(
Logger_,
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
CId_, IncomingFrame.begin()));
}
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
ProcessIncomingRadiusData(IncomingJSON);
if (IncomingJSON->has(uCentralProtocol::JSONRPC)) {
if (IncomingJSON->has(uCentralProtocol::METHOD) &&
IncomingJSON->has(uCentralProtocol::PARAMS)) {
ProcessJSONRPCEvent(IncomingJSON);
} else if (IncomingJSON->has(uCentralProtocol::RESULT) &&
IncomingJSON->has(uCentralProtocol::ID)) {
poco_trace(Logger_, fmt::format("RPC-RESULT({}): payload: {}", CId_,
IncomingFrame.begin()));
ProcessJSONRPCResult(IncomingJSON);
} else {
std::ostringstream iS;
IncomingJSON->stringify(iS);
poco_warning(
Logger_,
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc': {}",
CId_, iS.str()));
Errors_++;
fmt::format("INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}",
CId_, IncomingFrame.begin()));
}
} break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
poco_information(Logger_,
fmt::format("CLOSE({}): Device is closing its connection.", CId_));
KillConnection=true;
} break;
default: {
poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
CId_, std::to_string(Op)));
} else if (IncomingJSON->has(uCentralProtocol::RADIUS)) {
ProcessIncomingRadiusData(IncomingJSON);
} else {
std::ostringstream iS;
IncomingJSON->stringify(iS);
std::cout << iS.str() << std::endl;
poco_warning(
Logger_,
fmt::format("FRAME({}): illegal transaction header, missing 'jsonrpc'",
CId_));
Errors_++;
return;
}
return;
} break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
poco_information(Logger_,
fmt::format("CLOSE({}): Device is closing its connection.", CId_));
return EndConnection();
} break;
default: {
poco_warning(Logger_, fmt::format("UNKNOWN({}): unknown WS Frame operation: {}",
CId_, std::to_string(Op)));
} break;
}
} catch (const Poco::Net::ConnectionResetException &E) {
poco_warning(Logger_,
@@ -706,21 +790,21 @@ namespace OpenWifi {
CId_, E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::JSON::JSONException &E) {
poco_warning(Logger_,
fmt::format("JSONException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::Net::WebSocketException &E) {
poco_warning(Logger_,
fmt::format("WebSocketException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
poco_warning(
Logger_,
@@ -729,54 +813,54 @@ namespace OpenWifi {
CId_, E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::Net::SSLException &E) {
poco_warning(Logger_,
fmt::format("SSLException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::Net::NetException &E) {
poco_warning(Logger_,
fmt::format("NetException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::IOException &E) {
poco_warning(Logger_,
fmt::format("IOException({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const Poco::Exception &E) {
poco_warning(Logger_,
fmt::format("Exception({}): Text:{} Payload:{} Session:{}", CId_,
E.displayText(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (const std::exception &E) {
poco_warning(Logger_,
fmt::format("std::exception({}): Text:{} Payload:{} Session:{}", CId_,
E.what(),
IncomingFrame.begin() == nullptr ? "" : IncomingFrame.begin(),
State_.sessionId));
KillConnection=true;
return EndConnection();
} catch (...) {
poco_error(Logger_, fmt::format("UnknownException({}): Device must be disconnected. "
"Unknown exception. Session:{}",
CId_, State_.sessionId));
KillConnection=true;
return EndConnection();
}
if (!KillConnection && Errors_ < 10)
if (Errors_ < 10)
return;
poco_warning(Logger_, fmt::format("DISCONNECTING({}): ConnectionException: {} Errors: {}", CId_, KillConnection, Errors_ ));
EndConnection();
poco_warning(Logger_, fmt::format("DISCONNECTING({}): Too many errors", CId_));
return EndConnection();
}
bool AP_WS_Connection::Send(const std::string &Payload) {
@@ -888,36 +972,4 @@ namespace OpenWifi {
}
}
}
void AP_WS_Connection::SetLastStats(const std::string &LastStats) {
RawLastStats_ = LastStats;
try {
Poco::JSON::Parser P;
auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
State_.hasGPS = Stats->isObject("gps");
auto Unit = Stats->getObject("unit");
auto Memory = Unit->getObject("memory");
std::uint64_t TotalMemory = Memory->get("total");
std::uint64_t FreeMemory = Memory->get("free");
if (TotalMemory > 0) {
State_.memoryUsed =
(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
}
if (Unit->isArray("load")) {
Poco::JSON::Array::Ptr Load = Unit->getArray("load");
if (Load->size() > 1) {
State_.load = Load->get(1);
}
}
if (Unit->isArray("temperature")) {
Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
if (Temperature->size() > 1) {
State_.temperature = Temperature->get(0);
}
}
} catch (const Poco::Exception &E) {
poco_error(Logger_, "Failed to parse last stats: " + E.displayText());
}
}
} // namespace OpenWifi

View File

@@ -14,10 +14,8 @@
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/WebSocket.h"
#include <Poco/Data/Session.h>
#include "RESTObjects/RESTAPI_GWobjects.h"
#include <AP_WS_Reactor_Pool.h>
namespace OpenWifi {
@@ -27,17 +25,16 @@ namespace OpenWifi {
public:
explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
Poco::Logger &L, Poco::Net::SocketReactor &R);
~AP_WS_Connection();
void EndConnection();
void EndConnection(bool DeleteSession=true);
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
void ProcessIncomingFrame();
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
[[nodiscard]] bool Send(const std::string &Payload);
[[nodiscard]] inline bool MustBeSecureRTTY() const { return RTTYMustBeSecure_; }
bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
@@ -46,7 +43,10 @@ namespace OpenWifi {
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
bool LookForUpgrade(Poco::Data::Session &Session, uint64_t UUID, uint64_t &UpgradedUUID);
bool LookForUpgrade(uint64_t UUID, uint64_t &UpgradedUUID);
static bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData,
uint64_t compress_sz);
void LogException(const Poco::Exception &E);
inline Poco::Logger &Logger() { return Logger_; }
bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
@@ -59,33 +59,81 @@ namespace OpenWifi {
bool StopKafkaTelemetry(uint64_t RPCID);
inline void GetLastStats(std::string &LastStats) {
if(!Dead_) {
std::lock_guard G(ConnectionMutex_);
LastStats = RawLastStats_;
std::lock_guard G(ConnectionMutex_);
LastStats = RawLastStats_;
}
inline void SetLastStats(const std::string &LastStats) {
std::lock_guard G(ConnectionMutex_);
RawLastStats_ = LastStats;
try {
Poco::JSON::Parser P;
auto Stats = P.parse(LastStats).extract<Poco::JSON::Object::Ptr>();
hasGPS = Stats->isObject("gps");
auto Unit = Stats->getObject("unit");
auto Memory = Unit->getObject("memory");
std::uint64_t TotalMemory = Memory->get("total");
std::uint64_t FreeMemory = Memory->get("free");
if(TotalMemory>0) {
memory_used_ =
(100.0 * ((double)TotalMemory - (double)FreeMemory)) / (double)TotalMemory;
}
if(Unit->isArray("load")) {
Poco::JSON::Array::Ptr Load = Unit->getArray("load");
if(Load->size()>1) {
cpu_load_ = Load->get(1);
}
}
if(Unit->isArray("temperature")) {
Poco::JSON::Array::Ptr Temperature = Unit->getArray("temperature");
if(Temperature->size()>1) {
temperature_ = Temperature->get(0);
}
}
} catch (...) {
}
}
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
std::lock_guard G(ConnectionMutex_);
RawLastHealthcheck_ = H;
}
inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
if(!Dead_) {
std::lock_guard G(ConnectionMutex_);
H = RawLastHealthcheck_;
}
}
inline void GetState(GWObjects::ConnectionState &State) {
if(!Dead_) {
std::lock_guard G(ConnectionMutex_);
State = State_;
}
}
inline GWObjects::DeviceRestrictions GetRestrictions() {
std::lock_guard G(ConnectionMutex_);
return Restrictions_;
H = RawLastHealthcheck_;
}
[[nodiscard]] inline bool HasGPS() const { return hasGPS_; }
[[nodiscard]] bool ValidatedDevice();
inline void GetState(GWObjects::ConnectionState &State) const {
std::lock_guard G(ConnectionMutex_);
State = State_;
}
inline bool HasGPS() { return hasGPS; }
inline void GetRestrictions(GWObjects::DeviceRestrictions &R) const {
std::lock_guard G(ConnectionMutex_);
R = Restrictions_;
}
void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
void Process_state(Poco::JSON::Object::Ptr ParamsObj);
void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
void Process_log(Poco::JSON::Object::Ptr ParamsObj);
void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
void Process_event(Poco::JSON::Object::Ptr ParamsObj);
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
bool ValidatedDevice();
inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
@@ -105,14 +153,18 @@ namespace OpenWifi {
friend class AP_WS_Server;
void Start();
inline GWObjects::DeviceRestrictions Restrictions() const {
std::lock_guard G(ConnectionMutex_);
return Restrictions_;
}
inline bool MustBeSecureRtty() const { return RttyMustBeSecure_; }
private:
mutable std::recursive_mutex ConnectionMutex_;
mutable std::mutex ConnectionMutex_;
std::mutex TelemetryMutex_;
Poco::Logger &Logger_;
std::shared_ptr<Poco::Net::SocketReactor> Reactor_;
std::shared_ptr<LockedDbSession> DbSession_;
Poco::Net::SocketReactor &Reactor_;
std::unique_ptr<Poco::Net::WebSocket> WS_;
std::string SerialNumber_;
uint64_t SerialNumberInt_ = 0;
@@ -123,56 +175,34 @@ namespace OpenWifi {
uint64_t Errors_ = 0;
Poco::Net::IPAddress PeerAddress_;
volatile bool TelemetryReporting_ = false;
std::atomic_uint64_t TelemetryWebSocketRefCount_ = 0;
std::atomic_uint64_t TelemetryKafkaRefCount_ = 0;
std::atomic_uint64_t TelemetryWebSocketTimer_ = 0;
std::atomic_uint64_t TelemetryKafkaTimer_ = 0;
std::atomic_uint64_t TelemetryInterval_ = 0;
std::atomic_uint64_t TelemetryWebSocketPackets_ = 0;
std::atomic_uint64_t TelemetryKafkaPackets_ = 0;
volatile uint64_t TelemetryWebSocketRefCount_ = 0;
volatile uint64_t TelemetryKafkaRefCount_ = 0;
volatile uint64_t TelemetryWebSocketTimer_ = 0;
volatile uint64_t TelemetryKafkaTimer_ = 0;
volatile uint64_t TelemetryInterval_ = 0;
volatile uint64_t TelemetryWebSocketPackets_ = 0;
volatile uint64_t TelemetryKafkaPackets_ = 0;
GWObjects::ConnectionState State_;
Utils::CompressedString RawLastStats_;
std::string RawLastStats_;
GWObjects::HealthCheck RawLastHealthcheck_;
std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
std::atomic<bool> Dead_ = false;
std::atomic_flag Dead_ = false;
std::atomic_bool DeviceValidated_ = false;
std::atomic_bool Valid_ = false;
OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
bool RTTYMustBeSecure_ = false;
bool hasGPS_=false;
std::double_t memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
std::uint64_t uuid_=0;
bool Simulated_=false;
std::atomic_uint64_t LastContact_=0;
bool RttyMustBeSecure_ = false;
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
bool StopTelemetry(uint64_t RPCID);
void UpdateCounts();
static void DeviceDisconnectionCleanup(const std::string &SerialNumber, std::uint64_t uuid);
void SetLastStats(const std::string &LastStats);
void Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial);
void Process_state(Poco::JSON::Object::Ptr ParamsObj);
void Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj);
void Process_log(Poco::JSON::Object::Ptr ParamsObj);
void Process_crashlog(Poco::JSON::Object::Ptr ParamsObj);
void Process_ping(Poco::JSON::Object::Ptr ParamsObj);
void Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj);
void Process_recovery(Poco::JSON::Object::Ptr ParamsObj);
void Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial);
void Process_telemetry(Poco::JSON::Object::Ptr ParamsObj);
void Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj);
void Process_event(Poco::JSON::Object::Ptr ParamsObj);
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
RawLastHealthcheck_ = H;
}
bool hasGPS=false;
std::double_t memory_used_=0.0, cpu_load_ = 0.0, temperature_ = 0.0;
std::uint64_t uuid_=0;
bool Simulated_=false;
};
} // namespace OpenWifi

View File

@@ -1,111 +0,0 @@
#include <AP_WS_Connection.h>
#include "ConfigurationCache.h"
#include "UI_GW_WebSocketNotifications.h"
#include "CommandManager.h"
namespace OpenWifi {
bool AP_WS_Connection::LookForUpgrade(Poco::Data::Session &Session, const uint64_t UUID, uint64_t &UpgradedUUID) {
// A UUID of zero means ignore updates for that connection.
if (UUID == 0)
return false;
uint64_t GoodConfig = GetCurrentConfigurationID(SerialNumberInt_);
if (GoodConfig && (GoodConfig == UUID || GoodConfig == State_.PendingUUID)) {
UpgradedUUID = UUID;
State_.PendingUUID = 0;
return false;
}
GWObjects::Device D;
if (!StorageService()->GetDevice(Session,SerialNumber_, D)) {
return false;
}
if(State_.PendingUUID!=0 && UUID==State_.PendingUUID) {
// so we sent an upgrade to a device, and now it is completing now...
UpgradedUUID = UUID;
StorageService()->CompleteDeviceConfigurationChange(Session, SerialNumber_);
State_.PendingUUID = 0;
return true;
}
// dont upgrade a switch if it does not have a real config. Config will always be more than 20 characters
if (D.DeviceType==Platforms::SWITCH && D.Configuration.size()<20) {
return false;
}
Config::Config Cfg(D.Configuration);
// if this is a broken device (UUID==0) just fix it
auto StoredConfigurationUUID = Cfg.UUID();
if(D.UUID==0) {
D.UUID = StoredConfigurationUUID;
}
if (D.UUID == UUID) {
D.UUID = UpgradedUUID = UUID;
State_.PendingUUID = D.pendingUUID = 0;
D.pendingConfiguration.clear();
D.pendingConfigurationCmd.clear();
StorageService()->UpdateDevice(Session, D);
SetCurrentConfigurationID(SerialNumberInt_, UUID);
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID << " Pending:" << State_.PendingUUID << std::endl;
return false;
}
if (UUID > D.UUID) {
// so we have a problem, the device has a newer config than we have. So we need to
// make sure our config is newer.
D.UUID = UUID + 2;
UpgradedUUID = D.UUID;
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID << " Pending:" << State_.PendingUUID << std::endl;
}
Cfg.SetUUID(D.UUID);
D.Configuration = Cfg.get();
D.pendingUUID = State_.PendingUUID = UpgradedUUID = D.UUID;
StorageService()->UpdateDevice(Session, D);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroServiceCreateUUID();
Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM;
Cmd.Status = uCentralProtocol::PENDING;
Cmd.Command = uCentralProtocol::CONFIGURE;
Poco::JSON::Parser P;
auto ParsedConfig = P.parse(D.Configuration).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::UUID, D.UUID);
Params.set(uCentralProtocol::WHEN, 0);
Params.set(uCentralProtocol::CONFIG, ParsedConfig);
std::ostringstream O;
Poco::JSON::Stringifier::stringify(Params, O);
Cmd.Details = O.str();
poco_information(Logger_,
fmt::format("CFG-UPGRADE({}): Current ID: {}, newer configuration {}.",
CId_, UUID, D.UUID));
bool Sent;
StorageService()->AddCommand(SerialNumber_, Cmd,
Storage::CommandExecutionType::COMMAND_EXECUTED);
CommandManager()->PostCommand(
CommandManager()->Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false);
GWWebSocketNotifications::SingleDeviceConfigurationChange_t Notification;
Notification.content.serialNumber = D.SerialNumber;
Notification.content.oldUUID = UUID;
Notification.content.newUUID = UpgradedUUID;
GWWebSocketNotifications::DeviceConfigurationChange(Notification);
// std::cout << __LINE__ << ": " << SerialNumber_ << " GoodConfig: " << GoodConfig << " UUID:" << UUID <<
// " Pending:" << State_.PendingUUID << " Upgraded:" << UpgradedUUID << std::endl;
return true;
}
}

View File

@@ -71,8 +71,9 @@ namespace OpenWifi {
CommandManager()->ClearQueue(SerialNumberInt_);
AP_WS_Server()->StartSession(State_.sessionId, SerialNumberInt_);
AP_WS_Server()->SetSessionDetails(State_.sessionId, SerialNumberInt_);
std::lock_guard Lock(ConnectionMutex_);
Config::Capabilities Caps(Capabilities);
Compatible_ = Caps.Compatible();
@@ -83,8 +84,6 @@ namespace OpenWifi {
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
CId_ = SerialNumber_ + "@" + CId_;
auto Platform = Poco::toLower(Caps.Platform());
if(ParamsObj->has("reason")) {
State_.connectReason = ParamsObj->get("reason").toString();
}
@@ -101,24 +100,36 @@ namespace OpenWifi {
Restrictions_.from_json(RestrictionObject);
}
if (Capabilities->has("developer") && !Capabilities->isNull("developer")) {
if (Capabilities->has("developer")) {
Restrictions_.developer = Capabilities->getValue<bool>("developer");
}
if(Capabilities->has("secure-rtty")) {
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
RttyMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
}
State_.locale = FindCountryFromIP()->Get(IP);
GWObjects::Device DeviceInfo;
std::lock_guard DbSessionLock(DbSession_->Mutex());
auto DeviceExists = StorageService()->GetDevice(DbSession_->Session(), SerialNumber_, DeviceInfo);
auto DeviceExists = StorageService()->GetDevice(SerialNumber_, DeviceInfo);
if (Daemon()->AutoProvisioning() && !DeviceExists) {
// check the firmware version. if this is too old, we cannot let that device connect yet, we must
// force a firmware upgrade
GWObjects::DefaultFirmware MinimumFirmware;
if(FirmwareRevisionCache()->DeviceMustUpgrade(Compatible_, Firmware, MinimumFirmware)) {
/*
{ "jsonrpc" : "2.0" ,
"method" : "upgrade" ,
"params" : {
"serial" : <serial number> ,
"when" : Optional - <UTC time when to upgrade the firmware, 0 mean immediate, this is a suggestion>,
"uri" : <URI to download the firmware>,
"FWsignature" : <string representation of the signature for the FW> (optional)
},
"id" : <some number>
}
*/
Poco::JSON::Object UpgradeCommand, Params;
UpgradeCommand.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
UpgradeCommand.set(uCentralProtocol::METHOD,uCentralProtocol::UPGRADE);
@@ -146,7 +157,7 @@ namespace OpenWifi {
}
return;
} else {
StorageService()->CreateDefaultDevice( DbSession_->Session(),
StorageService()->CreateDefaultDevice(
SerialNumber_, Caps, Firmware, PeerAddress_,
State_.VerifiedCertificate == GWObjects::SIMULATED);
}
@@ -155,7 +166,7 @@ namespace OpenWifi {
poco_warning(Logger(),fmt::format("Device {} is a {} from {} and cannot be provisioned.",SerialNumber_,Compatible_, CId_));
return EndConnection();
} else if (DeviceExists) {
StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps);
int Updated{0};
if (!Firmware.empty()) {
if (Firmware != DeviceInfo.Firmware) {
@@ -206,13 +217,8 @@ namespace OpenWifi {
++Updated;
}
if (Compatible_ != DeviceInfo.Compatible) {
DeviceInfo.Compatible = Compatible_;
++Updated;
}
if (Platform != DeviceInfo.DeviceType) {
DeviceInfo.DeviceType = Platform;
if (Compatible_ != DeviceInfo.DeviceType) {
DeviceInfo.DeviceType = Compatible_;
++Updated;
}
@@ -232,13 +238,12 @@ namespace OpenWifi {
}
if (Updated) {
StorageService()->UpdateDevice(DbSession_->Session(), DeviceInfo);
StorageService()->UpdateDevice(DeviceInfo);
}
}
if(!Simulated_) {
uint64_t UpgradedUUID = 0;
if (LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID)) {
if(!Simulated_) {
uint64_t UpgradedUUID = 0;
LookForUpgrade(UUID, UpgradedUUID);
State_.UUID = UpgradedUUID;
}
}

View File

@@ -29,7 +29,7 @@ namespace OpenWifi {
.Recorded = Utils::Now(),
.LogType = 1,
.UUID = ParamsObj->get(uCentralProtocol::UUID)};
StorageService()->AddLog(*DbSession_, DeviceLog);
StorageService()->AddLog(DeviceLog);
DeviceLogKafkaEvent E(DeviceLog);
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));

View File

@@ -21,7 +21,7 @@ namespace OpenWifi {
if (ParamsObj->has("currentPassword")) {
auto Password = ParamsObj->get("currentPassword").toString();
StorageService()->SetDevicePassword(*DbSession_,Serial, Password);
StorageService()->SetDevicePassword(Serial, Password);
poco_trace(
Logger_,
fmt::format("DEVICE-UPDATE({}): Device is updating its login password.", Serial));

View File

@@ -3,7 +3,6 @@
//
#include "AP_WS_Connection.h"
#include "AP_WS_Server.h"
#include "StorageService.h"
#include "fmt/format.h"
@@ -26,7 +25,6 @@ namespace OpenWifi {
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
auto Sanity = ParamsObj->get(uCentralProtocol::SANITY);
State_.sanity = Sanity;
auto CheckData = ParamsObj->get(uCentralProtocol::DATA).toString();
if (CheckData.empty())
CheckData = uCentralProtocol::EMPTY_JSON_DOC;
@@ -50,14 +48,14 @@ namespace OpenWifi {
Check.Data = CheckData;
Check.Sanity = Sanity;
StorageService()->AddHealthCheckData(*DbSession_, Check);
StorageService()->AddHealthCheckData(Check);
if (!request_uuid.empty()) {
StorageService()->SetCommandResult(request_uuid, CheckData);
}
SetLastHealthCheck(Check);
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableHealthChecks()) {
if (KafkaManager()->Enabled()) {
KafkaManager()->PostMessage(KafkaTopics::HEALTHCHECK, SerialNumber_, *ParamsObj);
}
} else {

View File

@@ -36,7 +36,7 @@ namespace OpenWifi {
.Recorded = (uint64_t)time(nullptr),
.LogType = 0,
.UUID = State_.UUID};
StorageService()->AddLog(*DbSession_, DeviceLog);
StorageService()->AddLog(DeviceLog);
DeviceLogKafkaEvent E(DeviceLog);
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));

View File

@@ -35,7 +35,7 @@ namespace OpenWifi {
.Recorded = ParamsObj->get(uCentralProtocol::DATE),
.LogType = 2,
.UUID = ParamsObj->get(uCentralProtocol::UUID)};
StorageService()->AddLog(*DbSession_, DeviceLog);
StorageService()->AddLog(DeviceLog);
DeviceLogKafkaEvent E(DeviceLog);
} else {
poco_warning(Logger_, fmt::format("REBOOT-LOG({}): Missing parameters.", CId_));

View File

@@ -35,7 +35,7 @@ namespace OpenWifi {
.LogType = 1,
.UUID = 0};
StorageService()->AddLog(*DbSession_, DeviceLog);
StorageService()->AddLog(DeviceLog);
if (ParamsObj->get(uCentralProtocol::REBOOT).toString() == "true") {
GWObjects::CommandDetails Cmd;

View File

@@ -3,7 +3,6 @@
//
#include "AP_WS_Connection.h"
#include "AP_WS_Server.h"
#include "StateUtils.h"
#include "StorageService.h"
@@ -40,27 +39,25 @@ namespace OpenWifi {
UUID, request_uuid));
}
std::lock_guard Guard(DbSession_->Mutex());
if(!Simulated_) {
uint64_t UpgradedUUID;
LookForUpgrade(DbSession_->Session(), UUID, UpgradedUUID);
LookForUpgrade(UUID, UpgradedUUID);
State_.UUID = UpgradedUUID;
}
SetLastStats(StateStr);
GWObjects::Statistics Stats{
.SerialNumber = SerialNumber_, .UUID = UUID, .Data = StateStr};
Stats.Recorded = Utils::Now();
StorageService()->AddStatisticsData(DbSession_->Session(),Stats);
StorageService()->AddStatisticsData(Stats);
if (!request_uuid.empty()) {
StorageService()->SetCommandResult(request_uuid, StateStr);
}
StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
State_.Associations_5G, State_.Associations_6G, State_.uptime);
State_.Associations_5G, State_.Associations_6G);
if (KafkaManager()->Enabled() && !AP_WS_Server()->KafkaDisableState()) {
if (KafkaManager()->Enabled()) {
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, *ParamsObj);
}

View File

@@ -35,7 +35,8 @@ namespace OpenWifi {
}
if (TelemetryWebSocketRefCount_) {
if (now < TelemetryWebSocketTimer_) {
// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
// std::endl;
TelemetryWebSocketPackets_++;
State_.websocketPackets = TelemetryWebSocketPackets_;
TelemetryStream()->NotifyEndPoint(SerialNumberInt_, KafkaPayload);
@@ -45,6 +46,7 @@ namespace OpenWifi {
}
if (TelemetryKafkaRefCount_) {
if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
TelemetryKafkaPackets_++;
State_.kafkaPackets = TelemetryKafkaPackets_;
KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,

62
src/AP_WS_ReactorPool.h Normal file
View File

@@ -0,0 +1,62 @@
//
// Created by stephane bourque on 2022-02-03.
//
#pragma once
#include <mutex>
#include <string>
#include "Poco/Environment.h"
#include "Poco/Net/SocketAcceptor.h"
#include "framework/utils.h"
namespace OpenWifi {
class AP_WS_ReactorThreadPool {
public:
explicit AP_WS_ReactorThreadPool() {
NumberOfThreads_ = Poco::Environment::processorCount() * 4;
if (NumberOfThreads_ == 0)
NumberOfThreads_ = 4;
}
~AP_WS_ReactorThreadPool() { Stop(); }
void Start() {
for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
auto NewReactor = std::make_unique<Poco::Net::SocketReactor>();
auto NewThread = std::make_unique<Poco::Thread>();
NewThread->start(*NewReactor);
std::string ThreadName{"ap:react:" + std::to_string(i)};
Utils::SetThreadName(*NewThread, ThreadName.c_str());
Reactors_.emplace_back(std::move(NewReactor));
Threads_.emplace_back(std::move(NewThread));
}
}
void Stop() {
for (auto &i : Reactors_)
i->stop();
for (auto &i : Threads_) {
i->join();
}
Reactors_.clear();
Threads_.clear();
}
Poco::Net::SocketReactor &NextReactor() {
std::lock_guard Lock(Mutex_);
NextReactor_++;
NextReactor_ %= NumberOfThreads_;
return *Reactors_[NextReactor_];
}
private:
std::mutex Mutex_;
uint64_t NumberOfThreads_;
uint64_t NextReactor_ = 0;
std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
std::vector<std::unique_ptr<Poco::Thread>> Threads_;
};
} // namespace OpenWifi

View File

@@ -1,77 +0,0 @@
//
// Created by stephane bourque on 2022-02-03.
//
#pragma once
#include <mutex>
#include <string>
#include <framework/utils.h>
#include <Poco/Environment.h>
#include <Poco/Net/SocketAcceptor.h>
#include <Poco/Data/SessionPool.h>
#include <StorageService.h>
namespace OpenWifi {
class AP_WS_ReactorThreadPool {
public:
explicit AP_WS_ReactorThreadPool(Poco::Logger &Logger) : Logger_(Logger) {
NumberOfThreads_ = Poco::Environment::processorCount() * 4;
if (NumberOfThreads_ == 0)
NumberOfThreads_ = 8;
NumberOfThreads_ = std::min(NumberOfThreads_, (std::uint64_t) 128);
}
~AP_WS_ReactorThreadPool() { Stop(); }
void Start() {
Reactors_.reserve(NumberOfThreads_);
DbSessions_.reserve(NumberOfThreads_);
Threads_.reserve(NumberOfThreads_);
Logger_.information(fmt::format("WebSocket Processor: starting {} threads.", NumberOfThreads_));
for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
auto NewReactor = std::make_shared<Poco::Net::SocketReactor>();
auto NewThread = std::make_unique<Poco::Thread>();
NewThread->start(*NewReactor);
std::string ThreadName{"ap:react:" + std::to_string(i)};
Utils::SetThreadName(*NewThread, ThreadName.c_str());
Reactors_.emplace_back(std::move(NewReactor));
Threads_.emplace_back(std::move(NewThread));
DbSessions_.emplace_back(std::make_shared<LockedDbSession>());
}
Logger_.information(fmt::format("WebSocket Processor: {} threads started.", NumberOfThreads_));
}
void Stop() {
for (auto &i : Reactors_)
i->stop();
for (auto &i : Threads_) {
i->join();
}
Reactors_.clear();
Threads_.clear();
DbSessions_.clear();
}
auto NextReactor() {
std::lock_guard Lock(Mutex_);
NextReactor_++;
NextReactor_ %= NumberOfThreads_;
return std::make_pair(Reactors_[NextReactor_], DbSessions_[NextReactor_]);
}
private:
std::mutex Mutex_;
uint64_t NumberOfThreads_;
uint64_t NextReactor_ = 0;
std::vector<std::shared_ptr<Poco::Net::SocketReactor>> Reactors_;
std::vector<std::unique_ptr<Poco::Thread>> Threads_;
std::vector<std::shared_ptr<LockedDbSession>> DbSessions_;
Poco::Logger &Logger_;
};
} // namespace OpenWifi

View File

@@ -6,66 +6,32 @@
// Arilia Wireless Inc.
//
#include <Poco/Net/Context.h>
#include <Poco/Net/HTTPHeaderStream.h>
#include <Poco/Net/HTTPServerRequest.h>
#include "Poco/Net/Context.h"
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPServerRequest.h"
#include <AP_WS_Connection.h>
#include <AP_WS_Server.h>
#include <ConfigurationCache.h>
#include <TelemetryStream.h>
#include "AP_WS_Connection.h"
#include "AP_WS_Server.h"
#include "ConfigurationCache.h"
#include "TelemetryStream.h"
#include <fmt/format.h>
#include <framework/MicroServiceFuncs.h>
#include <framework/utils.h>
#include "UI_GW_WebSocketNotifications.h"
#include "fmt/format.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
#include <framework/KafkaManager.h>
#include <UI_GW_WebSocketNotifications.h>
namespace OpenWifi {
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
public:
explicit AP_WS_RequestHandler(Poco::Logger &L, std::uint64_t session_id) : Logger_(L),
session_id_(session_id) {
};
void handleRequest( Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override {
try {
auto NewConnection = std::make_shared<AP_WS_Connection>(request, response, session_id_, Logger_,
AP_WS_Server()->NextReactor());
AP_WS_Server()->AddConnection(NewConnection);
NewConnection->Start();
} catch (...) {
poco_warning(Logger_, "Exception during WS creation");
}
};
private:
Poco::Logger &Logger_;
std::uint64_t session_id_;
};
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
inline Poco::Net::HTTPRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
if (request.find("Upgrade") != request.end() &&
Poco::icompare(request["Upgrade"], "websocket") == 0) {
Utils::SetThreadName("ws:conn-init");
session_id_++;
return new AP_WS_RequestHandler(Logger_, session_id_);
} else {
return nullptr;
}
void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) {
try {
AP_WS_Server()->AddConnection(
id_, std::make_shared<AP_WS_Connection>(request, response, id_, Logger_,
AP_WS_Server()->NextReactor()));
} catch (...) {
poco_warning(Logger_, "Exception during WS creation");
}
private:
Poco::Logger &Logger_;
inline static std::atomic_uint64_t session_id_ = 0;
};
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
@@ -91,7 +57,7 @@ namespace OpenWifi {
SessionTimeOut_ = MicroServiceConfigGetInt("openwifi.session.timeout", 10*60);
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>(Logger());
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
Reactor_pool_->Start();
for (const auto &Svr : ConfigServersList_) {
@@ -169,9 +135,6 @@ namespace OpenWifi {
WebServerHttpParams);
WebServers_.push_back(std::move(NewWebServer));
}
KafkaDisableState_ = MicroServiceConfigGetBool("openwifi.kafka.disablestate", false);
KafkaDisableHealthChecks_ = MicroServiceConfigGetBool("openwifi.kafka.disablehealthchecks", false);
}
for (auto &server : WebServers_) {
@@ -193,420 +156,243 @@ namespace OpenWifi {
UseDefaultConfig_ = true;
}
SimulatorId_ = Poco::toLower(MicroServiceConfigGetString("simulatorid", ""));
SimulatorId_ = MicroServiceConfigGetString("simulatorid", "");
SimulatorEnabled_ = !SimulatorId_.empty();
Utils::SetThreadName(ReactorThread_, "dev:react:head");
GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(
*this, &AP_WS_Server::onGarbageCollecting);
Timer_.setStartInterval(10 * 1000);
Timer_.setPeriodicInterval(10 * 1000); // every minute
Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool());
Running_ = true;
GarbageCollector_.setName("ws:garbage");
GarbageCollector_.start(*this);
std::thread CleanupThread([this](){ CleanupSessions(); });
CleanupThread.detach();
return 0;
}
bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
SerialNumbers_[hashIndex].erase(DeviceHint);
}
void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) {
static uint64_t last_log = Utils::Now(), last_zombie_run = 0;
auto now = Utils::Now();
{
auto H = SessionHash::Hash(Connection->State_.sessionId);
std::lock_guard SessionLock(SessionMutex_[H]);
Sessions_[H].erase(Connection->State_.sessionId);
}
return true;
}
void AP_WS_Server::CleanupSessions() {
while(Running_) {
std::this_thread::sleep_for(std::chrono::seconds(10));
while(Running_ && !CleanupSessions_.empty()) {
std::pair<uint64_t, uint64_t> Session;
{
std::lock_guard G(CleanupMutex_);
Session = CleanupSessions_.front();
CleanupSessions_.pop_front();
{
std::lock_guard SessionLock(SessionMutex_);
if (!Garbage_.empty()) {
Garbage_.clear();
}
poco_trace(this->Logger(),fmt::format("Cleaning up session: {} for device: {}", Session.first, Utils::IntToSerialNumber(Session.second)));
EndSession(Session.first, Session.second);
}
}
}
void AP_WS_Server::run() {
uint64_t last_log = Utils::Now(),
last_zombie_run = 0,
last_garbage_run = 0;
Poco::Logger &LocalLogger = Poco::Logger::create(
"WS-Session-Janitor", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel());
while(Running_) {
if(!Poco::Thread::trySleep(30000)) {
break;
}
LocalLogger.information(fmt::format("Garbage collecting starting run." ));
uint64_t total_connected_time = 0;
uint64_t total_connected_time = 0, now = Utils::Now();
if(now-last_zombie_run > 60) {
try {
poco_information(LocalLogger,
fmt::format("Garbage collecting zombies... (step 1)"));
NumberOfConnectingDevices_ = 0;
AverageDeviceConnectionTime_ = 0;
int waits = 0;
for (int hashIndex = 0; hashIndex < MACHash::HashMax(); hashIndex++) {
last_zombie_run = now;
waits = 0;
while (true) {
if (SerialNumbersMutex_[hashIndex].try_lock()) {
waits = 0;
auto hint = SerialNumbers_[hashIndex].begin();
while (hint != end(SerialNumbers_[hashIndex])) {
if (hint->second == nullptr) {
poco_information(
LocalLogger,
fmt::format("Dead device found in hash index {}", hashIndex));
hint = SerialNumbers_[hashIndex].erase(hint);
} else {
auto Device = hint->second;
auto RightNow = Utils::Now();
if (Device->Dead_) {
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
++hint;
// hint = SerialNumbers_[hashIndex].erase(hint);
} else if (RightNow > Device->LastContact_ &&
(RightNow - Device->LastContact_) > SessionTimeOut_) {
poco_information(
LocalLogger,
fmt::format(
"{}: Session seems idle. Controller disconnecting device.",
Device->SerialNumber_));
// hint = SerialNumbers_[hashIndex].erase(hint);
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
++hint;
} else {
if (Device->State_.Connected) {
total_connected_time +=
(RightNow - Device->State_.started);
}
++hint;
}
}
}
SerialNumbersMutex_[hashIndex].unlock();
break;
} else if (waits < 5) {
waits++;
Poco::Thread::trySleep(10);
} else {
break;
}
if(now-last_zombie_run > 20) {
poco_information(Logger(), fmt::format("Garbage collecting..."));
std::vector<std::uint64_t> SessionsToRemove;
NumberOfConnectedDevices_ = 0;
NumberOfConnectingDevices_ = 0;
AverageDeviceConnectionTime_ = 0;
last_zombie_run = now;
for(int hashIndex=0;hashIndex<256;hashIndex++) {
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto hint = SerialNumbers_[hashIndex].begin();
while (hint != end(SerialNumbers_[hashIndex])) {
if (hint->second.second == nullptr) {
hint = SerialNumbers_[hashIndex].erase(hint);
} else if ((now - hint->second.second->State_.LastContact) >
SessionTimeOut_) {
hint->second.second->EndConnection(false);
poco_information(
Logger(),
fmt::format(
"{}: Session seems idle. Controller disconnecting device.",
hint->second.second->SerialNumber_));
SessionsToRemove.emplace_back(hint->second.first);
Garbage_.push_back(hint->second.second);
hint = SerialNumbers_[hashIndex].erase(hint);
} else if (hint->second.second->State_.Connected) {
NumberOfConnectedDevices_++;
total_connected_time += (now - hint->second.second->State_.started);
hint++;
} else {
NumberOfConnectingDevices_++;
hint++;
}
}
}
poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
LeftOverSessions_ = 0;
for (int i = 0; i < SessionHash::HashMax(); i++) {
waits = 0;
while (true) {
if (SessionMutex_[i].try_lock()) {
waits = 0;
auto hint = Sessions_[i].begin();
auto RightNow = Utils::Now();
while (hint != end(Sessions_[i])) {
if (hint->second == nullptr) {
hint = Sessions_[i].erase(hint);
} else if (hint->second->Dead_) {
// hint = Sessions_[i].erase(hint);
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
++hint;
} else if (RightNow > hint->second->LastContact_ &&
(RightNow - hint->second->LastContact_) >
SessionTimeOut_) {
poco_information(
LocalLogger,
fmt::format("{}: Session seems idle. Controller disconnecting device.",
hint->second->SerialNumber_));
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
++hint;
// hint = Sessions_[i].erase(hint);
} else {
++LeftOverSessions_;
++hint;
}
}
SessionMutex_[i].unlock();
break;
} else if (waits < 5) {
Poco::Thread::trySleep(10);
waits++;
} else {
break;
}
}
if(SessionsToRemove.empty()) {
poco_information(Logger(), fmt::format("Removing {} sessions.", SessionsToRemove.size()));
std::lock_guard Lock(SessionMutex_);
for (const auto &Session : SessionsToRemove) {
Sessions_.erase(Session);
}
AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
? total_connected_time / NumberOfConnectedDevices_
: 0;
poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
} catch (const Poco::Exception &E) {
poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
} catch (const std::exception &E) {
poco_error(LocalLogger, fmt::format("std::exception: Garbage collecting zombies failed: {}", E.what()));
} catch (...) {
poco_error(LocalLogger, fmt::format("exception:Garbage collecting zombies failed: {}", "unknown"));
}
AverageDeviceConnectionTime_ =
NumberOfConnectedDevices_ > 0 ? total_connected_time / NumberOfConnectedDevices_
: 0;
poco_information(Logger(), fmt::format("Garbage collecting done..."));
} else {
std::lock_guard SessionLock(SessionMutex_);
NumberOfConnectedDevices_ = Sessions_.size();
AverageDeviceConnectionTime_ += 10;
}
if(NumberOfConnectedDevices_) {
if (last_garbage_run > 0) {
AverageDeviceConnectionTime_ += (now - last_garbage_run);
}
}
try {
if ((now - last_log) > 60) {
last_log = now;
poco_information(
LocalLogger,
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds. Left Over Sessions: {}",
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
AverageDeviceConnectionTime_, LeftOverSessions_));
}
GWWebSocketNotifications::NumberOfConnection_t Notification;
Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
Notification.content.numberOfDevices = NumberOfConnectedDevices_;
Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
GetTotalDataStatistics(Notification.content.tx, Notification.content.rx);
GWWebSocketNotifications::NumberOfConnections(Notification);
Poco::JSON::Object KafkaNotification;
Notification.to_json(KafkaNotification);
Poco::JSON::Object FullEvent;
FullEvent.set("type", "load-update");
FullEvent.set("timestamp", now);
FullEvent.set("payload", KafkaNotification);
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
LocalLogger.information(fmt::format("Garbage collection finished run."));
last_garbage_run = now;
} catch (const Poco::Exception &E) {
LocalLogger.error(fmt::format("Poco::Exception: Garbage collecting failed: {}", E.displayText()));
} catch (const std::exception &E) {
LocalLogger.error(fmt::format("std::exception: Garbage collecting failed: {}", E.what()));
} catch (...) {
LocalLogger.error(fmt::format("exception:Garbage collecting failed: {}", "unknown"));
if ((now - last_log) > 120) {
last_log = now;
poco_information(Logger(),
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds",
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
AverageDeviceConnectionTime_));
}
}
LocalLogger.information(fmt::format("Garbage collector done for the day." ));
GWWebSocketNotifications::NumberOfConnection_t Notification;
Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
Notification.content.numberOfDevices = NumberOfConnectedDevices_;
Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
GetTotalDataStatistics(Notification.content.tx,Notification.content.rx);
GWWebSocketNotifications::NumberOfConnections(Notification);
Poco::JSON::Object KafkaNotification;
Notification.to_json(KafkaNotification);
Poco::JSON::Object FullEvent;
FullEvent.set("type", "load-update");
FullEvent.set("timestamp", now);
FullEvent.set("payload", KafkaNotification);
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, "system", FullEvent);
}
void AP_WS_Server::Stop() {
poco_information(Logger(), "Stopping...");
Running_ = false;
GarbageCollector_.wakeUp();
GarbageCollector_.join();
Timer_.stop();
for (auto &server : WebServers_) {
server->stopAll();
}
Reactor_pool_->Stop();
Reactor_.stop();
ReactorThread_.join();
poco_information(Logger(), "Stopped...");
}
bool AP_WS_Server::GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
SerialNumbers.clear();
for(int i=0;i<SessionHash::HashMax();i++) {
std::lock_guard Lock(SessionMutex_[i]);
for (const auto &connection : Sessions_[i]) {
if (connection.second->RawLastHealthcheck_.Sanity >= lowLimit &&
connection.second->RawLastHealthcheck_.Sanity <= highLimit) {
SerialNumbers.push_back(connection.second->SerialNumber_);
}
}
}
return true;
}
bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
return false;
}
Connection->GetLastStats(Statistics);
Device->second.second->GetLastStats(Statistics);
return true;
}
bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == SerialNumbers_[hashIndex].end() ||
DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
return false;
}
Connection->GetState(State);
Device->second.second->GetState(State);
return true;
}
bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
GWObjects::HealthCheck &CheckData) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == SerialNumbers_[hashIndex].end() || Device->second == nullptr) {
return false;
}
Connection = Device->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == SerialNumbers_[hashIndex].end() || Device->second.second == nullptr) {
return false;
}
Connection->GetLastHealthCheck(CheckData);
Device->second.second->GetLastHealthCheck(CheckData);
return true;
}
void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
auto sessionHash = SessionHash::Hash(session_id);
std::shared_ptr<AP_WS_Connection> Connection;
{
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
auto SessionHint = Sessions_[sessionHash].find(session_id);
if (SessionHint == end(Sessions_[sessionHash])) {
return;
}
Connection = SessionHint->second;
Sessions_[sessionHash].erase(SessionHint);
}
void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
std::lock_guard SessionLock(SessionMutex_);
auto Conn = Sessions_.find(connection_id);
if (Conn == end(Sessions_))
return;
auto deviceHash = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[deviceHash]);
SerialNumbers_[deviceHash][SerialNumber] = Connection;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto CurrentSerialNumber = SerialNumbers_[hashIndex].find(SerialNumber);
if ((CurrentSerialNumber == SerialNumbers_[hashIndex].end()) ||
(CurrentSerialNumber->second.first < connection_id)) {
SerialNumbers_[hashIndex][SerialNumber] = std::make_pair(connection_id, Conn->second);
return;
}
}
bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
{
poco_trace(Logger(), fmt::format("Ending session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
auto sessionHash = SessionHash::Hash(session_id);
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
Sessions_[sessionHash].erase(session_id);
poco_trace(Logger(), fmt::format("Ended session 1: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
std::lock_guard SessionLock(SessionMutex_);
auto Session = Sessions_.find(session_id);
if (Session == end(Sessions_))
return false;
Garbage_.push_back(Session->second);
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex])) {
Sessions_.erase(Session);
return false;
}
{
auto hashIndex = MACHash::Hash(SerialNumber);
poco_trace(Logger(), fmt::format("Ending session 2.0: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
poco_trace(Logger(), fmt::format("Ending session 2.1: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
poco_trace(Logger(), fmt::format("Ending session 2.2: {} for device: {} hi:{}", session_id, Utils::IntToSerialNumber(SerialNumber), hashIndex));
if (DeviceHint == SerialNumbers_[hashIndex].end()
|| DeviceHint->second == nullptr
|| DeviceHint->second->State_.sessionId != session_id) {
poco_trace(Logger(), fmt::format("Did not end session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
return false;
}
SerialNumbers_[hashIndex].erase(DeviceHint);
poco_trace(Logger(), fmt::format("Ended session 2: {} for device: {}", session_id, Utils::IntToSerialNumber(SerialNumber)));
if (Device->second.first == session_id) {
Sessions_.erase(Session);
SerialNumbers_[hashIndex].erase(Device);
return true;
}
return true;
Sessions_.erase(Session);
return false;
}
bool AP_WS_Server::Connected(uint64_t SerialNumber,
GWObjects::DeviceRestrictions &Restrictions) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
Restrictions = Connection->GetRestrictions();
return Connection->State_.Connected;
Device->second.second->GetRestrictions(Restrictions);
return Device->second.second->State_.Connected;
}
bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
return Connection->State_.Connected;
return Device->second.second->State_.Connected;
}
bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
auto hashIndex = MACHash::Hash(SerialNumber);
std::shared_ptr<AP_WS_Connection> Connection;
{
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
try {
return Connection->Send(Payload);
return Device->second.second->Send(Payload);
} catch (...) {
poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
Utils::IntToSerialNumber(SerialNumber)));
@@ -615,64 +401,48 @@ namespace OpenWifi {
}
void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second == nullptr) {
return;
}
Connection = Device->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return;
}
Connection->StopWebSocketTelemetry(RPCID);
Device->second.second->StopWebSocketTelemetry(RPCID);
}
void
AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return;
}
Connection->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
Device->second.second->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
}
void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return;
}
Connection->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
Device->second.second->SetKafkaTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
}
void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return;
}
Connection->StopKafkaTelemetry(RPCID);
Device->second.second->StopKafkaTelemetry(RPCID);
}
void AP_WS_Server::GetTelemetryParameters(
@@ -681,18 +451,14 @@ namespace OpenWifi {
uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(SerialNumber);
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return;
}
Connection = DeviceHint->second;
auto hashIndex = Utils::CalculateMacAddressHash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(SerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return;
}
Connection->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
Device->second.second->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
TelemetryWebSocketTimer, TelemetryKafkaTimer,
TelemetryWebSocketCount, TelemetryKafkaCount,
TelemetryWebSocketPackets, TelemetryKafkaPackets);
@@ -701,24 +467,16 @@ namespace OpenWifi {
bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = MACHash::Hash(IntSerialNumber);
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
try {
return Connection->SendRadiusAccountingData(buffer, size);
return Device->second.second->SendRadiusAccountingData(buffer, size);
} catch (...) {
poco_debug(
Logger(),
@@ -730,24 +488,16 @@ namespace OpenWifi {
bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = MACHash::Hash(IntSerialNumber);
std::lock_guard DevicesLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
try {
return Connection->SendRadiusAuthenticationData(buffer, size);
return Device->second.second->SendRadiusAuthenticationData(buffer, size);
} catch (...) {
poco_debug(
Logger(),
@@ -759,23 +509,16 @@ namespace OpenWifi {
bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = MACHash::Hash(IntSerialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr) {
return false;
}
Connection = DeviceHint->second;
}
if(Connection->Dead_) {
auto IntSerialNumber = Utils::SerialNumberToInt(SerialNumber);
auto hashIndex = Utils::CalculateMacAddressHash(IntSerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[hashIndex]);
auto Device = SerialNumbers_[hashIndex].find(IntSerialNumber);
if (Device == end(SerialNumbers_[hashIndex]) || Device->second.second == nullptr) {
return false;
}
try {
return Connection->SendRadiusCoAData(buffer, size);
return Device->second.second->SendRadiusCoAData(buffer, size);
} catch (...) {
poco_debug(Logger(),
fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",

View File

@@ -24,51 +24,46 @@
#include "Poco/Timer.h"
#include "AP_WS_Connection.h"
#include "AP_WS_Reactor_Pool.h"
#include "AP_WS_ReactorPool.h"
#include "framework/SubSystemServer.h"
#include "framework/utils.h"
namespace OpenWifi {
constexpr uint MACHashMax = 256;
constexpr uint MACHashMask = MACHashMax-1;
class MACHash {
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
public:
[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
uint8_t hash = 0, i=6;
while(i) {
hash ^= (value & MACHashMask) + 1;
value >>= 8;
--i;
explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id){};
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
private:
Poco::Logger &Logger_;
uint64_t id_ = 0;
};
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
inline Poco::Net::HTTPRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
if (request.find("Upgrade") != request.end() &&
Poco::icompare(request["Upgrade"], "websocket") == 0) {
Utils::SetThreadName("ws:conn-init");
return new AP_WS_RequestHandler(Logger_, id_++);
} else {
return nullptr;
}
return hash;
}
[[nodiscard]] static inline uint16_t Hash(const std::string & value) {
return Hash(Utils::MACToInt(value));
}
[[nodiscard]] static inline uint16_t HashMax() {
return MACHashMax;
}
private:
Poco::Logger &Logger_;
inline static uint64_t id_ = 1;
};
constexpr uint SessionHashMax = 256;
constexpr uint SessionHashMask = SessionHashMax-1;
class SessionHash {
public:
[[nodiscard]] static inline uint16_t Hash(std::uint64_t value) {
return (value & SessionHashMask);
}
[[nodiscard]] static inline uint16_t HashMax() {
return SessionHashMax;
}
};
class AP_WS_Server : public SubSystemServer, public Poco::Runnable {
class AP_WS_Server : public SubSystemServer {
public:
static auto instance() {
static auto instance_ = new AP_WS_Server;
@@ -82,50 +77,48 @@ namespace OpenWifi {
const Poco::Crypto::X509Certificate &Certificate);
inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
return IsSim(SerialNumber) &&
SerialNumber == SimulatorId_;
return IsSim(Poco::toLower(SerialNumber)) &&
Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
}
inline static bool IsSim(const std::string &SerialNumber) {
return SerialNumber.substr(0, 6) == "53494d";
}
void run() override; // Garbage collector thread.
[[nodiscard]] inline bool IsSimEnabled() const { return SimulatorEnabled_; }
[[nodiscard]] inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
[[nodiscard]] inline uint64_t MismatchDepth() const { return MismatchDepth_; }
[[nodiscard]] inline bool UseProvisioning() const { return LookAtProvisioning_; }
[[nodiscard]] inline bool UseDefaults() const { return UseDefaultConfig_; }
[[nodiscard]] inline bool Running() const { return Running_; }
[[nodiscard]] inline std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> NextReactor() {
inline bool IsSimEnabled() const { return SimulatorEnabled_; }
inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
inline uint64_t MismatchDepth() const { return MismatchDepth_; }
inline bool UseProvisioning() const { return LookAtProvisioning_; }
inline bool UseDefaults() const { return UseDefaultConfig_; }
[[nodiscard]] inline Poco::Net::SocketReactor &NextReactor() {
return Reactor_pool_->NextReactor();
}
[[nodiscard]] inline bool Running() const { return Running_; }
inline void AddConnection(std::shared_ptr<AP_WS_Connection> Connection) {
std::uint64_t sessionHash = SessionHash::Hash(Connection->State_.sessionId);
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
if(Sessions_[sessionHash].find(Connection->State_.sessionId)==end(Sessions_[sessionHash])) {
Sessions_[sessionHash][Connection->State_.sessionId] = std::move(Connection);
}
inline void AddConnection(uint64_t session_id,
std::shared_ptr<AP_WS_Connection> Connection) {
std::lock_guard Lock(SessionMutex_);
Sessions_[session_id] = std::move(Connection);
}
[[nodiscard]] inline bool DeviceRequiresSecureRTTY(uint64_t serialNumber) const {
std::shared_ptr<AP_WS_Connection> Connection;
{
auto hashIndex = MACHash::Hash(serialNumber);
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
auto DeviceHint = SerialNumbers_[hashIndex].find(serialNumber);
if (DeviceHint == end(SerialNumbers_[hashIndex]) || DeviceHint->second == nullptr)
return false;
Connection = DeviceHint->second;
}
return Connection->RTTYMustBeSecure_;
inline bool DeviceRequiresSecureRtty(uint64_t serialNumber) const {
auto hashIndex = Utils::CalculateMacAddressHash(serialNumber);
std::lock_guard G(SerialNumbersMutex_[hashIndex]);
auto Connection = SerialNumbers_[hashIndex].find(serialNumber);
if (Connection==end(SerialNumbers_[hashIndex]) || Connection->second.second==nullptr)
return false;
return Connection->second.second->RttyMustBeSecure_;
}
inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
}
[[nodiscard]] bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
inline bool GetState(const std::string &SerialNumber,
GWObjects::ConnectionState &State) const {
@@ -141,8 +134,13 @@ namespace OpenWifi {
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
bool Connected(uint64_t SerialNumber) const;
bool Disconnect(uint64_t SerialNumber);
inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
}
bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
bool SendRadiusAuthenticationData(const std::string &SerialNumber,
const unsigned char *buffer, std::size_t size);
bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
@@ -150,8 +148,9 @@ namespace OpenWifi {
bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
std::size_t size);
void StartSession(uint64_t session_id, uint64_t SerialNumber);
bool EndSession(uint64_t session_id, uint64_t SerialNumber);
void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber);
bool EndSession(uint64_t connection_id, uint64_t serial_number);
bool EndSessionUnSafe(uint64_t session_id, uint64_t serial_number);
void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes);
@@ -168,9 +167,7 @@ namespace OpenWifi {
uint64_t &TelemetryWebSocketPackets,
uint64_t &TelemetryKafkaPackets);
bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers);
// bool ExtendedAttributes(const std::string &serialNumber, bool & hasGPS, std::uint64_t &Sanity,
// std::double_t &MemoryUsed, std::double_t &Load, std::double_t &Temperature);
void onGarbageCollecting(Poco::Timer &timer);
inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
uint64_t &NumberOfConnectingDevices) const {
@@ -179,80 +176,94 @@ namespace OpenWifi {
NumberOfConnectingDevices = NumberOfConnectingDevices_;
}
inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
}
inline void AddRX(std::uint64_t bytes) {
std::lock_guard G(StatsMutex_);
RX_ += bytes;
}
inline void AddTX(std::uint64_t bytes) {
std::lock_guard G(StatsMutex_);
TX_ += bytes;
}
inline void GetTotalDataStatistics(std::uint64_t &TX, std::uint64_t &RX) const {
std::lock_guard G(StatsMutex_);
TX = TX_;
RX = RX_;
}
bool KafkaDisableState() const { return KafkaDisableState_; }
bool KafkaDisableHealthChecks() const { return KafkaDisableHealthChecks_; }
inline void IncrementConnectionCount() {
++NumberOfConnectedDevices_;
// TOD: move to hash based map.
inline bool GetHealthDevices(std::uint64_t lowLimit, std::uint64_t highLimit, std::vector<std::string> & SerialNumbers) {
std::lock_guard Lock(SessionMutex_);
for(const auto &connection:Sessions_) {
if( connection.second->RawLastHealthcheck_.Sanity>=lowLimit &&
connection.second->RawLastHealthcheck_.Sanity<=highLimit) {
SerialNumbers.push_back(connection.second->SerialNumber_);
}
}
return true;
}
inline void DecrementConnectionCount() {
--NumberOfConnectedDevices_;
}
inline bool ExtendedAttributes(const std::string &serialNumber,
bool & hasGPS,
std::uint64_t &Sanity,
std::double_t &MemoryUsed,
std::double_t &Load,
std::double_t &Temperature
) {
inline void AddCleanupSession(uint64_t session_id, uint64_t SerialNumber) {
std::lock_guard G(CleanupMutex_);
CleanupSessions_.emplace_back(session_id, SerialNumber);
auto serialNumberInt = Utils::SerialNumberToInt(serialNumber);
auto hashIndex = Utils::CalculateMacAddressHash(serialNumberInt);
std::lock_guard G(SerialNumbersMutex_[hashIndex]);
auto session_hint = SerialNumbers_[hashIndex].find(Utils::SerialNumberToInt(serialNumber));
if(session_hint==end(SerialNumbers_[hashIndex])) {
return false;
}
hasGPS = session_hint->second.second->hasGPS;
Sanity = session_hint->second.second->RawLastHealthcheck_.Sanity;
MemoryUsed = session_hint->second.second->memory_used_;
Load = session_hint->second.second->cpu_load_;
Temperature = session_hint->second.second->temperature_;
return true;
}
void CleanupSessions();
private:
std::array<std::mutex,SessionHashMax> SessionMutex_;
std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
using SerialNumberMap = std::map<uint64_t /* serial number */,
std::shared_ptr<AP_WS_Connection>>;
std::array<SerialNumberMap,MACHashMax> SerialNumbers_;
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
mutable std::mutex SessionMutex_;
mutable std::mutex StatsMutex_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
std::string SimulatorId_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64};
bool LookAtProvisioning_ = false;
bool UseDefaultConfig_ = true;
bool SimulatorEnabled_ = false;
bool AllowSerialNumberMismatch_ = true;
Poco::Thread CleanupThread_;
std::mutex CleanupMutex_;
std::deque<std::pair<uint64_t, uint64_t>> CleanupSessions_;
std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
std::atomic_bool Running_ = false;
std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_;
std::uint64_t MismatchDepth_ = 2;
using SerialNumberMap = std::map<uint64_t /* serial number */, std::pair<uint64_t /* session id*/,
std::shared_ptr<AP_WS_Connection>>>;
std::atomic_uint64_t NumberOfConnectedDevices_ = 0;
std::atomic_uint64_t AverageDeviceConnectionTime_ = 0;
std::array<SerialNumberMap,256> SerialNumbers_;
mutable std::array<std::mutex,256> SerialNumbersMutex_;
std::atomic_bool AllowSerialNumberMismatch_ = true;
std::atomic_uint64_t MismatchDepth_ = 2;
std::uint64_t NumberOfConnectedDevices_ = 0;
std::uint64_t AverageDeviceConnectionTime_ = 0;
std::uint64_t NumberOfConnectingDevices_ = 0;
std::uint64_t SessionTimeOut_ = 10*60;
std::uint64_t LeftOverSessions_ = 0;
std::atomic_uint64_t TX_=0,RX_=0;
std::atomic_bool KafkaDisableState_=false,
KafkaDisableHealthChecks_=false;
std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_;
Poco::Thread GarbageCollector_;
std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_;
Poco::Timer Timer_;
Poco::Thread GarbageCollector_;
AP_WS_Server() noexcept
: SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}

View File

@@ -10,7 +10,6 @@
#include <string>
#include "framework/MicroServiceFuncs.h"
#include "framework/ow_constants.h"
#include "CentralConfig.h"
#include "nlohmann/json.hpp"
@@ -35,7 +34,7 @@ namespace OpenWifi {
std::lock_guard G(Mutex_);
if (!PlatformsLoaded_)
LoadPlatforms();
auto P = Poco::toLower(Caps.Platform());
auto P = Poco::toUpper(Caps.Platform());
auto Hint = Platforms_.find(Caps.Compatible());
if (Hint == Platforms_.end()) {
Platforms_.insert(std::make_pair(Caps.Compatible(), P));
@@ -69,7 +68,7 @@ namespace OpenWifi {
auto Hint = Platforms_.find(DeviceType);
if (Hint == Platforms_.end())
return Platforms::AP;
return "AP";
return Hint->second;
}
@@ -111,7 +110,7 @@ namespace OpenWifi {
i >> cache;
for (const auto &[Type, Platform] : cache.items()) {
Platforms_[Type] = Poco::toLower(to_string(Platform));
Platforms_[Type] = Platform;
}
} catch (...) {
}

View File

@@ -204,17 +204,6 @@ namespace OpenWifi::Config {
return false;
}
std::uint64_t Config::UUID() {
try {
Poco::JSON::Parser Parser;
auto object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
if (object->has("uuid"))
return object->get("uuid");
} catch (...) {
}
return 0;
}
bool Config::Valid() {
try {
Poco::JSON::Parser Parser;
@@ -265,11 +254,7 @@ namespace OpenWifi::Config {
Model_ = Caps->get("model").toString();
if (Caps->has("platform"))
Platform_ = Poco::toLower(Caps->get("platform").toString());
if(Compatible_.empty()) {
Compatible_ = Model_;
}
Platform_ = Caps->get("platform").toString();
std::ostringstream OS;
Caps->stringify(OS);

View File

@@ -23,7 +23,6 @@ namespace OpenWifi::Config {
[[nodiscard]] std::string get() { return Config_; };
[[nodiscard]] std::string Default();
[[nodiscard]] Poco::JSON::Object::Ptr to_json();
[[nodiscard]] std::uint64_t UUID();
private:
void Init();

View File

@@ -45,9 +45,11 @@ namespace OpenWifi {
std::lock_guard Lock(LocalMutex_);
auto RPC = OutStandingRequests_.find(ID);
if (RPC == OutStandingRequests_.end()) {
// std::cout << __LINE__ << std::endl;
poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
SerialNumberStr, ID));
} else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
// std::cout << __LINE__ << std::endl;
poco_debug(
Logger(),
fmt::format("({}): RPC {} serial number mismatch {}!={}.",
@@ -58,6 +60,7 @@ namespace OpenWifi {
std::chrono::duration<double, std::milli> rpc_execution_time =
std::chrono::high_resolution_clock::now() -
RPC->second.submitted;
// std::cout << __LINE__ << std::endl;
poco_debug(Logger(),
fmt::format("({}): Received RPC answer {}. Command={}",
SerialNumberStr, ID,
@@ -137,6 +140,7 @@ namespace OpenWifi {
}
}
} else {
// std::cout << __LINE__ << std::endl;
}
Command.State = 0;
@@ -159,6 +163,7 @@ namespace OpenWifi {
if (Command.rpc_entry) {
TmpRpcEntry = Command.rpc_entry;
}
// std::cout << __LINE__ << " State=" << Command.State << std::endl;
if (Command.State == 2) {
// look at the payload to see if we should continue or not...
if (Payload->has("result")) {
@@ -168,10 +173,12 @@ namespace OpenWifi {
std::uint64_t Error = Status->get("error");
if (Error == 0) {
// std::cout << __LINE__ << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload,
rpc_execution_time, true);
Command.State = 1;
} else {
// std::cout << __LINE__ << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload,
rpc_execution_time, true);
std::string ErrorTxt = Status->get("result");
@@ -179,11 +186,14 @@ namespace OpenWifi {
Command.State = 0;
}
} else {
// std::cout << __LINE__ << std::endl;
}
} else {
// std::cout << __LINE__ << std::endl;
Command.State = 0;
}
} else if (Command.State == 1) {
// std::cout << "Completing script 2 phase commit." << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
if (Command.Deferred) {
Reply = false;
@@ -192,6 +202,7 @@ namespace OpenWifi {
}
if (Command.State == 0) {
// std::cout << __LINE__ << " State=" << Command.State << std::endl;
OutStandingRequests_.erase(Command.Id);
}
if (Reply && TmpRpcEntry != nullptr)
@@ -251,6 +262,8 @@ namespace OpenWifi {
for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
if (delta > 10min) {
// std::cout << __LINE__ << " -->> " << request->second.Id <<
// std::endl;
MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
APCommands::to_string(request->second.Command),
Utils::IntToSerialNumber(request->second.SerialNumber)));
@@ -262,6 +275,8 @@ namespace OpenWifi {
StorageService()->SetCommandTimedOut(request->second.UUID);
request = OutStandingRequests_.erase(request);
} else {
// std::cout << __LINE__ << " -->> " << request->second.Id <<
// std::endl;
++request;
}
}

View File

@@ -11,12 +11,12 @@
namespace OpenWifi {
class ConfigurationCache {
public:
static auto instance() {
static auto instance = new ConfigurationCache;
static ConfigurationCache &instance() {
static ConfigurationCache instance;
return instance;
}
inline uint64_t GetCurrentConfig(std::uint64_t SerialNumber) {
inline uint64_t CurrentConfig(uint64_t SerialNumber) {
std::lock_guard G(Mutex_);
const auto Hint = Cache_.find(SerialNumber);
if (Hint == end(Cache_))
@@ -24,25 +24,25 @@ namespace OpenWifi {
return Hint->second;
}
inline void SetCurrentConfig(std::uint64_t SerialNumber, uint64_t Id) {
inline void Add(uint64_t SerialNumber, uint64_t Id) {
std::lock_guard G(Mutex_);
Cache_[SerialNumber] = Id;
}
private:
std::mutex Mutex_;
std::recursive_mutex Mutex_;
std::map<uint64_t, uint64_t> Cache_;
};
inline auto GetCurrentConfigurationID(std::uint64_t SerialNumber) {
return ConfigurationCache::instance()->GetCurrentConfig(SerialNumber);
inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
return ConfigurationCache::instance().CurrentConfig(SerialNumber);
}
inline void SetCurrentConfigurationID(const std::string &SerialNumber, std::uint64_t ID) {
return ConfigurationCache::instance()->SetCurrentConfig(Utils::SerialNumberToInt(SerialNumber), ID);
inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
}
inline void SetCurrentConfigurationID(uint64_t SerialNumber, std::uint64_t ID) {
return ConfigurationCache::instance()->SetCurrentConfig(SerialNumber, ID);
inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
return ConfigurationCache::instance().Add(SerialNumber, ID);
}
} // namespace OpenWifi

View File

@@ -49,7 +49,7 @@ namespace OpenWifi {
SignatureManager(), AP_WS_Server(),
RegulatoryInfo(),
RADIUSSessionTracker(),
AP_WS_ConfigAutoUpgradeAgent(),
AP_WS_ConfigAutoUpgrader(),
FirmwareRevisionCache()
});
return &instance;
@@ -78,7 +78,7 @@ namespace OpenWifi {
if (Id == DeviceType)
return Type;
}
return Platforms::AP;
return "AP";
}
void DaemonPostInitialization(Poco::Util::Application &self) {

View File

@@ -21,6 +21,7 @@ namespace OpenWifi {
void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
if (GeneratingDashboard_.load()) {
// std::cout << "Trying to generate dashboard but already being generated" << std::endl;
while (GeneratingDashboard_.load()) {
Poco::Thread::trySleep(100);
}
@@ -30,6 +31,7 @@ namespace OpenWifi {
GeneratingDashboard_ = true;
ValidDashboard_ = false;
try {
// std::cout << "Generating dashboard." << std::endl;
poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
GWObjects::Dashboard NewData;
StorageService()->AnalyzeCommands(NewData.commands);

View File

@@ -8,12 +8,12 @@
#pragma once
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/HTTPServerRequest.h>
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include <framework/SubSystemServer.h>
#include "framework/SubSystemServer.h"
namespace OpenWifi {

View File

@@ -50,22 +50,12 @@ namespace OpenWifi {
class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
public:
DeviceConfigurationChangeKafkaEvent(std::uint64_t serialNumber,
std::uint64_t timestamp,
const Poco::JSON::Object::Ptr config)
std::uint64_t timestamp, const Poco::JSON::Object::Ptr config)
: GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
}
~DeviceConfigurationChangeKafkaEvent() {
if(config_!= nullptr) {
std::ostringstream os;
config_->stringify(os);
if(os.str().size()> KafkaManager()->KafkaManagerMaximumPayloadSize()) {
payload_->set("configuration", "{}");
payload_->set("configurationTooBig", true);
} else {
payload_->set("configuration", *config_);
}
}
payload_->set("configuration", *config_);
Send();
}

View File

@@ -1753,6 +1753,7 @@ namespace OpenWifi {
nlohmann::json new_ie;
nlohmann::json content;
// std::cout << BufferToHex(&data[0],data.size()) << std::endl;
uint offset = 0;
auto sub_ie = data[offset++];
switch (sub_ie) {
@@ -1787,6 +1788,7 @@ namespace OpenWifi {
try {
nlohmann::json D = nlohmann::json::parse(ofs.str());
// std::cout << "Start of parsing wifi" << std::endl;
if (D.contains("status")) {
auto Status = D["status"];
if (Status.contains("scan") && Status["scan"].is_array()) {
@@ -1801,6 +1803,8 @@ namespace OpenWifi {
if (ie.contains("type") && ie.contains("data")) {
uint64_t ie_type = ie["type"];
std::string ie_data = ie["data"];
// std::cout << "TYPE:" << ie_type << " DATA:" << ie_data
// << std::endl;
auto data = Base64Decode2Vec(ie_data);
if (ie_type == ieee80211_eid::WLAN_EID_COUNTRY) {
new_ies.push_back(WFS_WLAN_EID_COUNTRY(data));
@@ -1854,12 +1858,18 @@ namespace OpenWifi {
} else if (ie_type == ieee80211_eid::WLAN_EID_EXTENSION) {
new_ies.push_back(WFS_WLAN_EID_EXTENSION(data));
} else {
// std::cout
// << "Skipping IE: no parsing available: " << ie_type
// << std::endl;
new_ies.push_back(ie);
}
} else {
// std::cout << "Skipping IE: no data and type" <<
// std::endl;
new_ies.push_back(ie);
}
} catch (...) {
// std::cout << "Skipping IE: exception" << std::endl;
Logger.information(fmt::format("Error parsing IEs"));
new_ies.push_back(ie);
}
@@ -1867,6 +1877,7 @@ namespace OpenWifi {
scan_entry["ies"] = new_ies;
ParsedScan.push_back(scan_entry);
} else {
// std::cout << "Skipping scan" << std::endl;
ParsedScan.push_back(scan_entry);
}
}
@@ -1875,6 +1886,7 @@ namespace OpenWifi {
}
}
Result << to_string(D);
// std::cout << "End of parsing wifi" << std::endl;
return true;
} catch (const Poco::Exception &E) {
Logger.log(E);

View File

@@ -177,6 +177,15 @@ namespace OpenWifi {
} else {
session_hint->second->lastTransaction = Utils::Now();
}
/*
if(ap_hint!=AccountingSessions_.end()) {
std::cout << "Auth table:" << std::endl;
for(const auto &session:ap_hint->second) {
std::cout << Notification.SerialNumber_ << ": Index: " << session.first << ": ID: " << session.second->accountingSessionId << " MID:" << session.second->accountingMultiSessionId << std::endl;
}
}
*/
}
std::uint32_t GetUiInt32(const std::uint8_t *buf) {
@@ -414,15 +423,15 @@ namespace OpenWifi {
}
void RADIUSSessionTracker::DisconnectSession(const std::string &SerialNumber) {
poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
std::lock_guard Guard(Mutex_);
auto hint = AccountingSessions_.find(SerialNumber);
if(hint==end(AccountingSessions_)) {
return;
}
poco_information(Logger(),fmt::format("{}: Disconnecting.", SerialNumber));
// we need to go through all sessions and send an accounting stop
for(const auto &session:hint->second) {
poco_debug(Logger(), fmt::format("Stopping accounting for {}:{}", SerialNumber, session.first ));

View File

@@ -75,10 +75,8 @@ namespace OpenWifi {
} else if ((Utils::Now() - LastKeepAlive) > Pool_.radsecKeepAlive) {
RADIUS::RadiusOutputPacket P(Pool_.authConfig.servers[ServerIndex_].radsecSecret);
P.MakeStatusMessage(Pool_.authConfig.servers[ServerIndex_].name);
if(Type_!=GWObjects::RadiusEndpointType::generic) {
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
Socket_->sendBytes(P.Data(), P.Len());
}
poco_trace(Logger_, fmt::format("{}: Keep-Alive message.", Pool_.authConfig.servers[ServerIndex_].name));
Socket_->sendBytes(P.Data(), P.Len());
LastKeepAlive = Utils::Now();
}
Poco::Thread::trySleep(2000);
@@ -165,16 +163,17 @@ namespace OpenWifi {
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
}
return;
} else {
poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
Disconnect();
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
Disconnect();
} catch (...) {
Disconnect();
poco_warning(Logger_, "Exception occurred. Resetting the connection.");
}
Disconnect();
}
inline void
@@ -325,7 +324,7 @@ namespace OpenWifi {
ofs << OpenRoamingRootCert;
ofs.close();
auto SecureContext = Poco::AutoPtr<Poco::Net::Context>(
Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>(
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, ""));
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
@@ -431,7 +430,7 @@ namespace OpenWifi {
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
}
auto SecureContext =
Poco::Net::Context::Ptr SecureContext =
Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
if (Pool_.acctConfig.servers[ServerIndex_].allowSelfSigned) {
@@ -499,9 +498,7 @@ namespace OpenWifi {
}
inline bool Connect_Generic() {
poco_information(Logger_, fmt::format("Connecting {}", Pool_.name));
if (TryAgain_ && !Connected_) {
if (TryAgain_) {
std::lock_guard G(LocalMutex_);
Poco::Net::SocketAddress AuthSockAddrV4(
@@ -523,6 +520,26 @@ namespace OpenWifi {
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
/*
AuthenticationSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
Poco::Net::SocketAddress AuthSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.authentication.port",
DEFAULT_RADIUS_AUTHENTICATION_PORT));
Poco::Net::SocketAddress AcctSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.accounting.port",
DEFAULT_RADIUS_ACCOUNTING_PORT));
AccountingSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
Poco::Net::SocketAddress CoASockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
*/
Reactor_.addEventHandler(
*AuthenticationSocketV4_,
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
@@ -534,27 +551,7 @@ namespace OpenWifi {
Reactor_.addEventHandler(
*CoASocketV4_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
*this, &RADIUS_Destination::OnCoASocketReadable));
/*
Poco::Net::SocketAddress AuthSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.authentication.port",
DEFAULT_RADIUS_AUTHENTICATION_PORT));
AuthenticationSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
Poco::Net::SocketAddress AcctSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.accounting.port",
DEFAULT_RADIUS_AUTHENTICATION_PORT));
AccountingSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
Poco::Net::SocketAddress CoASockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
Reactor_.addEventHandler(
*AuthenticationSocketV6_,
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
@@ -568,7 +565,6 @@ namespace OpenWifi {
*CoASocketV6_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
*this, &RADIUS_Destination::OnCoASocketReadable));
*/
Connected_ = true;
}
return true;
}
@@ -594,8 +590,6 @@ namespace OpenWifi {
if (Connected_) {
std::lock_guard G(LocalMutex_);
if(Type_==GWObjects::RadiusEndpointType::generic) {
poco_information(Logger_, fmt::format("Disconnecting {} generic server. Releasing all UDP resources.", Pool_.name));
if(AuthenticationSocketV4_) {
Reactor_.removeEventHandler(
*AuthenticationSocketV4_,
@@ -623,8 +617,7 @@ namespace OpenWifi {
CoASocketV4_.reset();
}
/*
if(AuthenticationSocketV6_) {
/* if(AuthenticationSocketV6_) {
Reactor_.removeEventHandler(
*AuthenticationSocketV6_,
Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
@@ -653,6 +646,7 @@ namespace OpenWifi {
*/
} else {
if(Socket_!=nullptr) {
std::lock_guard G(LocalMutex_);
Reactor_.removeEventHandler(
*Socket_, Poco::NObserver<RADIUS_Destination, Poco::Net::ReadableNotification>(
*this, &RADIUS_Destination::onData));
@@ -666,9 +660,9 @@ namespace OpenWifi {
Socket_->close();
}
}
Connected_ = false;
}
poco_information(Logger_, fmt::format("Disconnecting {}", Pool_.name));
Connected_ = false;
poco_information(Logger_, "Disconnecting.");
}
static void DecodeFile(const std::string &filename, const std::string &s) {
@@ -730,8 +724,7 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
/*
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
/* std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
*/

View File

@@ -63,7 +63,7 @@ namespace OpenWifi {
poco_debug(Logger(), fmt::format("BLACKLIST-POST: {}", D.serialNumber));
Poco::toLowerInPlace(D.serialNumber);
if (StorageService()->IsBlackListed(Utils::MACToInt(D.serialNumber))) {
if (StorageService()->IsBlackListed(D.serialNumber)) {
return BadRequest(RESTAPI::Errors::SerialNumberExists);
}

View File

@@ -56,27 +56,17 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if (DefConfig.models.empty()) {
if (DefConfig.Models.empty()) {
return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
}
DefConfig.platform = DefConfig.platform.empty() ? Platforms::AP : DefConfig.platform;
if(DefConfig.platform != Platforms::AP && DefConfig.platform != Platforms::SWITCH) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(DefConfig.configuration.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DefConfig.platform),
DefConfig.configuration, Error,
std::vector<std::string> Error;
if (!ValidateUCentralConfiguration(DefConfig.Configuration, Error,
GetBoolParameter("strict", false))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
DefConfig.created = DefConfig.lastModified = Utils::Now();
DefConfig.Created = DefConfig.LastModified = Utils::Now();
if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
return OK();
}
@@ -98,31 +88,19 @@ namespace OpenWifi {
return NotFound();
}
if(Existing.platform.empty()) {
Existing.platform = Platforms::AP;
}
if(ParsedBody_->has("platform")) {
if(NewConfig.platform.empty() || (NewConfig.platform != Platforms::AP && NewConfig.platform != Platforms::SWITCH)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
Existing.platform = NewConfig.platform;
}
if (!NewConfig.configuration.empty()) {
std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.platform),
NewConfig.configuration, Error,
if (!NewConfig.Configuration.empty()) {
std::vector<std::string> Error;
if (!ValidateUCentralConfiguration(NewConfig.Configuration, Error,
GetBoolParameter("strict", false))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
Existing.configuration = NewConfig.configuration;
Existing.Configuration = NewConfig.Configuration;
}
Existing.lastModified = Utils::Now();
AssignIfPresent(Obj, "description", Existing.description);
Existing.LastModified = Utils::Now();
AssignIfPresent(Obj, "description", Existing.Description);
if (Obj->has("modelIds"))
Existing.models = NewConfig.models;
Existing.Models = NewConfig.Models;
if (StorageService()->UpdateDefaultConfiguration(Name, Existing)) {
GWObjects::DefaultConfiguration ModifiedConfig;

View File

@@ -87,7 +87,7 @@ namespace OpenWifi {
poco_debug(
Logger_,
fmt::format(
"Command RTTY TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
"Command rtty TID={} can proceed. Identified as {} and RPCID as {}. thr_id={}",
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return Rtty(UUID, RPC, 60000ms, Restrictions);
};
@@ -166,8 +166,7 @@ namespace OpenWifi {
{APCommands::Commands::rrm, false, true, &RESTAPI_device_commandHandler::RRM, 60000ms},
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms},
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms}
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms}
};
void RESTAPI_device_commandHandler::DoPost() {
@@ -654,18 +653,13 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
GWObjects::Device DeviceInfo;
if (!StorageService()->GetDevice(SerialNumber_, DeviceInfo)) {
return NotFound();
}
auto Configuration =
GetS(RESTAPI::Protocol::CONFIGURATION, Obj, uCentralProtocol::EMPTY_JSON_DOC);
std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceInfo.DeviceType),
Configuration, Error,
std::vector<std::string> Error;
if (!ValidateUCentralConfiguration(Configuration, Error,
GetBoolParameter("strict", false))) {
CallCanceled("CONFIGURE", CMD_UUID, CMD_RPC, RESTAPI::Errors::ConfigBlockInvalid);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
auto When = GetWhen(Obj);
@@ -1175,7 +1169,7 @@ namespace OpenWifi {
if (RTTYS_server()->UseInternal()) {
std::uint64_t SN = Utils::SerialNumberToInt(SerialNumber_);
bool mTLS = AP_WS_Server()->DeviceRequiresSecureRTTY(SN);
bool mTLS = AP_WS_Server()->DeviceRequiresSecureRtty(SN);
auto Hash = Utils::ComputeHash(UserInfo_.webtoken.refresh_token_, Utils::Now());
Rtty.Token = Hash.substr(0, RTTY_DEVICE_TOKEN_LENGTH);
if (!RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, Requester(),
@@ -1407,9 +1401,9 @@ namespace OpenWifi {
Cmd.WaitingForFile = 0;
Cmd.Status= "completed";
if(CommandManager()->FireAndForget(SerialNumber_, uCentralProtocol::RRM, Params)) {
Cmd.Status= "completed";
StorageService()->AddCommand(SerialNumber_, Cmd,
Storage::CommandExecutionType::COMMAND_COMPLETED);
Cmd.Status= "completed";
return OK();
}
Cmd.Status= "failed"; // should never happen
@@ -1507,45 +1501,4 @@ namespace OpenWifi {
}
void RESTAPI_device_commandHandler::PowerCycle(
const std::string &CMD_UUID, uint64_t CMD_RPC,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("POWERCYCLE({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("RRM", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::PowerCycleRequest PR;
if(!PR.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::POWERCYCLE;
std::ostringstream os;
ParsedBody_->stringify(os);
Cmd.Details = os.str();
Cmd.RunAt = PR.when;
Cmd.ErrorCode = 0;
Cmd.WaitingForFile = 0;
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::powercycle, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
} // namespace OpenWifi

View File

@@ -68,8 +68,6 @@ namespace OpenWifi {
const GWObjects::DeviceRestrictions &R);
void Transfer(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
static auto PathName() {
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};

View File

@@ -17,8 +17,6 @@
#include "RESTAPI_device_helper.h"
#include "AP_WS_Server.h"
namespace OpenWifi {
void RESTAPI_device_handler::DoGet() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
@@ -82,9 +80,6 @@ namespace OpenWifi {
return OK();
} else if (StorageService()->DeleteDevice(SerialNumber)) {
if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
}
return OK();
}
@@ -106,10 +101,9 @@ namespace OpenWifi {
}
auto Config = Obj->get("configuration").toString();
Poco::JSON::Object Answer;
std::string Error;
auto DeviceType = Poco::toLower(GetParameter("deviceType", Platforms::AP));
std::vector<std::string> Error;
auto Res =
ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),Config, Error, GetBoolParameter("strict", false));
ValidateUCentralConfiguration(Config, Error, GetBoolParameter("strict", false));
Answer.set("valid", Res);
if (!Error.empty())
Answer.set("error", Error);
@@ -129,13 +123,12 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
std::string Error;
std::vector<std::string> Error;
if (Device.Configuration.empty() ||
(!Device.Configuration.empty() &&
!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Device.DeviceType),
Device.Configuration, Error,
!ValidateUCentralConfiguration(Device.Configuration, Error,
GetBoolParameter("strict", false)))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
for (auto &i : Device.Notes) {
@@ -176,11 +169,10 @@ namespace OpenWifi {
}
if (!NewDevice.Configuration.empty()) {
std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.DeviceType),
NewDevice.Configuration, Error,
std::vector<std::string> Error;
if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error,
GetBoolParameter("strict", false))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
Config::Config NewConfig(NewDevice.Configuration);
uint64_t NewConfigUUID = Utils::Now();

View File

@@ -82,24 +82,15 @@ namespace OpenWifi {
}
}
auto platform = Poco::toLower(GetParameter("platform", ""));
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
auto completeInfo = GetBoolParameter("completeInfo", false);
auto includeProvisioned = GetBoolParameter("includeProvisioned", true);
if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(platform=="all")
platform="";
Poco::JSON::Object RetObj;
if (!QB_.Select.empty()) {
Poco::JSON::Array Objects;
for (auto &i : SelectedRecords()) {
auto &SerialNumber = i;
auto SerialNumber = i;
if (!Utils::ValidSerialNumber(i))
continue;
GWObjects::Device D;
@@ -125,14 +116,14 @@ namespace OpenWifi {
else
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
} else if (QB_.CountOnly) {
} else if (QB_.CountOnly == true) {
uint64_t Count = 0;
if (StorageService()->GetDeviceCount(Count, platform)) {
if (StorageService()->GetDeviceCount(Count)) {
return ReturnCountOnly(Count);
}
} else if (serialOnly) {
std::vector<std::string> SerialNumbers;
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform, includeProvisioned);
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy);
Poco::JSON::Array Objects;
for (const auto &i : SerialNumbers) {
Objects.add(i);
@@ -150,7 +141,7 @@ namespace OpenWifi {
RetObj.set("serialNumbers", Objects);
} else {
std::vector<GWObjects::Device> Devices;
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform, includeProvisioned);
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy);
Poco::JSON::Array Objects;
for (const auto &i : Devices) {
Poco::JSON::Object Obj;
@@ -184,12 +175,10 @@ namespace OpenWifi {
}
if(GetBoolParameter("simulatedDevices",false)) {
auto F = []() ->void {
StorageService()->DeleteSimulatedDevice("");
};
std::thread T(F);
T.detach();
return OK();
if(StorageService()->DeleteSimulatedDevice("")) {
return OK();
}
return NotFound();
}
if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {

View File

@@ -8,7 +8,7 @@
#pragma once
#include <framework/RESTAPI_Handler.h>
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_file : public RESTAPIHandler {

View File

@@ -7,7 +7,6 @@
#include "RESTAPI_ProvObjects.h"
#include "framework/utils.h"
#include <vector>
#include "framework/ow_constants.h"
namespace OpenWifi {

View File

@@ -12,7 +12,6 @@
#include "Daemon.h"
#ifdef TIP_GATEWAY_SERVICE
#include "AP_WS_Server.h"
#include "StorageService.h"
#include "CapabilitiesCache.h"
#include "RADIUSSessionTracker.h"
#endif
@@ -30,8 +29,8 @@ namespace OpenWifi::GWObjects {
void Device::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "serialNumber", SerialNumber);
#ifdef TIP_GATEWAY_SERVICE
field_to_json(Obj, "deviceType", StorageService()->GetPlatform(SerialNumber));
field_to_json(Obj, "blackListed", StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
#endif
field_to_json(Obj, "macAddress", MACAddress);
field_to_json(Obj, "manufacturer", Manufacturer);
@@ -69,14 +68,9 @@ namespace OpenWifi::GWObjects {
#ifdef TIP_GATEWAY_SERVICE
ConnectionState ConState;
#ifdef USE_MEDUSA_CLIENT
auto Res = GS()->GetState(SerialNumber);
if (Res.has_value()) {
Res.value().to_json(SerialNumber,Obj);
#else
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber,Obj);
#endif
} else {
field_to_json(Obj, "ipAddress", "");
field_to_json(Obj, "txBytes", (uint64_t)0);
@@ -172,17 +166,14 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "recorded", Recorded);
}
bool HealthCheck::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "sanity", Sanity);
field_from_json(Obj, "recorded", Recorded);
return true;
} catch(...) {
}
return false;
}
void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
EmbedDocument("configuration", Obj, Configuration);
field_to_json(Obj, "name", Name);
field_to_json(Obj, "modelIds", Models);
field_to_json(Obj, "description", Description);
field_to_json(Obj, "created", Created);
field_to_json(Obj, "lastModified", LastModified);
}
void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType);
@@ -231,25 +222,12 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "deferred", deferred);
}
void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
EmbedDocument("configuration", Obj, configuration);
field_to_json(Obj, "name", name);
field_to_json(Obj, "modelIds", models);
field_to_json(Obj, "description", description);
field_to_json(Obj, "created", created);
field_to_json(Obj, "lastModified", lastModified);
field_to_json(Obj, "platform", platform);
}
bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "configuration", configuration);
field_from_json(Obj, "name", name);
field_from_json(Obj, "modelIds", models);
field_from_json(Obj, "description", description);
field_from_json(Obj, "created", created);
field_from_json(Obj, "lastModified", lastModified);
field_from_json(Obj, "platform", platform);
field_from_json(Obj, "name", Name);
field_from_json(Obj, "configuration", Configuration);
field_from_json(Obj, "modelIds", Models);
field_from_json(Obj, "description", Description);
return true;
} catch (const Poco::Exception &E) {
}
@@ -298,11 +276,13 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_to_json(Obj, "connectReason", connectReason);
field_to_json(Obj, "uptime", uptime);
field_to_json(Obj, "compatible", Compatible);
#ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
memoryUsed,
load,
temperature);
#endif
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_to_json(Obj, "hasGPS", hasGPS);
@@ -334,45 +314,6 @@ namespace OpenWifi::GWObjects {
}
}
bool ConnectionState::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "compatible", Compatible);
field_from_json(Obj, "ipAddress", Address);
field_from_json(Obj, "txBytes", TX);
field_from_json(Obj, "rxBytes", RX);
field_from_json(Obj, "messageCount", MessageCount);
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "connected", Connected);
field_from_json(Obj, "firmware", Firmware);
field_from_json(Obj, "lastContact", LastContact);
field_from_json(Obj, "associations_2G", Associations_2G);
field_from_json(Obj, "associations_5G", Associations_5G);
field_from_json(Obj, "associations_6G", Associations_6G);
field_from_json(Obj, "webSocketClients", webSocketClients);
field_from_json(Obj, "websocketPackets", websocketPackets);
field_from_json(Obj, "kafkaClients", kafkaClients);
field_from_json(Obj, "kafkaPackets", kafkaPackets);
field_from_json(Obj, "locale", locale);
field_from_json(Obj, "started", started);
field_from_json(Obj, "sessionId", sessionId);
field_from_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_from_json(Obj, "totalConnectionTime", totalConnectionTime);
field_from_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_from_json(Obj, "connectReason", connectReason);
field_from_json(Obj, "uptime", uptime);
field_from_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_from_json(Obj, "hasGPS", hasGPS);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "memoryUsed", memoryUsed);
field_from_json(Obj, "sanity", sanity);
field_from_json(Obj, "load", load);
field_from_json(Obj, "temperature", temperature);
return true;
} catch(const Poco::Exception &E) {
}
return false;
}
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "averageConnectionTime", averageConnectionTime);
field_to_json(Obj, "connectedDevices", connectedDevices);
@@ -770,7 +711,7 @@ namespace OpenWifi::GWObjects {
bool DeviceCertificateUpdateRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "serialNumber", serialNumber);
field_from_json(Obj, "encodedCertificate", encodedCertificate);
return true;
} catch (const Poco::Exception &E) {
@@ -778,25 +719,4 @@ namespace OpenWifi::GWObjects {
return false;
}
bool PowerCyclePort::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "cycle", cycle);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool PowerCycleRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "when", when);
field_from_json(Obj, "ports", ports);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
} // namespace OpenWifi::GWObjects

View File

@@ -49,11 +49,8 @@ namespace OpenWifi::GWObjects {
std::double_t load=0.0;
std::double_t temperature=0.0;
std::string connectReason;
std::uint64_t uptime=0;
std::uint64_t totalConnectionTime=0;
void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceRestrictionsKeyInfo {
@@ -115,7 +112,6 @@ namespace OpenWifi::GWObjects {
std::uint64_t lastRecordedContact=0;
std::uint64_t certificateExpiryDate = 0;
std::string connectReason;
bool blackListed=false;
void to_json(Poco::JSON::Object &Obj) const;
void to_json_with_status(Poco::JSON::Object &Obj) const;
@@ -141,15 +137,13 @@ namespace OpenWifi::GWObjects {
};
struct HealthCheck {
std::string SerialNumber;
uint64_t UUID = 0;
std::string Data;
uint64_t Recorded = 0;
uint64_t Sanity = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
std::string SerialNumber;
uint64_t UUID = 0;
std::string Data;
uint64_t Recorded = 0;
uint64_t Sanity = 0;
void to_json(Poco::JSON::Object &Obj) const;
};
struct Capabilities {
std::string Capabilities;
@@ -180,13 +174,12 @@ namespace OpenWifi::GWObjects {
};
struct DefaultConfiguration {
std::string name;
std::string configuration;
Types::StringVec models;
std::string description;
uint64_t created;
uint64_t lastModified;
std::string platform;
std::string Name;
std::string Configuration;
Types::StringVec Models;
std::string Description;
uint64_t Created;
uint64_t LastModified;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
@@ -520,18 +513,4 @@ namespace OpenWifi::GWObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PowerCyclePort {
std::string name;
std::uint64_t cycle=10000;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PowerCycleRequest {
std::string serialNumber;
std::uint64_t when;
std::vector<PowerCyclePort> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} // namespace OpenWifi::GWObjects

View File

@@ -587,9 +587,6 @@ namespace OpenWifi::ProvObjects {
field_to_json(Obj, "locale", locale);
field_to_json(Obj, "realMacAddress", realMacAddress);
field_to_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
field_to_json(Obj, "imported", imported);
field_to_json(Obj, "connected", connected);
field_to_json(Obj, "platform", platform);
}
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -612,9 +609,6 @@ namespace OpenWifi::ProvObjects {
field_from_json(Obj, "locale", locale);
field_from_json(Obj, "realMacAddress", realMacAddress);
field_from_json(Obj, "doNotAllowOverrides", doNotAllowOverrides);
field_from_json(Obj, "imported", imported);
field_from_json(Obj, "connected", connected);
field_from_json(Obj, "platform", platform);
return true;
} catch (...) {
}

View File

@@ -490,11 +490,9 @@ namespace OpenWifi::ProvObjects {
std::string locale;
std::string realMacAddress;
bool doNotAllowOverrides = false;
std::uint64_t imported=0;
std::uint64_t connected=0;
std::string platform{Platforms::AP};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};

View File

@@ -24,7 +24,7 @@ namespace OpenWifi::StateUtils {
}
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
uint64_t &Radios_5G, uint64_t &Radios_6G, uint64_t &UpTime ) {
uint64_t &Radios_5G, uint64_t &Radios_6G) {
Radios_2G = 0;
Radios_5G = 0;
Radios_6G = 0;
@@ -90,15 +90,9 @@ namespace OpenWifi::StateUtils {
}
}
}
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
return true;
}
if(RawObject->has("unit") && !RawObject->isNull("unit") && RawObject->isObject("unit")) {
auto unit = RawObject->getObject("unit");
if(unit->has("uptime")) {
UpTime = unit->get("uptime");
}
}
return false;
}
} // namespace OpenWifi::StateUtils

View File

@@ -8,5 +8,5 @@
namespace OpenWifi::StateUtils {
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
uint64_t &Radios_5G, uint64_t &Radio_6G, uint64_t &UpTime);
uint64_t &Radios_5G, uint64_t &Radio_6G);
}

View File

@@ -22,8 +22,6 @@ namespace OpenWifi {
ScriptDB_->Create();
ScriptDB_->Initialize();
FixDeviceTypeBug();
return 0;
}

View File

@@ -16,22 +16,6 @@
namespace OpenWifi {
class LockedDbSession {
public:
explicit LockedDbSession();
~LockedDbSession() = default;
inline std::mutex &Mutex() { return *Mutex_; };
inline Poco::Data::Session &Session() {
if(!Session_->isConnected()) {
Session_->reconnect();
}
return *Session_;
};
private:
std::shared_ptr<Poco::Data::Session> Session_;
std::shared_ptr<std::mutex> Mutex_;
};
class Storage : public StorageClass {
public:
@@ -106,8 +90,7 @@ namespace OpenWifi {
// typedef std::map<std::string,std::string> DeviceCapabilitiesCache;
bool AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log);
bool AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats);
bool AddLog(const GWObjects::DeviceLog &Log);
bool AddStatisticsData(const GWObjects::Statistics &Stats);
bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Offset, uint64_t HowMany,
@@ -119,7 +102,6 @@ namespace OpenWifi {
std::vector<GWObjects::Statistics> &Stats);
bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
bool AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check);
bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::HealthCheck> &Checks);
@@ -133,43 +115,31 @@ namespace OpenWifi {
uint64_t &NewUUID);
bool RollbackDeviceConfigurationChange(std::string & SerialNumber);
bool CompleteDeviceConfigurationChange(Poco::Data::Session &Session, std::string & SerialNumber);
bool CompleteDeviceConfigurationChange(std::string & SerialNumber);
bool CreateDevice(LockedDbSession &Session, GWObjects::Device &);
bool CreateDevice(GWObjects::Device &);
bool CreateDefaultDevice(Poco::Data::Session &Session,std::string &SerialNumber,
const Config::Capabilities &Caps,
bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
std::string &Firmware, const Poco::Net::IPAddress &IPAddress,
bool simulated);
bool CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails);
bool GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &);
bool GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails);
bool GetDevice(const std::string &SerialNumber, GWObjects::Device &);
bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
const std::string &orderBy = "",
const std::string &platform = "",
bool includeProvisioned = true);
const std::string &orderBy = "");
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
bool DeleteDevice(std::string &SerialNumber);
bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
std::string GetPlatform(const std::string &SerialNumber);
bool UpdateDevice(GWObjects::Device &);
bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
bool UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails);
bool DeviceExists(std::string &SerialNumber);
bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
bool GetDeviceCount(uint64_t &Count, const std::string &platform = "");
bool GetDeviceCount(uint64_t &Count);
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
std::vector<std::string> &SerialNumbers,
const std::string &orderBy = "",
const std::string &platform = "",
bool includeProvisioned = true);
const std::string &orderBy = "");
bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
bool SetDevicePassword(std::string &SerialNumber, std::string &Password);
bool UpdateSerialNumberCache();
static void GetDeviceDbFieldList(Types::StringVec &Fields);
@@ -178,11 +148,9 @@ namespace OpenWifi {
bool UpdateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Capabilities);
bool UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
const Config::Capabilities &Capabilities);
bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
bool DeleteDeviceCapabilities(std::string &SerialNumber);
bool CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
bool CreateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Capabilities);
bool InitCapabilitiesCache();
@@ -203,7 +171,6 @@ namespace OpenWifi {
bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
std::vector<GWObjects::DefaultConfiguration> &Devices);
bool FindDefaultConfigurationForModel(const std::string &Model,
const std::string &Platform,
GWObjects::DefaultConfiguration &DefConfig);
uint64_t GetDefaultConfigurationsCount();
bool DefaultConfigurationAlreadyExists(std::string &Name);
@@ -255,15 +222,15 @@ namespace OpenWifi {
void RemovedExpiredCommands();
void RemoveTimedOutCommands();
bool RemoveOldCommands(std::string &SerialNumber, std::string &Command);
bool RemoveOldCommands(std::string &SerilNumber, std::string &Command);
bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
bool DeleteBlackListDevice(std::string &SerialNumber);
bool IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
bool IsBlackListed(const std::string &SerialNumber, std::string &reason,
std::string &author, std::uint64_t &created);
bool IsBlackListed(std::uint64_t SerialNumber);
bool IsBlackListed(const std::string &SerialNumber);
bool InitializeBlackListCache();
bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::BlackListedDevice> &Devices);
@@ -278,9 +245,7 @@ namespace OpenWifi {
bool RemoveCommandListRecordsOlderThan(uint64_t Date);
bool RemoveUploadedFilesRecordsOlderThan(uint64_t Date);
bool SetDeviceLastRecordedContact(LockedDbSession &Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool SetDeviceLastRecordedContact(std::string & SeialNumber, std::uint64_t lastRecordedContact);
int Create_Tables();
int Create_Statistics();
@@ -297,24 +262,13 @@ namespace OpenWifi {
bool AnalyzeCommands(Types::CountedMap &R);
bool AnalyzeDevices(GWObjects::Dashboard &D);
void FixDeviceTypeBug();
int Start() override;
void Stop() override;
inline Poco::Data::Session StartSession() {
return Pool_->get();
}
private:
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
};
inline auto StorageService() { return Storage::instance(); }
inline LockedDbSession::LockedDbSession() {
Session_ = std::make_shared<Poco::Data::Session>(Poco::Data::Session(StorageService()->StartSession()));
Mutex_ = std::make_shared<std::mutex>();
}
} // namespace OpenWifi

View File

@@ -111,6 +111,7 @@ namespace OpenWifi {
}
} break;
case TelemetryNotification::NotificationType::unregister: {
std::lock_guard G(Mutex_);
auto client = Clients_.find(Notification->Data_);
if (client != Clients_.end()) {

View File

@@ -23,7 +23,7 @@
#include "framework/SubSystemServer.h"
#include "AP_WS_Reactor_Pool.h"
#include "AP_WS_ReactorPool.h"
#include "TelemetryClient.h"
namespace OpenWifi {

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
#pragma once
#include "framework/SubSystemServer.h"
#include "framework/ow_constants.h"
#include <valijson/adapters/poco_json_adapter.hpp>
#include <valijson/constraints/constraint.hpp>
#include <valijson/constraints/constraint_visitor.hpp>
@@ -17,42 +17,33 @@
namespace OpenWifi {
class ConfigurationValidator : public SubSystemServer {
public:
enum class ConfigurationType { AP = 0 , SWITCH = 1};
static auto instance() {
static auto instance_ = new ConfigurationValidator;
return instance_;
}
bool Validate(ConfigurationType Type, const std::string &C, std::string &Errors, bool Strict);
bool Validate(const std::string &C, std::vector<std::string> &Errors, bool Strict);
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
inline static ConfigurationType GetType(const std::string &type) {
std::string Type = Poco::toLower(type);
if (Type == Platforms::AP)
return ConfigurationType::AP;
if (Type == Platforms::SWITCH)
return ConfigurationType::SWITCH;
return ConfigurationType::AP;
}
private:
bool Initialized_ = false;
bool Working_ = false;
void Init();
std::array<valijson::Schema,2> RootSchema_;
bool SetSchema(ConfigurationType Type, const std::string &SchemaStr);
std::unique_ptr<valijson::Schema> RootSchema_;
std::unique_ptr<valijson::SchemaParser> SchemaParser_;
std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
Poco::JSON::Object::Ptr SchemaDocPtr_;
bool SetSchema(const std::string &SchemaStr);
ConfigurationValidator()
: SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
};
inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
inline bool ValidateUCentralConfiguration(ConfigurationValidator::ConfigurationType Type, const std::string &C, std::string &Errors,
inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error,
bool strict) {
return ConfigurationValidator::instance()->Validate(Type, C, Errors, strict);
return ConfigurationValidator::instance()->Validate(C, Error, strict);
}
} // namespace OpenWifi

View File

@@ -9,6 +9,8 @@
namespace OpenWifi {
EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
void EventBusManager::run() {
Running_ = true;
Utils::SetThreadName("fmwk:EventMgr");
@@ -16,9 +18,9 @@ namespace OpenWifi {
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
false);
while (Running_) {
if(!Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer())) {
break;
}
Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
if (!Running_)
break;
Msg = (MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
Msg, false);
@@ -29,7 +31,7 @@ namespace OpenWifi {
};
void EventBusManager::Start() {
poco_information(Logger_, "Starting...");
poco_information(Logger(), "Starting...");
if (KafkaManager()->Enabled()) {
Thread_.start(*this);
}
@@ -37,11 +39,11 @@ namespace OpenWifi {
void EventBusManager::Stop() {
if (KafkaManager()->Enabled()) {
poco_information(Logger_, "Stopping...");
poco_information(Logger(), "Stopping...");
Running_ = false;
Thread_.wakeUp();
Thread_.join();
poco_information(Logger_, "Stopped...");
poco_information(Logger(), "Stopped...");
}
}

View File

@@ -12,16 +12,7 @@ namespace OpenWifi {
class EventBusManager : public Poco::Runnable {
public:
EventBusManager() :
Logger_(Poco::Logger::create(
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())) {
}
static auto instance() {
static auto instance_ = new EventBusManager;
return instance_;
}
explicit EventBusManager(Poco::Logger &L);
void run() final;
void Start();
void Stop();
@@ -33,6 +24,4 @@ namespace OpenWifi {
Poco::Logger &Logger_;
};
inline auto EventBusManager() { return EventBusManager::instance(); }
} // namespace OpenWifi

View File

@@ -79,10 +79,8 @@ namespace OpenWifi {
Utils::SetThreadName("Kafka:Prod");
cppkafka::Configuration Config(
{{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
{"metadata.broker.list",MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")} // ,
// {"send.buffer.bytes", KafkaManager()->KafkaManagerMaximumPayloadSize() }
}
);
{"metadata.broker.list",
MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
AddKafkaSecurity(Config);
@@ -107,16 +105,7 @@ namespace OpenWifi {
NewMessage.partition(0);
NewMessage.payload(Msg->Payload());
Producer.produce(NewMessage);
if (Queue_.size() < 100) {
// use flush when internal queue is lightly loaded, i.e. flush after each
// message
Producer.flush();
}
else {
// use poll when internal queue is loaded to allow messages to be sent in
// batches
Producer.poll((std::chrono::milliseconds) 0);
}
Producer.flush();
}
} catch (const cppkafka::HandleException &E) {
poco_warning(Logger_,
@@ -126,13 +115,8 @@ namespace OpenWifi {
} catch (...) {
poco_error(Logger_, "std::exception");
}
if (Queue_.size() == 0) {
// message queue is empty, flush all previously sent messages
Producer.flush();
}
Note = Queue_.waitDequeueNotification();
}
Producer.flush();
poco_information(Logger_, "Stopped...");
}
@@ -291,7 +275,6 @@ namespace OpenWifi {
int KafkaManager::Start() {
if (!KafkaEnabled_)
return 0;
MaxPayloadSize_ = MicroServiceConfigGetInt("openwifi.kafka.max.payload", 250000);
ConsumerThr_.Start();
ProducerThr_.Start();
return 0;
@@ -338,4 +321,4 @@ namespace OpenWifi {
partitions.front().get_partition()));
}
} // namespace OpenWifi
} // namespace OpenWifi

View File

@@ -94,14 +94,11 @@ namespace OpenWifi {
return ConsumerThr_.UnregisterTopicWatcher(Topic,Id);
}
std::uint64_t KafkaManagerMaximumPayloadSize() const { return MaxPayloadSize_; }
private:
bool KafkaEnabled_ = false;
std::string SystemInfoWrapper_;
KafkaProducer ProducerThr_;
KafkaConsumer ConsumerThr_;
std::uint64_t MaxPayloadSize_ = 250000;
void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);

View File

@@ -1,5 +1,4 @@
//
//
// Created by stephane bourque on 2022-10-26.
//
@@ -30,29 +29,13 @@
#include "framework/WebSocketLogger.h"
#include "framework/utils.h"
#ifdef USE_MEDUSA_CLIENT
#include <medusa/MedusaClient.h>
#endif
namespace OpenWifi {
static std::string MakeServiceListString(const Types::MicroServiceMetaMap &Services) {
std::string SvcList;
for (const auto &Svc : Services) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
}
return SvcList;
}
void MicroService::Exit(int Reason) { std::exit(Reason); }
void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
const std::string &Payload) {
std::lock_guard G(InfraMutex_);
Poco::Logger &BusLogger = EventBusManager()->Logger();
try {
Poco::JSON::Parser P;
auto Object = P.parse(Payload).extract<Poco::JSON::Object::Ptr>();
@@ -72,10 +55,13 @@ namespace OpenWifi {
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
auto PrivateEndPoint =
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
Services_.find(PrivateEndPoint) != Services_.end()) {
Services_[PrivateEndPoint].LastUpdate = Utils::Now();
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
Services_.erase(PrivateEndPoint);
poco_information(
BusLogger,
poco_debug(
logger(),
fmt::format(
"Service {} ID={} leaving system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
@@ -83,7 +69,14 @@ namespace OpenWifi {
ID));
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
auto ServiceInfo = Types::MicroServiceMeta{
poco_debug(
logger(),
fmt::format(
"Service {} ID={} joining system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
Services_[PrivateEndPoint] = Types::MicroServiceMeta{
.Id = ID,
.Type = Poco::toLower(
Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
@@ -101,46 +94,20 @@ namespace OpenWifi {
.toString(),
.LastUpdate = Utils::Now()};
auto s1 = MakeServiceListString(Services_);
auto PreviousSize = Services_.size();
Services_[PrivateEndPoint] = ServiceInfo;
auto CurrentSize = Services_.size();
if(Event == KafkaTopics::ServiceEvents::EVENT_JOIN) {
if(!s1.empty()) {
poco_information(
BusLogger,
fmt::format(
"Service {} ID={} is joining the system.",
Object
->get(
KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
}
std::string SvcList;
for (const auto &Svc : Services_) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
}
poco_information(
BusLogger,
fmt::format("Current list of microservices: {}", SvcList));
} else if(CurrentSize!=PreviousSize) {
poco_information(
BusLogger,
fmt::format(
"Service {} ID={} is being added back in.",
Object
->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
std::string SvcList;
for (const auto &Svc : Services_) {
if (SvcList.empty())
SvcList = Svc.second.Type;
else
SvcList += ", " + Svc.second.Type;
}
poco_information(
logger(),
fmt::format("Current list of microservices: {}", SvcList));
}
} else {
poco_information(
BusLogger,
poco_error(
logger(),
fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
Event));
}
@@ -151,39 +118,32 @@ namespace OpenWifi {
Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
#endif
} else {
poco_information(
BusLogger,
poco_error(
logger(),
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
}
} else {
poco_information(BusLogger,
poco_error(logger(),
fmt::format("Unknown Event: {} Source: {}", Event, ID));
}
}
} else {
std::ostringstream os;
Object->stringify(std::cout);
poco_error(BusLogger, fmt::format("Bad bus message: {}", os.str()));
poco_error(logger(), "Bad bus message.");
std::ostringstream os;
Object->stringify(std::cout);
}
auto ServiceHint = Services_.begin();
auto i = Services_.begin();
auto now = Utils::Now();
auto si1 = Services_.size();
auto ss1 = MakeServiceListString(Services_);
while(ServiceHint!=Services_.end()) {
if ((now - ServiceHint->second.LastUpdate) > 120) {
poco_information(BusLogger, fmt::format("ZombieService: Removing service {}, ", ServiceHint->second.PublicEndPoint));
ServiceHint = Services_.erase(ServiceHint);
for (; i != Services_.end();) {
if ((now - i->second.LastUpdate) > 60) {
i = Services_.erase(i);
} else
++ServiceHint;
++i;
}
if(Services_.size() != si1) {
auto ss2 = MakeServiceListString(Services_);
poco_information(BusLogger, fmt::format("Current list of microservices: {} -> {}", ss1, ss2));
}
} catch (const Poco::Exception &E) {
BusLogger.log(E);
logger().log(E);
}
}
@@ -207,29 +167,25 @@ namespace OpenWifi {
Res.push_back(ServiceRec);
}
return Res;
}
void MicroService::LoadConfigurationFile() {
if(ConfigContent_.empty()) {
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
ConfigFileName_ =
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
Poco::Path ConfigFile(ConfigFileName_);
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
ConfigFileName_ =
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
Poco::Path ConfigFile(ConfigFileName_);
if (!ConfigFile.isFile()) {
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
" file."
<< std::endl;
std::exit(Poco::Util::Application::EXIT_CONFIG);
}
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
} else {
std::istringstream is(ConfigContent_);
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(is);
}
if (!ConfigFile.isFile()) {
std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
<< " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
" env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
" file."
<< std::endl;
std::exit(Poco::Util::Application::EXIT_CONFIG);
}
// loadConfiguration(ConfigFile.toString());
PropConfigurationFile_ = new Poco::Util::PropertyFileConfiguration(ConfigFile.toString());
configPtr()->addWriteable(PropConfigurationFile_, PRIO_DEFAULT);
}
@@ -432,69 +388,49 @@ namespace OpenWifi {
void DaemonPostInitialization(Poco::Util::Application &self);
void MicroService::StartEverything(Poco::Util::Application &self) {
LoadConfigurationFile();
InitializeLoggingSystem();
void MicroService::initialize(Poco::Util::Application &self) {
// add the default services
LoadConfigurationFile();
InitializeLoggingSystem();
static bool InitializedBaseService=false;
if(!InitializedBaseService) {
InitializedBaseService = true;
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
SubSystems_.push_back(RESTAPI_ExtServer());
SubSystems_.push_back(RESTAPI_IntServer());
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
SubSystems_.push_back(RESTAPI_ExtServer());
SubSystems_.push_back(RESTAPI_IntServer());
#ifndef TIP_SECURITY_SERVICE
SubSystems_.push_back(AuthClient());
SubSystems_.push_back(AuthClient());
#endif
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
}
Poco::File DataDir(ConfigPath("openwifi.system.data"));
DataDir_ = DataDir.path();
if (!DataDir.exists()) {
try {
DataDir.createDirectory();
} catch (const Poco::Exception &E) {
logger().log(E);
}
}
WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
if (WWWAssetsDir_.empty())
WWWAssetsDir_ = DataDir_;
Poco::File DataDir(ConfigPath("openwifi.system.data"));
DataDir_ = DataDir.path();
if (!DataDir.exists()) {
try {
DataDir.createDirectory();
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets", "");
if (WWWAssetsDir_.empty())
WWWAssetsDir_ = DataDir_;
LoadMyConfig();
LoadMyConfig();
AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
AllowExternalMicroServices_ = ConfigGetBool("allowexternalmicroservices", true);
InitializeSubSystemServers();
ServerApplication::initialize(self);
DaemonPostInitialization(self);
InitializeSubSystemServers();
ServerApplication::initialize(self);
DaemonPostInitialization(self);
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
this->BusMessageReceived(Key, Payload);
};
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
}
void MicroService::StopEverything([[maybe_unused]] Poco::Util::Application &self) {
LoadConfigurationFile();
InitializeLoggingSystem();
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
this->BusMessageReceived(Key, Payload);
};
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
}
void MicroService::initialize([[maybe_unused]] Poco::Util::Application &self) {
#ifndef USE_MEDUSA_CLIENT
StartEverything(self);
#endif
Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
this->BusMessageReceived(Key, Payload);
};
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
}
void MicroService::uninitialize() {
@@ -594,12 +530,14 @@ namespace OpenWifi {
for (auto i : SubSystems_) {
i->Start();
}
EventBusManager()->Start();
EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
EventBusManager_->Start();
}
void MicroService::StopSubSystemServers() {
AddActivity("Stopping");
EventBusManager()->Stop();
EventBusManager_->Stop();
for (auto i = SubSystems_.rbegin(); i != SubSystems_.rend(); ++i) {
(*i)->Stop();
}
@@ -759,7 +697,7 @@ namespace OpenWifi {
auto APIKEY = Request.get("X-API-KEY");
return APIKEY == MyHash_;
} catch (const Poco::Exception &E) {
Logger_.log(E);
logger().log(E);
}
return false;
}
@@ -780,8 +718,6 @@ namespace OpenWifi {
MicroServiceErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler);
Args_ = args;
if (!HelpRequested_) {
SavePID();
@@ -797,18 +733,11 @@ namespace OpenWifi {
poco_information(logger, "Starting as a daemon.");
}
#ifdef USE_MEDUSA_CLIENT
MedusaClient::instance()->SetSubSystems(SubSystems_);
MedusaClient::instance()->Start();
waitForTerminationRequest();
MedusaClient::instance()->Stop();
#else
poco_information(logger, fmt::format("System ID set to {}", ID_));
StartSubSystemServers();
waitForTerminationRequest();
StopSubSystemServers();
logger.notice(fmt::format("Stopped {}...", DAEMON_APP_NAME));
#endif
}
return Application::EXIT_OK;

View File

@@ -55,6 +55,9 @@ namespace OpenWifi {
#include "nlohmann/json.hpp"
#include "ow_version.h"
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
namespace OpenWifi {
class MicroService : public Poco::Util::ServerApplication {
@@ -67,6 +70,7 @@ namespace OpenWifi {
SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
instance_ = this;
RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
// Logger_ = Poco::Logger::root().get("BASE-SVC");
}
inline static const char *ExtraConfigurationFilename = "/configuration_override.json";
@@ -88,7 +92,7 @@ namespace OpenWifi {
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
static inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline std::string GetPublicAPIEndPoint() const {
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() {
return MyPublicEndPoint_ + "/api/v1";
};
[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
@@ -103,8 +107,7 @@ namespace OpenWifi {
}
static MicroService &instance() { return *instance_; }
inline void Exit(int Reason) { std::exit(Reason); }
inline void Exit(int Reason);
void BusMessageReceived(const std::string &Key, const std::string &Payload);
Types::MicroServiceMetaVec GetServices(const std::string &Type);
Types::MicroServiceMetaVec GetServices();
@@ -112,9 +115,7 @@ namespace OpenWifi {
void Reload();
void LoadMyConfig();
void initialize(Poco::Util::Application &self) override;
void StartEverything(Poco::Util::Application &self);
void StopEverything(Poco::Util::Application &self);
void uninitialize() override;
void uninitialize() override;
void reinitialize(Poco::Util::Application &self) override;
void defineOptions(Poco::Util::OptionSet &options) override;
void handleHelp(const std::string &name, const std::string &value);
@@ -131,7 +132,7 @@ namespace OpenWifi {
void Reload(const std::string &Sub);
Types::StringVec GetSubSystems() const;
Types::StringPairVec GetLogLevels();
static const Types::StringVec &GetLogLevelNames();
const Types::StringVec &GetLogLevelNames();
uint64_t ConfigGetInt(const std::string &Key, uint64_t Default);
uint64_t ConfigGetInt(const std::string &Key);
uint64_t ConfigGetBool(const std::string &Key, bool Default);
@@ -165,25 +166,12 @@ namespace OpenWifi {
const std::string &FormatterPattern,
const std::string &root_env_var);
inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
const ArgVec &Args() const { return Args_; }
inline void SetConfigContent(const std::string &Content) { ConfigContent_ = Content; }
inline std::optional<OpenWifi::Types::MicroServiceMeta> GetPrivateEndPointServiceKey( const std::string & ServicePrivateEndPoint ) {
std::lock_guard G(InfraMutex_);
auto K = Services_.find(ServicePrivateEndPoint);
if(K==end(Services_)) {
return std::nullopt;
}
return K->second;
}
private:
static MicroService *instance_;
bool HelpRequested_ = false;
std::string LogDir_;
std::string ConfigFileName_;
std::string ConfigContent_;
uint64_t ID_ = 1;
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_;
bool DebugMode_ = false;
@@ -213,7 +201,7 @@ namespace OpenWifi {
Poco::JWT::Signer Signer_;
Poco::Logger &Logger_;
Poco::ThreadPool TimerPool_{"timer:pool", 2, 32};
ArgVec Args_;
std::unique_ptr<EventBusManager> EventBusManager_;
};
inline MicroService *MicroService::instance_ = nullptr;

View File

@@ -133,8 +133,4 @@ namespace OpenWifi {
return MicroService::instance().Hash();
}
std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint) {
return MicroService::instance().GetPrivateEndPointServiceKey(servicePrivateEndPoint);
}
} // namespace OpenWifi

View File

@@ -23,9 +23,7 @@ namespace OpenWifi {
std::string MicroServiceConfigGetString(const std::string &Key,
const std::string &DefaultValue);
std::string MicroServiceAccessKey();
std::optional<OpenWifi::Types::MicroServiceMeta> MicroServicePrivateAccessKey(const std::string &servicePrivateEndPoint);
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
std::string MicroServicePrivateEndPoint();
std::uint64_t MicroServiceID();

View File

@@ -47,8 +47,6 @@ namespace OpenWifi {
}
Poco::Data::SessionPool &Pool() { return *Pool_; }
private:
inline int Setup_SQLite();
inline int Setup_MySQL();

View File

@@ -58,9 +58,11 @@ namespace OpenWifi {
void UI_WebSocketClientServer::run() {
Running_ = true;
while (Running_) {
if(!Poco::Thread::trySleep(2000)) {
break;
}
Poco::Thread::trySleep(2000);
if (!Running_)
break;
std::lock_guard G(LocalMutex_);
for (const auto i : ToBeRemoved_) {
// std::cout << "Erasing old WS UI connection..." << std::endl;

View File

@@ -7,59 +7,57 @@
#include <vector>
#include <string>
#include "ow_constants.h"
namespace OpenWifi {
inline const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypeList{
{"actiontec_web7200", Platforms::AP},
{"cig_wf186w", Platforms::AP},
{"cig_wf188n", Platforms::AP},
{"cig_wf194c4", Platforms::AP},
{"cig_wf196", Platforms::AP},
{"cig_wf196-ca", Platforms::AP},
{"cig_wf196-ca-ath12", Platforms::AP},
{"cig_wf196-us", Platforms::AP},
{"cig_wf610d", Platforms::AP},
{"cig_wf660a", Platforms::AP},
{"cig_wf808", Platforms::AP},
{"cybertan_eww622-a1", Platforms::AP},
{"edgecore_eap101", Platforms::AP},
{"edgecore_eap101-ath12", Platforms::AP},
{"edgecore_eap102", Platforms::AP},
{"edgecore_eap104", Platforms::AP},
{"edgecore_eap104-ath12", Platforms::AP},
{"edgecore_ecs4100-12ph", Platforms::AP},
{"edgecore_ecw5211", Platforms::AP},
{"edgecore_ecw5410", Platforms::AP},
{"edgecore_oap100", Platforms::AP},
{"edgecore_spw2ac1200", Platforms::SWITCH},
{"edgecore_spw2ac1200-lan-poe", Platforms::SWITCH},
{"edgecore_ssw2ac2600", Platforms::SWITCH},
{"hfcl_ion4", Platforms::AP},
{"hfcl_ion4x", Platforms::AP},
{"hfcl_ion4x_2", Platforms::AP},
{"hfcl_ion4xe", Platforms::AP},
{"hfcl_ion4xi", Platforms::AP},
{"indio_um-305ac", Platforms::AP},
{"indio_um-305ax", Platforms::AP},
{"indio_um-310ax-v1", Platforms::AP},
{"indio_um-325ac", Platforms::AP},
{"indio_um-510ac-v3", Platforms::AP},
{"indio_um-510axm-v1", Platforms::AP},
{"indio_um-510axp-v1", Platforms::AP},
{"indio_um-550ac", Platforms::AP},
{"linksys_e8450-ubi", Platforms::AP},
{"linksys_ea6350-v4", Platforms::AP},
{"linksys_ea8300", Platforms::AP},
{"liteon_wpx8324", Platforms::AP},
{"meshpp_s618_cp01", Platforms::AP},
{"meshpp_s618_cp03", Platforms::AP},
{"udaya_a5-id2", Platforms::AP},
{"wallys_dr40x9", Platforms::AP},
{"wallys_dr6018", Platforms::AP},
{"wallys_dr6018_v4", Platforms::AP},
{"x64_vm", Platforms::AP},
{"yuncore_ax840", Platforms::AP},
{"yuncore_fap640", Platforms::AP},
{"yuncore_fap650", Platforms::AP}};
{"actiontec_web7200", "AP"},
{"cig_wf186w", "AP"},
{"cig_wf188n", "AP"},
{"cig_wf194c4", "AP"},
{"cig_wf196", "AP"},
{"cig_wf196-ca", "AP"},
{"cig_wf196-ca-ath12", "AP"},
{"cig_wf196-us", "AP"},
{"cig_wf610d", "AP"},
{"cig_wf660a", "AP"},
{"cig_wf808", "AP"},
{"cybertan_eww622-a1", "AP"},
{"edgecore_eap101", "AP"},
{"edgecore_eap101-ath12", "AP"},
{"edgecore_eap102", "AP"},
{"edgecore_eap104", "AP"},
{"edgecore_eap104-ath12", "AP"},
{"edgecore_ecs4100-12ph", "AP"},
{"edgecore_ecw5211", "AP"},
{"edgecore_ecw5410", "AP"},
{"edgecore_oap100", "AP"},
{"edgecore_spw2ac1200", "SWITCH"},
{"edgecore_spw2ac1200-lan-poe", "SWITCH"},
{"edgecore_ssw2ac2600", "SWITCH"},
{"hfcl_ion4", "AP"},
{"hfcl_ion4x", "AP"},
{"hfcl_ion4x_2", "AP"},
{"hfcl_ion4xe", "AP"},
{"hfcl_ion4xi", "AP"},
{"indio_um-305ac", "AP"},
{"indio_um-305ax", "AP"},
{"indio_um-310ax-v1", "AP"},
{"indio_um-325ac", "AP"},
{"indio_um-510ac-v3", "AP"},
{"indio_um-510axm-v1", "AP"},
{"indio_um-510axp-v1", "AP"},
{"indio_um-550ac", "AP"},
{"linksys_e8450-ubi", "AP"},
{"linksys_ea6350-v4", "AP"},
{"linksys_ea8300", "AP"},
{"liteon_wpx8324", "AP"},
{"meshpp_s618_cp01", "AP"},
{"meshpp_s618_cp03", "AP"},
{"udaya_a5-id2", "AP"},
{"wallys_dr40x9", "AP"},
{"wallys_dr6018", "AP"},
{"wallys_dr6018_v4", "AP"},
{"x64_vm", "AP"},
{"yuncore_ax840", "AP"},
{"yuncore_fap640", "AP"},
{"yuncore_fap650", "AP"}};
}

View File

@@ -576,8 +576,8 @@ namespace ORM {
bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
try {
assert(ValidFieldName(FieldName));
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Update(Session);
RecordTuple RT;
@@ -593,7 +593,6 @@ namespace ORM {
Update.execute();
if (Cache_)
Cache_->UpdateCache(R);
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
@@ -663,7 +662,6 @@ namespace ORM {
assert(ValidFieldName(FieldName));
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Delete(Session);
std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
@@ -673,7 +671,6 @@ namespace ORM {
Delete.execute();
if (Cache_)
Cache_->Delete(FieldName, Value);
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
@@ -685,13 +682,11 @@ namespace ORM {
try {
assert(!WhereClause.empty());
Poco::Data::Session Session = Pool_.get();
Session.begin();
Poco::Data::Statement Delete(Session);
std::string St = "delete from " + TableName_ + " where " + WhereClause;
Delete << St;
Delete.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);

View File

@@ -565,7 +565,6 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *TRANSFER = "transfer";
static const char *CERTUPDATE = "certupdate";
static const char *POWERCYCLE = "powercycle";
static const char *RRM = "rrm";
static const char *REQUIREMENTS = "requirements";
@@ -688,7 +687,6 @@ namespace OpenWifi::uCentralProtocol {
static const char *TRANSFER = "transfer";
static const char *CERTUPDATE = "certupdate";
static const char *POWERCYCLE = "powercycle";
static const char *RRM = "rrm";
static const char *ACTIONS = "actions";
@@ -787,7 +785,6 @@ namespace OpenWifi::APCommands {
rrm,
certupdate,
transfer,
powercycle,
unknown
};
@@ -802,7 +799,7 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE
RESTAPI::Protocol::TRANSFER
};
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
@@ -831,11 +828,6 @@ namespace OpenWifi::Provisioning::DeviceClass {
} // namespace OpenWifi::Provisioning::DeviceClass
namespace OpenWifi::Platforms {
static const std::string AP = "ap";
static const std::string SWITCH = "switch";
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

@@ -126,6 +126,20 @@ namespace OpenWifi::Utils {
[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
[[nodiscard]] inline uint8_t CalculateMacAddressHash(std::uint64_t value) {
uint8_t hash = 0, i=6;
while(i) {
hash ^= (value & 0xFF) + 1;
value >>= 8;
--i;
}
return hash;
}
[[nodiscard]] inline uint8_t CalculateMacAddressHash(const std::string & value) {
return CalculateMacAddressHash(MACToInt(value));
}
template <typename T> std::string int_to_hex(T i) {
std::stringstream stream;
stream << std::setfill('0') << std::setw(12) << std::hex << i;
@@ -316,90 +330,5 @@ namespace OpenWifi::Utils {
uint32_t Port;
};
class CompressedString {
public:
CompressedString() {
DecompressedSize_ = 0;
};
explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
CompressIt(Data);
}
CompressedString(const CompressedString &Data) {
this->DecompressedSize_ = Data.DecompressedSize_;
this->CompressedData_ = Data.CompressedData_;
}
CompressedString& operator=(const CompressedString& rhs) {
if (this != &rhs) {
this->DecompressedSize_ = rhs.DecompressedSize_;
this->CompressedData_ = rhs.CompressedData_;
}
return *this;
}
CompressedString& operator=(CompressedString&& rhs) {
if (this != &rhs) {
this->DecompressedSize_ = rhs.DecompressedSize_;
this->CompressedData_ = rhs.CompressedData_;
}
return *this;
}
~CompressedString() = default;
operator std::string() const {
return DecompressIt();
}
CompressedString &operator=(const std::string &Data) {
DecompressedSize_ = Data.size();
CompressIt(Data);
return *this;
}
auto CompressedSize() const { return CompressedData_.size(); }
auto DecompressedSize() const { return DecompressedSize_; }
private:
std::string CompressedData_;
std::size_t DecompressedSize_;
inline void CompressIt(const std::string &Data) {
z_stream strm; // = {0};
CompressedData_.resize(Data.size());
strm.next_in = (Bytef *)Data.data();
strm.avail_in = Data.size();
strm.next_out = (Bytef *)CompressedData_.data();
strm.avail_out = Data.size();
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
deflate(&strm, Z_FINISH);
deflateEnd(&strm);
CompressedData_.resize(strm.total_out);
}
[[nodiscard]] std::string DecompressIt() const {
std::string Result;
if(DecompressedSize_!=0) {
Result.resize(DecompressedSize_);
z_stream strm ; //= {0};
strm.next_in = (Bytef *)CompressedData_.data();
strm.avail_in = CompressedData_.size();
strm.next_out = (Bytef *)Result.data();
strm.avail_out = Result.size();
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
inflateInit2(&strm, 15 + 32);
inflate(&strm, Z_FINISH);
inflateEnd(&strm);
}
return Result;
}
};
} // namespace OpenWifi::Utils

View File

@@ -146,7 +146,7 @@ namespace OpenWifi {
auto WebClientSecureContext =
new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName,
CertFileName, "", Poco::Net::Context::VERIFY_NONE);
CertFileName, "", Poco::Net::Context::VERIFY_RELAXED);
Poco::Crypto::X509Certificate WebRoot(RootCaFileName);
WebClientSecureContext->addCertificateAuthority(WebRoot);
WebClientSecureContext->disableStatelessSessionResumption();

View File

@@ -56,10 +56,10 @@ namespace OpenWifi {
struct DeviceDetails {
std::string reason;
std::string author;
std::uint64_t created=Utils::Now();
std::uint64_t created;
};
static std::map<std::uint64_t , DeviceDetails> BlackListDevices;
static std::map<std::string, DeviceDetails> BlackListDevices;
static std::recursive_mutex BlackListMutex;
bool Storage::InitializeBlackListCache() {
@@ -78,7 +78,7 @@ namespace OpenWifi {
auto Reason = RSet[1].convert<std::string>();
auto Author = RSet[2].convert<std::string>();
auto Created = RSet[3].convert<std::uint64_t>();
BlackListDevices[Utils::MACToInt(SerialNumber)] =
BlackListDevices[SerialNumber] =
DeviceDetails{.reason = Reason, .author = Author, .created = Created};
More = RSet.moveNext();
}
@@ -93,7 +93,6 @@ namespace OpenWifi {
bool Storage::AddBlackListDevice(GWObjects::BlackListedDevice &Device) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Insert(Sess);
std::string St{"INSERT INTO BlackList (" + DB_BlackListDeviceSelectFields + ") " +
@@ -103,9 +102,9 @@ namespace OpenWifi {
ConvertBlackListDeviceRecord(Device, T);
Insert << ConvertParams(St), Poco::Data::Keywords::use(T);
Insert.execute();
Sess.commit();
std::lock_guard G(BlackListMutex);
BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
BlackListDevices[Device.serialNumber] = DeviceDetails{
.reason = Device.reason, .author = Device.author, .created = Device.created};
return true;
} catch (const Poco::Exception &E) {
@@ -131,7 +130,6 @@ namespace OpenWifi {
bool Storage::DeleteBlackListDevice(std::string &SerialNumber) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM BlackList WHERE SerialNumber=?"};
@@ -139,9 +137,9 @@ namespace OpenWifi {
Poco::toLowerInPlace(SerialNumber);
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
Delete.execute();
Sess.commit();
std::lock_guard G(BlackListMutex);
BlackListDevices.erase(Utils::MACToInt(SerialNumber));
BlackListDevices.erase(SerialNumber);
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -179,7 +177,6 @@ namespace OpenWifi {
GWObjects::BlackListedDevice &Device) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
std::string St{"UPDATE BlackList SET " + DB_BlackListDeviceUpdateFields +
@@ -190,9 +187,9 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(T),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Sess.commit();
std::lock_guard G(BlackListMutex);
BlackListDevices[Utils::MACToInt(Device.serialNumber)] = DeviceDetails{
BlackListDevices[Device.serialNumber] = DeviceDetails{
.reason = Device.reason, .author = Device.author, .created = Device.created};
return true;
@@ -236,10 +233,10 @@ namespace OpenWifi {
return BlackListDevices.size();
}
bool Storage::IsBlackListed(std::uint64_t SerialNumber, std::string &reason,
bool Storage::IsBlackListed(const std::string &SerialNumber, std::string &reason,
std::string &author, std::uint64_t &created) {
std::lock_guard G(BlackListMutex);
auto DeviceHint = BlackListDevices.find(SerialNumber);
auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
if (DeviceHint == end(BlackListDevices))
return false;
reason = DeviceHint->second.reason;
@@ -248,9 +245,9 @@ namespace OpenWifi {
return true;
}
bool Storage::IsBlackListed(std::uint64_t SerialNumber) {
bool Storage::IsBlackListed(const std::string &SerialNumber) {
std::lock_guard G(BlackListMutex);
auto DeviceHint = BlackListDevices.find(SerialNumber);
auto DeviceHint = BlackListDevices.find(Poco::toLower(SerialNumber));
return DeviceHint != end(BlackListDevices);
}
} // namespace OpenWifi

View File

@@ -17,11 +17,11 @@
namespace OpenWifi {
bool Storage::CreateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
bool Storage::CreateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Capabilities) {
try {
Session.begin();
Poco::Data::Statement UpSert(Session);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement UpSert(Sess);
std::string TCaps{Capabilities.AsString()};
uint64_t Now = Utils::Now();
@@ -33,7 +33,6 @@ namespace OpenWifi {
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
Poco::Data::Keywords::use(Now);
UpSert.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -42,11 +41,11 @@ namespace OpenWifi {
return false;
}
bool Storage::UpdateDeviceCapabilities(Poco::Data::Session &Session, std::string &SerialNumber,
bool Storage::UpdateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Caps) {
try {
Session.begin();
Poco::Data::Statement UpSert(Session);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement UpSert(Sess);
uint64_t Now = Utils::Now();
if (!Caps.Compatible().empty() && !Caps.Platform().empty())
@@ -62,7 +61,6 @@ namespace OpenWifi {
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(TCaps),
Poco::Data::Keywords::use(Now);
UpSert.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -101,14 +99,13 @@ namespace OpenWifi {
bool Storage::DeleteDeviceCapabilities(std::string &SerialNumber) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM Capabilities WHERE SerialNumber=?"};
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),

View File

@@ -105,7 +105,6 @@ namespace OpenWifi {
bool Storage::RemoveOldCommands(std::string &SerialNumber, std::string &Command) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{
@@ -113,7 +112,8 @@ namespace OpenWifi {
Delete << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
Poco::Data::Keywords::use(Command);
Delete.execute();
Sess.commit();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -146,7 +146,6 @@ namespace OpenWifi {
RemoveOldCommands(SerialNumber, Command.Command);
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Insert(Sess);
std::string St{"INSERT INTO CommandList ( " + DB_Command_SelectFields + " ) VALUES( " +
@@ -157,7 +156,7 @@ namespace OpenWifi {
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
Insert.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
@@ -216,7 +215,6 @@ namespace OpenWifi {
bool Storage::DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
@@ -239,7 +237,8 @@ namespace OpenWifi {
Delete << IntroStatement + DateSelector;
Delete.execute();
Sess.commit();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -275,6 +274,7 @@ namespace OpenWifi {
if (Records.size() < HowMany)
Done = true;
}
Select.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -286,7 +286,6 @@ namespace OpenWifi {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
std::string St{"UPDATE CommandList SET Status=?, Executed=?, Completed=?, "
@@ -300,7 +299,7 @@ namespace OpenWifi {
Poco::Data::Keywords::use(Command.ErrorCode), Poco::Data::Keywords::use(UUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
@@ -312,7 +311,6 @@ namespace OpenWifi {
bool Storage::SetCommandExecuted(std::string &CommandUUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now();
@@ -323,7 +321,6 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -334,7 +331,6 @@ namespace OpenWifi {
void Storage::RemovedExpiredCommands() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
@@ -345,7 +341,8 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(Window);
Update.execute();
Sess.commit();
Update.reset(Sess);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
@@ -354,7 +351,6 @@ namespace OpenWifi {
bool Storage::SetCommandLastTry(std::string &CommandUUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now();
@@ -363,7 +359,6 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(CommandUUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -374,7 +369,6 @@ namespace OpenWifi {
void Storage::RemoveTimedOutCommands() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now(), Window = Now - CommandManager()->CommandTimeout();
@@ -383,7 +377,7 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Window);
Update.execute();
Sess.commit();
Update.reset(Sess);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
@@ -392,7 +386,6 @@ namespace OpenWifi {
bool Storage::SetCommandTimedOut(std::string &CommandUUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now();
@@ -402,7 +395,6 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Status), Poco::Data::Keywords::use(CommandUUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -433,7 +425,6 @@ namespace OpenWifi {
bool Storage::DeleteCommand(std::string &UUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM CommandList WHERE UUID=?"};
@@ -444,7 +435,8 @@ namespace OpenWifi {
St = "DELETE FROM FileUploads WHERE UUID=?";
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
Delete.execute();
Sess.commit();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -518,7 +510,6 @@ namespace OpenWifi {
auto Now = Utils::Now();
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
std::string St{"UPDATE CommandList SET Executed=? WHERE UUID=?"};
@@ -527,7 +518,7 @@ namespace OpenWifi {
Poco::Data::Keywords::use(UUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -564,7 +555,6 @@ namespace OpenWifi {
}
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Status = to_string(Storage::CommandExecutionType::COMMAND_COMPLETED);
@@ -576,7 +566,6 @@ namespace OpenWifi {
Poco::Data::Keywords::use(ResultStr), Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(tET), Poco::Data::Keywords::use(UUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -614,7 +603,6 @@ namespace OpenWifi {
bool Storage::CancelWaitFile(std::string &UUID, std::string &ErrorText) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
auto Now = Utils::Now();
uint64_t Size = 0, WaitForFile = 0;
@@ -628,7 +616,6 @@ namespace OpenWifi {
Poco::Data::Keywords::use(ErrorText), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(UUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -644,7 +631,6 @@ namespace OpenWifi {
uint64_t Size = FileContent.str().size();
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Statement(Sess);
std::string StatementStr;
@@ -658,14 +644,14 @@ namespace OpenWifi {
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
Poco::Data::Keywords::use(UUID);
Statement.execute();
Sess.commit();
if (Size < FileUploader()->MaxSize()) {
Poco::Data::BLOB TheBlob;
TheBlob.appendRaw((const unsigned char *)FileContent.str().c_str(),
FileContent.str().size());
Sess.begin();
Poco::Data::Statement Insert(Sess);
std::string FileType{Type};
@@ -676,12 +662,10 @@ namespace OpenWifi {
Poco::Data::Keywords::use(FileType), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(TheBlob);
Insert.execute();
Sess.commit();
return true;
} else {
poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
}
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
@@ -728,7 +712,6 @@ namespace OpenWifi {
bool Storage::SetCommandResult(std::string &UUID, std::string &Result) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
auto Now = Utils::Now();
@@ -739,7 +722,6 @@ namespace OpenWifi {
Poco::Data::Keywords::use(Result), Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(UUID);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
@@ -751,14 +733,13 @@ namespace OpenWifi {
bool Storage::RemoveAttachedFile(std::string &UUID) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM FileUploads WHERE UUID=?"};
Delete << ConvertParams(St), Poco::Data::Keywords::use(UUID);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
@@ -770,13 +751,11 @@ namespace OpenWifi {
bool Storage::RemoveUploadedFilesRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from FileUploads where Created<?"};
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -787,13 +766,11 @@ namespace OpenWifi {
bool Storage::RemoveCommandListRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from CommandList where Submitted<?"};
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);

View File

@@ -82,7 +82,6 @@ namespace OpenWifi {
if (!TmpName.empty())
return false;
Sess.begin();
Poco::Data::Statement Insert(Sess);
std::string St2{"INSERT INTO DefaultFirmwares ( " + DB_DefFirmware_SelectFields +
@@ -95,7 +94,6 @@ namespace OpenWifi {
Insert << ConvertParams(St2),
Poco::Data::Keywords::use(R);
Insert.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
@@ -109,7 +107,6 @@ namespace OpenWifi {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
Poco::toLowerInPlace(deviceType);
@@ -117,7 +114,7 @@ namespace OpenWifi {
Delete << ConvertParams(St), Poco::Data::Keywords::use(deviceType);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -128,9 +125,9 @@ namespace OpenWifi {
bool Storage::UpdateDefaultFirmware(GWObjects::DefaultFirmware &DefFirmware) {
try {
uint64_t Now = Utils::Now();
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
uint64_t Now = time(nullptr);
Poco::Data::Statement Update(Sess);
DefFirmware.LastModified = Now;
Poco::toLowerInPlace(DefFirmware.deviceType);
@@ -146,7 +143,7 @@ namespace OpenWifi {
Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(DefFirmware.deviceType);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),

View File

@@ -19,39 +19,37 @@ namespace OpenWifi {
"Models TEXT, "
"Description TEXT, "
"Created BIGINT , "
"LastModified BIGINT, Platform TEXT )"};
"LastModified BIGINT)"};
const static std::string DB_DefConfig_SelectFields{"Name, "
"Configuration, "
"Models, "
"Description, "
"Created, "
"LastModified, Platform "};
"LastModified "};
const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?,?"};
const static std::string DB_DefConfig_InsertValues{"?,?,?,?,?,?"};
typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t, std::string>
typedef Poco::Tuple<std::string, std::string, std::string, std::string, uint64_t, uint64_t>
DefConfigRecordTuple;
typedef std::vector<DefConfigRecordTuple> DefConfigRecordList;
void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration &T) {
T.name = R.get<0>();
T.configuration = R.get<1>();
T.models = RESTAPI_utils::to_object_array(R.get<2>());
T.description = R.get<3>();
T.created = R.get<4>();
T.lastModified = R.get<5>();
T.platform = R.get<6>();
T.Name = R.get<0>();
T.Configuration = R.get<1>();
T.Models = RESTAPI_utils::to_object_array(R.get<2>());
T.Description = R.get<3>();
T.Created = R.get<4>();
T.LastModified = R.get<5>();
}
void Convert(const GWObjects::DefaultConfiguration &R, DefConfigRecordTuple &T) {
T.set<0>(R.name);
T.set<1>(R.configuration);
T.set<2>(RESTAPI_utils::to_string(R.models));
T.set<3>(R.description);
T.set<4>(R.created);
T.set<5>(R.lastModified);
T.set<6>(R.platform);
T.set<0>(R.Name);
T.set<1>(R.Configuration);
T.set<2>(RESTAPI_utils::to_string(R.Models));
T.set<3>(R.Description);
T.set<4>(R.Created);
T.set<5>(R.LastModified);
}
bool Storage::CreateDefaultConfiguration(std::string &Name,
@@ -71,10 +69,9 @@ namespace OpenWifi {
if (!TmpName.empty())
return false;
Config::Config Cfg(DefConfig.configuration);
Config::Config Cfg(DefConfig.Configuration);
if (Cfg.Valid()) {
Sess.begin();
Poco::Data::Statement Insert(Sess);
std::string St{"INSERT INTO DefaultConfigs ( " + DB_DefConfig_SelectFields +
@@ -86,7 +83,6 @@ namespace OpenWifi {
Convert(DefConfig, R);
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
Insert.execute();
Sess.commit();
return true;
} else {
poco_warning(Logger(), "Cannot create device: invalid configuration.");
@@ -103,14 +99,13 @@ namespace OpenWifi {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM DefaultConfigs WHERE Name=?"};
Delete << ConvertParams(St), Poco::Data::Keywords::use(Name);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -122,14 +117,14 @@ namespace OpenWifi {
bool Storage::UpdateDefaultConfiguration(std::string &Name,
GWObjects::DefaultConfiguration &DefConfig) {
try {
uint64_t Now = Utils::Now();
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
uint64_t Now = time(nullptr);
Poco::Data::Statement Update(Sess);
DefConfig.lastModified = Now;
DefConfig.LastModified = Now;
std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?, Models=?, "
"Description=?, Created=? , LastModified=? , Platform=? WHERE Name=?"};
"Description=?, Created=? , LastModified=? WHERE Name=?"};
DefConfigRecordTuple R;
Convert(DefConfig, R);
@@ -137,7 +132,6 @@ namespace OpenWifi {
Update << ConvertParams(St), Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(Name);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -221,30 +215,31 @@ namespace OpenWifi {
return false;
}
bool Storage::FindDefaultConfigurationForModel(const std::string &DeviceModel, const std::string &Platform,
GWObjects::DefaultConfiguration &Config) {
bool Storage::FindDefaultConfigurationForModel(const std::string &Model,
GWObjects::DefaultConfiguration &DefConfig) {
try {
DefConfigRecordList DefConfigs;
DefConfigRecordList Records;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Select << "SELECT " + DB_DefConfig_SelectFields + " FROM DefaultConfigs",
Poco::Data::Keywords::into(DefConfigs);
Poco::Data::Keywords::into(Records);
Select.execute();
for (const auto &DefConfig : DefConfigs) {
GWObjects::DefaultConfiguration C;
Convert(DefConfig, C);
for (const auto &Model : C.models) {
if ((Model == "*" || Model == DeviceModel) && (Config.platform == Platform)){
Config = C;
for (const auto &i : Records) {
GWObjects::DefaultConfiguration Config;
Convert(i, Config);
for (const auto &j : Config.Models) {
if (j == "*" || j == Model) {
DefConfig = Config;
return true;
}
}
}
Logger().information(
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", DeviceModel));
fmt::format("AUTO-PROVISIONING: no default configuration for model:{}", Model));
return false;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));

View File

@@ -172,18 +172,14 @@ namespace OpenWifi {
R.set<30>(D.connectReason);
}
bool Storage::GetDeviceCount(uint64_t &Count, const std::string &platform) {
bool Storage::GetDeviceCount(uint64_t &Count) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
if(!platform.empty()) {
std::string st{"SELECT COUNT(*) FROM Devices WHERE DeviceType='" + platform + "'"};
Select << st, Poco::Data::Keywords::into(Count);
} else {
std::string st{"SELECT COUNT(*) FROM Devices"};
Select << st, Poco::Data::Keywords::into(Count);
}
std::string st{"SELECT COUNT(*) FROM Devices"};
Select << st, Poco::Data::Keywords::into(Count);
Select.execute();
return true;
} catch (const Poco::Exception &E) {
@@ -194,37 +190,16 @@ namespace OpenWifi {
bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
std::vector<std::string> &SerialNumbers,
const std::string &orderBy,
const std::string &platform, bool includeProvisioned) {
const std::string &orderBy) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st;
std::string whereClause = "";
if(!platform.empty()) {
if (includeProvisioned == false) {
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
} else {
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
}
//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
} else {
if (includeProvisioned == false) {
whereClause = fmt::format("WHERE entity='' and venue=''");
}
//st = "SELECT SerialNumber From Devices ";
}
st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
if (orderBy.empty())
st += " ORDER BY SerialNumber ASC ";
st = "SELECT SerialNumber From Devices ORDER BY SerialNumber ASC ";
else
st += orderBy;
st = "SELECT SerialNumber From Devices " + orderBy;
Select << st + ComputeRange(From, HowMany), Poco::Data::Keywords::into(SerialNumbers);
Select.execute();
@@ -235,7 +210,7 @@ namespace OpenWifi {
return false;
}
/* bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
bool Storage::UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
uint64_t &NewUUID) {
try {
@@ -280,7 +255,7 @@ namespace OpenWifi {
}
return false;
}
*/
bool Storage::RollbackDeviceConfigurationChange(std::string & SerialNumber) {
try {
GWObjects::Device D;
@@ -290,10 +265,9 @@ namespace OpenWifi {
D.pendingUUID = 0;
D.LastConfigurationChange = Utils::Now();
SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
DeviceRecordTuple R;
@@ -303,7 +277,6 @@ namespace OpenWifi {
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -313,43 +286,22 @@ namespace OpenWifi {
bool Storage::CompleteDeviceConfigurationChange(std::string & SerialNumber) {
try {
auto Session = Pool_->get();
return CompleteDeviceConfigurationChange(Session, SerialNumber);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::CompleteDeviceConfigurationChange(Poco::Data::Session & Session, std::string & SerialNumber) {
try {
GWObjects::Device D;
if (!GetDevice(SerialNumber, D))
return false;
if(!D.pendingConfiguration.empty()) {
D.Configuration = D.pendingConfiguration;
D.pendingConfiguration.clear();
}
if(D.pendingUUID!=0) {
D.UUID = D.pendingUUID;
D.pendingUUID = 0;
}
// if this is a broken device, fix it...
if(D.UUID==0) {
Config::Config Cfg(D.Configuration);
if(Cfg.Valid()) {
D.UUID = Cfg.UUID();
}
}
if(D.pendingConfiguration.empty())
return true;
D.Configuration = D.pendingConfiguration;
D.pendingConfiguration.clear();
D.UUID = D.pendingUUID;
D.pendingUUID = 0;
D.LastConfigurationChange = Utils::Now();
SetCurrentConfigurationID(Utils::SerialNumberToInt(SerialNumber), D.UUID);
Session.begin();
Poco::Data::Statement Update(Session);
ConfigurationCache().Add(Utils::SerialNumberToInt(SerialNumber), D.UUID);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
DeviceRecordTuple R;
ConvertDeviceRecord(D, R);
@@ -358,7 +310,6 @@ namespace OpenWifi {
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -377,12 +328,13 @@ namespace OpenWifi {
return false;
}
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
GWObjects::Device D;
if (!GetDevice(SerialNumber, D))
return false;
uint64_t Now = time(nullptr);
if(NewUUID==0) {
D.pendingUUID = NewUUID = (D.LastConfigurationChange == Now ? Now + 1 : Now);
@@ -391,8 +343,6 @@ namespace OpenWifi {
}
if (Cfg.SetUUID(NewUUID)) {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Update(Sess);
D.pendingConfiguration = Cfg.get();
@@ -403,7 +353,6 @@ namespace OpenWifi {
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Sess.commit();
poco_information(Logger(),
fmt::format("DEVICE-PENDING-CONFIGURATION-UPDATED({}): New UUID is {}",
SerialNumber, NewUUID));
@@ -417,74 +366,68 @@ namespace OpenWifi {
return false;
}
bool Storage::SetDeviceLastRecordedContact(LockedDbSession &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
try {
std::lock_guard Lock(Session.Mutex());
return SetDeviceLastRecordedContact(Session.Session(), SerialNumber, lastRecordedContact);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::SetDeviceLastRecordedContact(Poco::Data::Session &Session, std::string &SerialNumber, std::uint64_t lastRecordedContact) {
try {
Session.begin();
Poco::Data::Statement Update(Session);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
std::string St{"UPDATE Devices SET lastRecordedContact=? WHERE SerialNumber=?"};
Update << ConvertParams(St), Poco::Data::Keywords::use(lastRecordedContact),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::SetDeviceLastRecordedContact(std::string &SerialNumber, std::uint64_t lastRecordedContact) {
try {
auto Session = Pool_->get();
return SetDeviceLastRecordedContact(Session, SerialNumber, lastRecordedContact);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::CreateDevice(Poco::Data::Session &Sess, GWObjects::Device &DeviceDetails) {
bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
std::string SerialNumber;
try {
Config::Config Cfg(DeviceDetails.Configuration);
uint64_t Now = Utils::Now();
DeviceDetails.modified = Utils::Now();
DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
std::string St{"SELECT SerialNumber FROM Devices WHERE SerialNumber=?"};
DeviceDetails.Configuration = Cfg.get();
Sess.begin();
Poco::Data::Statement Insert(Sess);
// Select << ConvertParams(St), Poco::Data::Keywords::into(SerialNumber),
// Poco::Data::Keywords::use(DeviceDetails.SerialNumber);
// Select.execute();
std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
// if (Select.rowsExtracted() == 0) {
Config::Config Cfg(DeviceDetails.Configuration);
uint64_t Now = Utils::Now();
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
DeviceRecordTuple R;
ConvertDeviceRecord(DeviceDetails, R);
Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
Insert.execute();
Sess.commit();
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
} else {
poco_warning(Logger(), "Cannot create device: invalid configuration.");
return false;
}
DeviceDetails.modified = Utils::Now();
DeviceDetails.CreationTimestamp = DeviceDetails.LastConfigurationDownload =
DeviceDetails.UUID = DeviceDetails.LastConfigurationChange = Now;
if (Cfg.Valid() && Cfg.SetUUID(DeviceDetails.UUID)) {
DeviceDetails.Configuration = Cfg.get();
Poco::Data::Statement Insert(Sess);
std::string St2{"INSERT INTO Devices ( " + DB_DeviceSelectFields + " ) " +
DB_DeviceInsertValues + " ON CONFLICT (SerialNumber) DO NOTHING"};
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
DeviceRecordTuple R;
ConvertDeviceRecord(DeviceDetails, R);
Insert << ConvertParams(St2), Poco::Data::Keywords::use(R);
Insert.execute();
SetCurrentConfigurationID(DeviceDetails.SerialNumber, DeviceDetails.UUID);
SerialNumberCache()->AddSerialNumber(DeviceDetails.SerialNumber);
return true;
} else {
poco_warning(Logger(), "Cannot create device: invalid configuration.");
return false;
}
// } else {
// poco_warning(Logger(), fmt::format("Device {} already exists.", SerialNumber));
// return false;
// }
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -492,26 +435,6 @@ namespace OpenWifi {
return false;
}
bool Storage::CreateDevice(LockedDbSession &Session, GWObjects::Device &DeviceDetails) {
try {
std::lock_guard Lock(Session.Mutex());
return CreateDevice(Session.Session(), DeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::CreateDevice(GWObjects::Device &DeviceDetails) {
try {
auto Session = Pool_->get();
return CreateDevice(Session, DeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
static std::string InsertRadiosCountyRegulation(std::string &Config,
const Poco::Net::IPAddress &IPAddress) {
std::string FoundCountry;
@@ -561,18 +484,19 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
return true;
}
bool Storage::CreateDefaultDevice(Poco::Data::Session &Session, std::string &SerialNumber, const Config::Capabilities &Caps,
#define __DBGLOG__ std::cout << __LINE__ << std::endl;
bool Storage::CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
std::string &Firmware,
const Poco::Net::IPAddress &IPAddress,
bool simulated) {
GWObjects::Device D;
// poco_information(Logger(), fmt::format("AUTO-CREATION({}): Start.", SerialNumber));
uint64_t Now = Utils::Now();
poco_information(Logger(), fmt::format("AUTO-CREATION({})", SerialNumber));
uint64_t Now = time(nullptr);
GWObjects::DefaultConfiguration DefConfig;
if (!Caps.Platform().empty() && !Caps.Compatible().empty()) {
@@ -593,31 +517,21 @@ namespace OpenWifi {
}
if (!Found && AP_WS_Server()->UseDefaults() &&
FindDefaultConfigurationForModel(Caps.Compatible(), Caps.Platform(), DefConfig)) {
Config::Config NewConfig(DefConfig.configuration);
FindDefaultConfigurationForModel(Caps.Compatible(), DefConfig)) {
Config::Config NewConfig(DefConfig.Configuration);
NewConfig.SetUUID(Now);
D.Configuration = NewConfig.get();
} else if (!Found) {
if(Caps.Platform()==Platforms::AP) {
Config::Config NewConfig;
NewConfig.SetUUID(Now);
D.Configuration = NewConfig.get();
} else {
Poco::JSON::Object Obj;
Obj.set("uuid", Now);
std::ostringstream os;
Obj.stringify(os);
D.Configuration = os.str();
}
Config::Config NewConfig;
NewConfig.SetUUID(Now);
D.Configuration = NewConfig.get();
}
// We need to insert the country code according to the IP in the radios section...
D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
D.SerialNumber = Poco::toLower(SerialNumber);
D.Compatible = Caps.Compatible();
if(D.Compatible.empty())
D.Compatible = Caps.Model();
D.DeviceType = Poco::toLower(Caps.Platform());
D.DeviceType = Daemon()->IdentifyDevice(D.Compatible);
D.MACAddress = Utils::SerialToMAC(SerialNumber);
D.Manufacturer = Caps.Model();
D.Firmware = Firmware;
@@ -625,13 +539,12 @@ namespace OpenWifi {
D.Notes = SecurityObjects::NoteInfoVec{
SecurityObjects::NoteInfo{(uint64_t)Utils::Now(), "", "Auto-provisioned."}};
CreateDeviceCapabilities(Session, SerialNumber, Caps);
auto Result = CreateDevice(Session, D);
poco_information(Logger(), fmt::format("AUTO-CREATION({}): Done, Result={}", SerialNumber, Result));
return Result;
CreateDeviceCapabilities(SerialNumber, Caps);
return CreateDevice(D);
}
/* bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
bool Storage::GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
@@ -646,19 +559,16 @@ namespace OpenWifi {
}
return false;
}
*/
bool Storage::SetDevicePassword(LockedDbSession &Sess, std::string &SerialNumber, std::string &Password) {
try {
std::lock_guard Lock(Sess.Mutex());
Sess.Session().begin();
Poco::Data::Statement Update(Sess.Session());
bool Storage::SetDevicePassword(std::string &SerialNumber, std::string &Password) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
std::string St{"UPDATE Devices SET DevicePassword=? WHERE SerialNumber=?"};
Update << ConvertParams(St), Poco::Data::Keywords::use(Password),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
Sess.Session().commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -666,20 +576,34 @@ namespace OpenWifi {
return false;
}
std::string Storage::GetPlatform(const std::string &SerialNumber) {
bool Storage::SetConnectInfo(std::string &SerialNumber, std::string &Firmware) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string St = fmt::format("SELECT DeviceType FROM Devices WHERE SerialNumber='{}'", SerialNumber);
std::string Platform;
Select << ConvertParams(St), Poco::Data::Keywords::into(Platform);
// Get the old version and if they do not match, set the last date
std::string St{"SELECT Firmware FROM Devices WHERE SerialNumber=?"};
std::string TmpFirmware;
Select << ConvertParams(St), Poco::Data::Keywords::into(TmpFirmware),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
return Platform;
if (TmpFirmware != Firmware) {
Poco::Data::Statement Update(Sess);
std::string St2{
"UPDATE Devices SET Firmware=?, LastFWUpdate=? WHERE SerialNumber=?"};
uint64_t Now = Utils::Now();
Update << ConvertParams(St2), Poco::Data::Keywords::use(Firmware),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(SerialNumber);
Update.execute();
return true;
}
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return "";
return false;
}
bool Storage::DeleteDevice(std::string &SerialNumber) {
@@ -690,14 +614,12 @@ namespace OpenWifi {
for (const auto &tableName : TableNames) {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St = fmt::format("DELETE FROM {} WHERE SerialNumber='{}'", tableName, SerialNumber);
try {
Delete << St;
Delete.execute();
Sess.commit();
} catch (...) {
}
}
@@ -770,14 +692,19 @@ namespace OpenWifi {
return false;
}
bool Storage::GetDevice(Poco::Data::Session &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
bool Storage::GetDevice(std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
try {
Poco::Data::Statement Select(Session);
std::string St = fmt::format("SELECT {} FROM Devices WHERE SerialNumber='{}'", DB_DeviceSelectFields, SerialNumber);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string St{"SELECT " + DB_DeviceSelectFields +
" FROM Devices WHERE SerialNumber=?"};
DeviceRecordTuple R;
Select << St, Poco::Data::Keywords::into(R);
Select << ConvertParams(St), Poco::Data::Keywords::into(R),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
if (Select.rowsExtracted() == 0)
return false;
ConvertDeviceRecord(R, DeviceDetails);
@@ -788,26 +715,6 @@ namespace OpenWifi {
return false;
}
bool Storage::GetDevice(const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
try {
auto Sess = Pool_->get();
return GetDevice(Sess, SerialNumber, DeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::GetDevice(LockedDbSession &Session, const std::string &SerialNumber, GWObjects::Device &DeviceDetails) {
try {
std::lock_guard Lock(Session.Mutex());
return GetDevice(Session.Session(), SerialNumber, DeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::DeviceExists(std::string &SerialNumber) {
try {
Poco::Data::Session Sess = Pool_->get();
@@ -834,26 +741,6 @@ namespace OpenWifi {
bool Storage::UpdateDevice(GWObjects::Device &NewDeviceDetails) {
try {
Poco::Data::Session Sess = Pool_->get();
return UpdateDevice(Sess, NewDeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::UpdateDevice(LockedDbSession &Session, GWObjects::Device &NewDeviceDetails) {
try {
std::lock_guard Lock(Session.Mutex());
return UpdateDevice(Session.Session(), NewDeviceDetails);
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
bool Storage::UpdateDevice(Poco::Data::Session &Sess, GWObjects::Device &NewDeviceDetails) {
try {
Sess.begin();
Poco::Data::Statement Update(Sess);
DeviceRecordTuple R;
@@ -866,7 +753,6 @@ namespace OpenWifi {
Update << ConvertParams(St2), Poco::Data::Keywords::use(R),
Poco::Data::Keywords::use(NewDeviceDetails.SerialNumber);
Update.execute();
Sess.commit();
// GetDevice(NewDeviceDetails.SerialNumber,NewDeviceDetails);
return true;
} catch (const Poco::Exception &E) {
@@ -876,38 +762,18 @@ namespace OpenWifi {
}
bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
std::vector<GWObjects::Device> &Devices, const std::string &orderBy, const std::string &platform,
bool includeProvisioned) {
std::vector<GWObjects::Device> &Devices, const std::string &orderBy) {
DeviceRecordList Records;
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st;
std::string whereClause = "";
if(platform.empty()) {
// std::string st{"SELECT " + DB_DeviceSelectFields + " FROM Devices " + orderBy.empty()
// ? " ORDER BY SerialNumber ASC " + ComputeRange(From, HowMany)};
std::string st = fmt::format("SELECT {} FROM Devices {} {}", DB_DeviceSelectFields,
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
ComputeRange(From, HowMany));
if (includeProvisioned == false) {
whereClause = fmt::format("WHERE entity='' and venue=''");
}
} else {
if (includeProvisioned == false) {
whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
} else {
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
}
}
st =
fmt::format("SELECT {} FROM Devices {} {} {}", DB_DeviceSelectFields, whereClause,
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
ComputeRange(From, HowMany));
//Logger().information(fmt::format(" GetDevices st is {} ", st));
Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
Select.execute();
@@ -1135,9 +1001,9 @@ namespace OpenWifi {
}
}
uint64_t Associations_2G, Associations_5G, Associations_6G, uptime;
uint64_t Associations_2G, Associations_5G, Associations_6G;
StateUtils::ComputeAssociations(RawObject, Associations_2G, Associations_5G,
Associations_6G, uptime);
Associations_6G);
UpdateCountedMap(Dashboard.associations, "2G", Associations_2G);
UpdateCountedMap(Dashboard.associations, "5G", Associations_5G);
UpdateCountedMap(Dashboard.associations, "6G", Associations_6G);
@@ -1161,25 +1027,4 @@ namespace OpenWifi {
FieldList.push_back(field);
}
void Storage::FixDeviceTypeBug() {
try {
std::vector<std::string> ScriptLines{
"update devices set devicetype='ap' where devicetype='AP';",
"update devices set devicetype='switch' where devicetype='SWITCH';",
"update devices set devicetype='ap' where devicetype!='ap' and devicetype!='switch';"
};
for (const auto &ScriptLine : ScriptLines) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement SqlStatement(Sess);
SqlStatement << ScriptLine, Poco::Data::Keywords::now;
} catch (...) {
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
}
} // namespace OpenWifi

View File

@@ -35,11 +35,10 @@ namespace OpenWifi {
R.set<4>(H.Recorded);
}
bool Storage::AddHealthCheckData(LockedDbSession &Session, const GWObjects::HealthCheck &Check) {
bool Storage::AddHealthCheckData(const GWObjects::HealthCheck &Check) {
try {
std::lock_guard Guard(Session.Mutex());
Session.Session().begin();
Poco::Data::Statement Insert(Session.Session());
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
std::string St{"INSERT INTO HealthChecks ( " + DB_HealthCheckSelectFields +
" ) VALUES( " + DB_HealthCheckInsertValues + " )"};
@@ -48,7 +47,6 @@ namespace OpenWifi {
ConvertHealthCheckRecord(Check, R);
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
Insert.execute();
Session.Session().commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -136,7 +134,7 @@ namespace OpenWifi {
uint64_t ToDate) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
std::string Prefix{"DELETE FROM HealthChecks "};
@@ -160,7 +158,7 @@ namespace OpenWifi {
Delete << Statement + DateSelector;
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -172,13 +170,11 @@ namespace OpenWifi {
bool Storage::RemoveHealthChecksRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from HealthChecks where recorded<?"};
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),

View File

@@ -39,11 +39,11 @@ namespace OpenWifi {
R.set<6>(Log.UUID);
}
bool Storage::AddLog(LockedDbSession &Session, const GWObjects::DeviceLog &Log) {
bool Storage::AddLog(const GWObjects::DeviceLog &Log) {
try {
std::lock_guard Guard(Session.Mutex());
Session.Session().begin();
Poco::Data::Statement Insert(Session.Session());
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
std::string St{"INSERT INTO DeviceLogs (" + DB_LogsSelectFields + ") values( " +
DB_LogsInsertValues + " )"};
@@ -53,7 +53,6 @@ namespace OpenWifi {
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
Insert.execute();
Session.Session().commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -115,7 +114,7 @@ namespace OpenWifi {
uint64_t Type) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
bool HasWhere = DatesIncluded || !SerialNumber.empty();
@@ -142,7 +141,7 @@ namespace OpenWifi {
Delete << StatementStr + DateSelector + TypeSelector;
Delete.execute();
Sess.commit();
Delete.reset(Sess);
return true;
} catch (const Poco::Exception &E) {
@@ -184,13 +183,11 @@ namespace OpenWifi {
bool Storage::RemoveDeviceLogsRecordsOlderThan(uint64_t Date) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from DeviceLogs where recorded<?"};
Delete << ConvertParams(St1), Poco::Data::Keywords::use(Date);
Delete.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),

View File

@@ -8,6 +8,7 @@
#include "AP_WS_Server.h"
#include "StorageService.h"
#include "fmt/format.h"
namespace OpenWifi {
@@ -32,10 +33,10 @@ namespace OpenWifi {
R.set<3>(Stats.Recorded);
}
bool Storage::AddStatisticsData(Poco::Data::Session &Session, const GWObjects::Statistics &Stats) {
bool Storage::AddStatisticsData(const GWObjects::Statistics &Stats) {
try {
Session.begin();
Poco::Data::Statement Insert(Session);
Poco::Data::Session Sess(Pool_->get());
Poco::Data::Statement Insert(Sess);
poco_trace(Logger(), fmt::format("{}: Adding stats. Size={}", Stats.SerialNumber,
std::to_string(Stats.Data.size())));
@@ -45,7 +46,6 @@ namespace OpenWifi {
ConvertStatsRecord(Stats, R);
Insert << ConvertParams(St), Poco::Data::Keywords::use(R);
Insert.execute();
Session.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
@@ -167,7 +167,7 @@ namespace OpenWifi {
uint64_t ToDate) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
bool DatesIncluded = (FromDate != 0 || ToDate != 0);
std::string Prefix{"DELETE FROM Statistics "};
@@ -189,7 +189,7 @@ namespace OpenWifi {
Poco::Data::Statement Select(Sess);
Select << Statement + DateSelector;
Select.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), (fmt::format("{}: Failed with: {}", std::string(__func__),

View File

@@ -275,21 +275,9 @@ namespace OpenWifi {
"Models TEXT, "
"Description TEXT, "
"Created BIGINT , "
"LastModified BIGINT, Platform TEXT)",
"LastModified BIGINT)",
Poco::Data::Keywords::now;
}
std::vector<std::string> Script{
"alter table DefaultConfigs add column Platform text"
};
for (const auto &i : Script) {
try {
Sess << i, Poco::Data::Keywords::now;
} catch (...) {
}
}
return 0;
} catch (const Poco::Exception &E) {
Logger().log(E);