Compare commits

...

57 Commits

Author SHA1 Message Date
Kumiko18
83c4a543d8 14589 & 14652 & 14655 dev test1 2025-06-02 00:29:46 +00:00
Kumiko18
4d1d817b4c WIFI-14589, WIFI-14652 dev-complete
Signed-off-by: Kumiko18 <alex18_huang@accton.com>
2025-05-29 07:43:59 +00:00
alex18_huang
1c4c080cf7 test commit 2025-05-28 11:28:31 +08:00
alex18_huang
daa773ad73 array version
Signed-off-by: alex18_huang <alex18_huang@accton.com>
2025-05-26 14:00:08 +08:00
i-chvets
a5d1eebe6d Merge pull request #405 from Telecominfraproject/version_update
WIFI-14521: fix: Version update - release 4.0.0
2025-04-24 16:56:09 -04:00
Ivan Chvets
ee14f064c8 Merge branch 'master' of github.com:Telecominfraproject/wlan-cloud-ucentralgw into version_update 2025-04-24 16:36:14 -04:00
i-chvets
dbf52c1f23 Merge pull request #406 from Telecominfraproject/WIFI-14521-ci-changes
WIFI-14521 Update to ubuntu-latest for GH runner
2025-04-24 16:18:31 -04:00
Carsten Schafer
9dc6a6bf97 Update to ubuntu-latest for GH runner
Signed-off-by: Carsten Schafer <Carsten.Schafer@kinarasystems.com>
2025-04-24 15:30:49 -04:00
Ivan Chvets
1c0556f8bf fix: Version update - release 4.0.0
Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-04-24 14:09:12 -04:00
i-chvets
d298139525 Merge pull request #403 from Telecominfraproject/wifi-14521_feat_use_clientcas_for_validation
WIFI-14521: feat: Added processing of clientcas
2025-04-09 11:50:04 -04:00
Ivan Chvets
a37c961f5b feat: Added processing of clientcas
https://telecominfraproject.atlassian.net/browse/WIFI-14521

Summary of changes:
- Updated code to add certificates from clientcas to trust chain and
  validate client certificates against it.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2025-04-09 10:30:52 -04:00
Nicolas Alfonso De Pineda Gutierrez
75bcbd748c Merge pull request #398 from Telecominfraproject/WIFI-14349-plat_cache.json-isnt-being-read-correctly-and-can-result-in-huge-memory-ussages-under-very-specific-situations
WIFI-14349-plat_cache.json-isnt-being-read-correctly-and-can-result-in-huge-memory-ussages-under-very-specific-situations
2025-01-21 16:00:14 +01:00
Nicolas de Pineda
b6eba2a96d fix: plat_cache.json not being read correctly
https://telecominfraproject.atlassian.net/browse/WIFI-14349

Summary of changes:
- Resolved an issue where a string field was being read as JSON, causing the output to be incorrectly surrounded by quotation marks.

Signed-off-by: Nicolas de Pineda <nicolas.depineda@galgus.ai>
2025-01-21 09:42:31 +01:00
i-chvets
17082803d4 Merge pull request #397 from Telecominfraproject/OLS-433-fix-switch-schema-sync
OLS-433: fix: updated internal switch schema
2024-12-10 10:23:27 -05:00
Ivan Chvets
26b9a96506 fix: updated internal switch schema
https://telecominfraproject.atlassian.net/browse/OLS-433

Summary of changes:
- Updated internal switch schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-12-10 08:53:01 -05:00
i-chvets
5ce8dae9ec Merge pull request #393 from Telecominfraproject/OLS-433-fix-switch-schema-sync
OLS-433: fix: updated internal switch schema
2024-12-04 15:49:07 -05:00
i-chvets
7da135c1e5 Merge pull request #394 from Telecominfraproject/OLS-380-fix-file-upload
OSL-380: fix: modified code for file upload transactions
2024-12-04 15:48:47 -05:00
Carsten Schafer
50ee4ba5cb Merge pull request #395 from Telecominfraproject/version_update
fix: release 3.2.1 version update
2024-12-04 12:17:39 -05:00
Ivan Chvets
3a8109d7ad fix: release 3.2.1 version update
https://telecominfraproject.atlassian.net/browse/WIFI-14165

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-12-04 12:10:44 -05:00
Ivan Chvets
56232966ec fix: modified code for file upload transactions
https://telecominfraproject.atlassian.net/browse/OLS-380

Summary of changes:
- Modified code to have two distinct transaction in storage file upload.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-29 13:09:34 -05:00
Ivan Chvets
1ecf98d712 fix: updated internal switch schema
https://telecominfraproject.atlassian.net/browse/OLS-433

Summary of changes:
- Updated internal switch schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-29 11:56:05 -05:00
Gopi Raga
f5b60ced61 Merge pull request #392 from Telecominfraproject/WIFI-14292-fix-json-parse-error
WIFI-14292: fix: json parsing error
2024-11-17 11:20:00 +05:30
Ivan Chvets
e4d141bb8e fix: json parsing error
https://telecominfraproject.atlassian.net/browse/WIFI-14292

Summary of changes:
- Removed code that was incorrectly added to JSON string.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-11-15 13:17:12 -05:00
i-chvets
25b4288050 Merge pull request #391 from Telecominfraproject/WIFI-14254-doc-update
WIFI-14254: doc: update protocol.md
2024-10-31 10:39:24 -04:00
Ivan Chvets
82430c2d5d doc: update protocol.md
https://telecominfraproject.atlassian.net/browse/WIFI-14254

Summary of changes:
- Updated PROTOCOL.md with compressed configuration message
  specification.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-10-31 10:14:21 -04:00
i-chvets
7b68ec0536 Merge pull request #390 from Telecominfraproject/WIFI-14227-feat-compressed-config
WIFI-14229: feat: compressed config
2024-10-30 12:08:45 -04:00
Ivan Chvets
839f4fec44 feat: compressed config
https://telecominfraproject.atlassian.net/browse/WIFI-14229

Summary of changes:
- Modified code to compress configuration data, if capabilities object
  has compress command indicator enabled.
- Added encode and compress function to utilities.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-10-30 11:44:02 -04:00
i-chvets
c4178209bb Merge pull request #388 from Telecominfraproject/version_update
WIFI-14165: Release 3.2 version update
2024-09-30 10:12:32 -04:00
Ivan Chvets
79ab67db50 fix: release 3.2 version update
https://telecominfraproject.atlassian.net/browse/WIFI-14165

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-30 09:39:44 -04:00
i-chvets
00bc77feea Merge pull request #385 from Telecominfraproject/WIFI-14134-fix_code_style_change
WIFI-14134: fix: file upload status - code style change
2024-09-27 10:59:14 -04:00
Ivan Chvets
4f00d77d2b fix: file upload status - code style change
https://telecominfraproject.atlassian.net/browse/WIFI-14134

Summary of changes:
- Code style change.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-27 10:34:45 -04:00
i-chvets
c679d4ac40 Merge pull request #383 from Telecominfraproject/WIFI-14134-fix_file_upload_status
WIP: WIFI-14134: fix: file upload status
2024-09-26 21:33:56 -04:00
Ivan Chvets
4a150a9fcb fix: file upload status
https://telecominfraproject.atlassian.net/browse/WIFI-14134

Summary of changes:
- Return 202 in case of file pening upload.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-26 16:07:19 -04:00
i-chvets
83eb603f0a Merge pull request #382 from Telecominfraproject/openapi-fix
WIFI-14165: Fix wrong port in openapi.yaml
2024-09-25 15:10:28 -04:00
Adam Capparelli
38bc0f0d69 Fix wrong port in openapi.yaml
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2024-09-25 11:08:11 -04:00
i-chvets
e7362c2020 Merge pull request #381 from Telecominfraproject/ols-246-feat-cable-diag
OLS-246: feat: add cable diagnostics command
2024-09-25 10:42:52 -04:00
Ivan Chvets
9c9987e190 feat: add cable diagnostics command
https://telecominfraproject.atlassian.net/browse/OLS-246

Summary of changes:
- Modified code to match spec, ie. command is `cable-diagnostics`.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-25 10:17:52 -04:00
i-chvets
4ac7b6ba0b Merge pull request #379 from Telecominfraproject/WIFI-14140-fix-update-schema-multi-psk
WIFI-14140: fix: sync-ed up ucentral schema with code - added missing code
2024-09-25 09:54:12 -04:00
Ivan Chvets
f9ee19af91 fix: sync-ed up ucentral schema with code - added missing code
https://telecominfraproject.atlassian.net/browse/WIFI-14140

Summary of changes:
- Synchronized built-in schema in configuration validation code with
ucentral schema. Added missing code.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-25 08:30:58 -04:00
i-chvets
cd2ab8660f Merge pull request #376 from Telecominfraproject/WIFI-14140-fix-update-schema-multi-psk
WIFI-14140 fix: sync-ed up ucentral schema with code
2024-09-24 10:05:56 -04:00
Ivan Chvets
b9f00f6603 fix: sync-ed up ucentral schema with code
https://telecominfraproject.atlassian.net/browse/WIFI-14140

Summary of changes:
- Synchronized built-in schema in configuration validation code with
  ucentral schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-19 10:26:51 -04:00
i-chvets
596cfd49e1 Merge pull request #375 from Telecominfraproject/ols-246-feat-cable-diag
OLS-246: feat: add cable diagnostics command
2024-09-18 11:45:14 -04:00
Ivan Chvets
b3deba5606 feat: add cable diagnostics command
https://telecominfraproject.atlassian.net/browse/OLS-246

Summary of changes:
- Added `cablediagnostics` command.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-18 11:04:57 -04:00
i-chvets
a97d49a06b Merge pull request #373 from Telecominfraproject/WIFI-13126-feat-fixed-config-doc-update
WIFI-13126: feat: fixedconfig doc update
2024-09-16 10:05:55 -04:00
Ivan Chvets
b1be0604d6 feat: fixedconfig doc update
https://telecominfraproject.atlassian.net/browse/WIFI-13126

Summary of changes:
- Updated documentation.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-13 11:30:40 -04:00
i-chvets
b29f7f7dc4 Merge pull request #372 from Telecominfraproject/WIFI-13126-feat-fixed-config
WIFI-13126: feat: add fixedconfig command
2024-09-11 16:59:16 -04:00
Ivan Chvets
132b31b06b feat: add fixedconfig command
https://telecominfraproject.atlassian.net/browse/WIFI-13126

Summary of changes:
- Added `fixedconfig` command.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-11 16:20:02 -04:00
i-chvets
3114ff8a32 Merge pull request #371 from Telecominfraproject/WIFI-14038-fix-exception-handling-for-zero-queue
WIFI-14038: fix: update code to improve exception handling
2024-09-10 13:45:48 -04:00
Ivan Chvets
9c5aeda5dd fix: update code to improve exception handling
https://telecominfraproject.atlassian.net/browse/WIFI-14038

Summary of changes:
- Modified code to cover zero sized queues under exception handling.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-29 17:57:05 -04:00
i-chvets
783ec99930 Merge pull request #370 from Telecominfraproject/WIFI-13875-fix-use-dns
WIFI-13875: fix: updated valijson version
2024-08-08 10:05:40 -04:00
Ivan Chvets
0c661b8b93 fix: updated valijson version
https://telecominfraproject.atlassian.net/browse/WIFI-13875

Summary of changes:
- Updated valijson version in Docker file to bring in fix for https://github.com/tristanpenman/valijson/issues/181

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-08 09:23:30 -04:00
i-chvets
9d7f4da504 Merge pull request #369 from Telecominfraproject/WIFI-14027-fix-ping-crash
fix: fix crash for non-configure commands
2024-08-01 19:03:54 -04:00
Ivan Chvets
a3b6e7c315 fix: fix crash for non-configure commands
https://telecominfraproject.atlassian.net/browse/WIFI-14027

Summary of changes:
- Modified code to relay errors only in case of configure command and
  strict mode.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-01 17:09:09 -04:00
i-chvets
451680cd5a Merge pull request #368 from Telecominfraproject/WIFI-14019-fix-report-errors-in-strict-only
WIFI-14019: fix: relay errors from ap nos configuration only when strict mode is enabled
2024-07-30 12:50:25 -04:00
Ivan Chvets
7be48c3cfc fix: relay errors from ap nos configuration only when strict mode is
enabled
https://telecominfraproject.atlassian.net/browse/WIFI-14019

Summary of changes:
- Modified code to only relay errors from AP NOS configuration update
  only when strict mode is enabled.

NOTE: AP NOS is capable of modifying config thus fixing invalid configs
(in some cases) and applying resulting configuration. Warning messages
are produced, but error code is being sent back as error/failed.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-07-30 12:21:19 -04:00
i-chvets
b59d1cb4da Merge pull request #366 from Telecominfraproject/WIFI-13985-fix-return-400-on-error
WIFI-13985: commands API will return 400 if command fails on device.
2024-07-26 13:26:27 -04:00
Adam Capparelli
c3a709c2b9 commands API will return 400 if command fails on device.
Signed-off-by: Adam Capparelli <adam.capparelli@mail.utoronto.ca>
2024-07-22 14:28:03 -04:00
37 changed files with 988 additions and 143 deletions

View File

@@ -21,7 +21,7 @@ defaults:
jobs:
docker:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
env:
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
DOCKER_REGISTRY_USERNAME: ucentral

View File

@@ -11,7 +11,7 @@ defaults:
jobs:
helm-package:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
env:
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
HELM_REPO_USERNAME: ucentral

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"chrono": "cpp"
}
}

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(owgw VERSION 3.1.0)
project(owgw VERSION 4.0.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@@ -153,6 +153,7 @@ add_executable( owgw
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
src/storage/storage_packages.cpp
src/storage/storage_scripts.cpp src/storage/storage_scripts.h
src/storage/storage_tables.cpp
src/RESTAPI/RESTAPI_routers.cpp

View File

@@ -1,7 +1,7 @@
ARG DEBIAN_VERSION=11.5-slim
ARG POCO_VERSION=poco-tip-v2
ARG CPPKAFKA_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1.0.2
ARG APP_NAME=owgw
ARG APP_HOME_DIR=/openwifi

View File

@@ -306,8 +306,54 @@ The device should answer:
},
"id" : <same number>
}
```
#### Controller wants the device to apply a given fixed configuration
Controller sends this command when it requires the device to apply fixed configuration, eg. country code. The device
should respond with message indicating failure or success.
```json
{ "jsonrpc" : "2.0",
"method" : "fixedconfig",
"params" : {
"serial" : <serial number>,
"when" : Optional - <UTC time when to apply this config, 0 means immediate, this is a suggestion>
"country" : "<country-code>"
},
}
```
If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller
will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed
and encoded in base64 format:
```json
{ "jsonrpc" : "2.0",
"method" : "configure",
"params" : {
"compress_64" : "<b64 encoded zlib compressed payload>",
"compress_sz" : "<size of uncompressed data in bytes>"
},
"id" : <some number>
}
```
The device should answer:
```json
{ "jsonrpc" : "2.0",
"result" : {
"serial": <serial number>,
"status": {
"error": 0 or an error number,
"text": <description of the error or success, eg. "Applied fixed config, rebooting">
},
"uuid": <UUID>
}
}
```
##### The Answer
The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device

24
ipk-req.json Normal file
View File

@@ -0,0 +1,24 @@
[
{
"jsonrpc": "2.0",
"method": "package_list",
"id": "xxxx"
},
{
"jsonrpc": "2.0",
"method": "package_install",
"params": {
"category": "base/telephony/luci...",
"package": "package_name"
},
"id": "yyyy"
},
{
"jsonrpc": "2.0",
"method": "package_remove",
"params": {
"package": "package_name"
},
"id": "zzzz"
}
]

37
ipk-resp.json Normal file
View File

@@ -0,0 +1,37 @@
[
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
},
"packages": "<installed packages>",
"lastUpdate": ""
},
"id": "xxxx"
},
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
}
},
"id": "yyyy"
},
{
"jsonrpc": "2.0",
"result": {
"serial": "serial number",
"status": {
"error": 0,
"text": "<description of the error or success>"
}
},
"id": "zzzz"
}
]

View File

@@ -12,7 +12,7 @@ info:
url: https://www.ucentral.info/support
servers:
- url: 'https://localhost:16001/api/v1'
- url: 'https://localhost:16002/api/v1'
security:
- bearerAuth: []

View File

@@ -145,6 +145,7 @@ namespace OpenWifi {
std::uint64_t uuid_=0;
bool Simulated_=false;
std::atomic_uint64_t LastContact_=0;
GWObjects::PackagesOnDevice DevicePackages_;
static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
@@ -168,6 +169,9 @@ namespace OpenWifi {
void Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj);
void Process_alarm(Poco::JSON::Object::Ptr ParamsObj);
void Process_rebootLog(Poco::JSON::Object::Ptr ParamsObj);
void Process_packagelist(Poco::JSON::Object::Ptr ParamsObj);
void Process_packageinstall(Poco::JSON::Object::Ptr ParamsObj);
void Process_packageremove(Poco::JSON::Object::Ptr ParamsObj);
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
RawLastHealthcheck_ = H;

View File

@@ -105,10 +105,15 @@ namespace OpenWifi {
Restrictions_.developer = Capabilities->getValue<bool>("developer");
}
if(Capabilities->has("secure-rtty")) {
if (Capabilities->has("secure-rtty")) {
RTTYMustBeSecure_ = Capabilities->getValue<bool>("secure-rtty");
}
if (ParamsObj->has("packages")) {
auto Packages = ParamsObj->getArray("packages");
DevicePackages_.from_json(Packages);
}
State_.locale = FindCountryFromIP()->Get(IP);
GWObjects::Device DeviceInfo;
std::lock_guard DbSessionLock(DbSession_->Mutex());
@@ -149,6 +154,8 @@ namespace OpenWifi {
StorageService()->CreateDefaultDevice( DbSession_->Session(),
SerialNumber_, Caps, Firmware, PeerAddress_,
State_.VerifiedCertificate == GWObjects::SIMULATED);
StorageService()->CreateDeviceInstalledPackages(SerialNumber_,
DevicePackages_);
}
} else if (!Daemon()->AutoProvisioning() && !DeviceExists) {
SendKafkaDeviceNotProvisioned(SerialNumber_, Firmware, Compatible_, CId_);
@@ -156,6 +163,7 @@ namespace OpenWifi {
return EndConnection();
} else if (DeviceExists) {
StorageService()->UpdateDeviceCapabilities(DbSession_->Session(), SerialNumber_, Caps);
StorageService()->CreateDeviceInstalledPackages(SerialNumber_, DevicePackages_);
int Updated{0};
if (!Firmware.empty()) {
if (Firmware != DeviceInfo.Firmware) {

View File

@@ -0,0 +1,61 @@
//
// Created by euphokumiko on 2025-05-19.
//
#include "AP_WS_Connection.h"
#include "StorageService.h"
#include "fmt/format.h"
#include "framework/ow_constants.h"
#include <GWKafkaEvents.h>
namespace OpenWifi {
void AP_WS_Connection::Process_packagelist(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
poco_trace(Logger_, fmt::format("PACKAGE_LIST({}): new entry.", CId_));
return;
}
void AP_WS_Connection::Process_packageinstall(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
if (ParamsObj->has(uCentralProtocol::PACKAGE) && ParamsObj->has(uCentralProtocol::CATEGORY)) {
poco_trace(Logger_, fmt::format("PACKAGE_INSTALL({}): new entry.", CId_));
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return;
}
}
void AP_WS_Connection::Process_packageremove(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) {
poco_warning(Logger_,
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++;
return;
}
if (ParamsObj->has(uCentralProtocol::PACKAGE)) {
poco_trace(Logger_, fmt::format("PACKAGE_REMOVE({}): new entry.", CId_));
} else {
poco_warning(Logger_, fmt::format("LOG({}): Missing parameters.", CId_));
return;
}
}
} // namespace OpenWifi

View File

@@ -71,14 +71,18 @@ namespace OpenWifi {
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
const Poco::Crypto::X509Certificate &Certificate) {
if (IsCertOk()) {
if (!Certificate.issuedBy(*IssuerCert_)) {
poco_warning(
Logger(),
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
return false;
// validate certificate agains trusted chain
for (const auto &cert : ClientCasCerts_) {
if (Certificate.issuedBy(cert)) {
return true;
}
}
return true;
poco_warning(
Logger(),
fmt::format(
"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
ConnectionId)
);
}
return false;
}
@@ -133,6 +137,13 @@ namespace OpenWifi {
Context->addChainCertificate(Issuing);
Context->addCertificateAuthority(Issuing);
// add certificates from clientcas to trust chain
ClientCasCerts_ = Poco::Net::X509Certificate::readPEM(Svr.ClientCas());
for (const auto &cert : ClientCasCerts_) {
Context->addChainCertificate(cert);
Context->addCertificateAuthority(cert);
}
Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
Context->usePrivateKey(Key);

View File

@@ -223,6 +223,7 @@ namespace OpenWifi {
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
Poco::Net::SocketReactor Reactor_;

View File

@@ -111,7 +111,7 @@ namespace OpenWifi {
i >> cache;
for (const auto &[Type, Platform] : cache.items()) {
Platforms_[Type] = Poco::toLower(to_string(Platform));
Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
}
} catch (...) {
}

12
src/ParsePackageList.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "nlohmann/json.hpp"
namespace OpenWiFi {
}

View File

@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
if (Handler != nullptr)
return Handler->ReturnObject(RetObj);
return;
if (Handler == nullptr) {
// nothing to process/return
return;
}
Poco::Net::HTTPResponse::HTTPStatus cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
if (Cmd.ErrorCode > 0) {
// command returned error
cmd_status = Poco::Net::HTTPResponse::HTTP_BAD_REQUEST;
if (Cmd.Command == uCentralProtocol::CONFIGURE) {
// special handling for configure command
if (!Handler->GetBoolParameter("strict", false)) {
// in non-strict mode return success for failed configure command
cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
}
}
}
return Handler->ReturnObject(RetObj, cmd_status);
}
if (Handler != nullptr)
return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
@@ -40,8 +54,8 @@ namespace OpenWifi::RESTAPI_RPC {
std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
Cmd.Submitted = Utils::Now();
Cmd.Executed = 0;
@@ -141,7 +155,13 @@ namespace OpenWifi::RESTAPI_RPC {
auto ScanObj = rpc_answer->get(uCentralProtocol::RESULT)
.extract<Poco::JSON::Object::Ptr>();
ParseWifiScan(ScanObj, ResultText, Logger);
} else {
}
// else if (Cmd.Command == uCentralProtocol::PACKAGE) {
// auto PkgObj = rpc_answer->get(uCentralProtocol::RESULT)
// .extract<Poco::JSON::Object::Ptr>();
// ParsePackageList(PkgObj, ResultText, Logger);
// }
else {
Poco::JSON::Stringifier::stringify(rpc_answer->get(uCentralProtocol::RESULT),
ResultText);
}
@@ -167,6 +187,20 @@ namespace OpenWifi::RESTAPI_RPC {
Cmd.AttachType = "";
}
// If the command fails on the device we should show it as failed and not return 200 OK
// exception is configure command which only reported failed in strict validation mode
if (Cmd.ErrorCode &&
(Cmd.Command != uCentralProtocol::CONFIGURE ||
(Cmd.Command == uCentralProtocol::CONFIGURE && Handler->GetBoolParameter("strict", false))
))
{
Logger.information(fmt::format(
"Command failed with error on device: {} Reason: {}.",
Cmd.ErrorCode, Cmd.ErrorText));
return SetCommandStatus(Cmd, Request, Response, Handler,
Storage::CommandExecutionType::COMMAND_FAILED, Logger);
}
if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
// we need to post a kafka event for this.
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
@@ -175,6 +209,7 @@ namespace OpenWifi::RESTAPI_RPC {
DeviceConfigurationChangeKafkaEvent KEvent(
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
Config);
}
}

View File

@@ -91,6 +91,8 @@ namespace OpenWifi {
TransactionId_, UUID, RPC, Poco::Thread::current()->id()));
return Rtty(UUID, RPC, 60000ms, Restrictions);
};
case APCommands::Commands::package:
return GetPackages();
default:
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
@@ -128,6 +130,28 @@ namespace OpenWifi {
return DeleteChecks();
case APCommands::Commands::statistics:
return DeleteStatistics();
// case APCommands::Commands::package:
// GWObjects::DeviceRestrictions Restrictions;
// if (!AP_WS_Server()->Connected(SerialNumberInt_, Restrictions)) {
// CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceNotConnected);
// return BadRequest(RESTAPI::Errors::DeviceNotConnected);
// }
// std::string Command_UUID;
// APCommands::Commands CommandName;
// if (CommandManager()->CommandRunningForDevice(SerialNumberInt_, Command_UUID,
// CommandName)) {
// auto Extra = fmt::format("UUID={} Command={}", Command_UUID,
// APCommands::to_string(CommandName));
// CallCanceled(Command_.c_str(), RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
// return BadRequest(RESTAPI::Errors::DeviceIsAlreadyBusy, Extra);
// }
// auto UUID = MicroServiceCreateUUID();
// auto RPC = CommandManager()->Next_RPC_ID();
// poco_debug(Logger_, fmt::format("Command {} TID={} can proceed. Identified as {} "
// "and RPCID as {}. thr_id={}",
// Command_, TransactionId_, UUID, RPC,
// Poco::Thread::current()->id()));
// return DeletePackages(UUID, RPC, 12000, Restrictions);
default:
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
@@ -167,7 +191,10 @@ namespace OpenWifi {
{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::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
// {APCommands::Commands::package, false, true, &RESTAPI_device_commandHandler::PackageInstall, 120000ms},
};
void RESTAPI_device_commandHandler::DoPost() {
@@ -405,6 +432,52 @@ namespace OpenWifi {
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::GetPackages() {
poco_debug(Logger_, fmt::format("GET-PACKAGES({},{}): TID={} user={} serial={}. thr_id={}",
TransactionId_, Requester(), SerialNumber_,
Poco::Thread::current()->id()));
if(IsDeviceSimulated(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::PackagesOnDevice Pkgs;
StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs);
Poco::JSON::Array::Ptr ArrayObj = Poco::SharedPtr<Poco::JSON::Array>(new Poco::JSON::Array);
for (const auto &i : Pkgs.packageArray) {
Poco::JSON::Object::Ptr Obj =
Poco::SharedPtr<Poco::JSON::Object>(new Poco::JSON::Object);
i.to_json(*Obj);
ArrayObj->add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::PACKAGES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
}
// void RESTAPI_device_commandHandler::DeletePackages() {
// poco_debug(Logger_, fmt::format("DELETE-PACKAGES({},{}): TID={} user={} serial={}. thr_id={}",
// TransactionId_, Requester(), SerialNumber_,
// Poco::Thread::current()->id()));
// if(IsDeviceSimulated(SerialNumber_)) {
// CallCanceled("PACKAGEDELETE", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
// return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
// }
// GWObjects::PackageList Pkgs;
// if (StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs)) {
// Poco::JSON::Object RetObj;
// Pkgs.to_json(RetObj);
// RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
// return ReturnObject(RetObj);
// }
// NotFound();
// }
void RESTAPI_device_commandHandler::Ping(
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
@@ -691,9 +764,31 @@ namespace OpenWifi {
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
// retrieve capabilities and encode/compress parameters, if required
Poco::JSON::Object ConfigParams = Params;
GWObjects::Capabilities Caps;
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
Poco::JSON::Object CapsJson;
Caps.to_json(CapsJson);
auto DeviceCaps = CapsJson.getObject(uCentralProtocol::CAPABILITIES);
if (DeviceCaps->has("compress_cmd") && DeviceCaps->get("compress_cmd")) {
// compressed command capability present and it is set, compress parameters
Poco::JSON::Object CompressedParams;
std::string CompressedBase64Data;
std::uint64_t UncompressedDataLen = ParamStream.str().length();
if (Utils::CompressAndEncodeBase64(ParamStream.str(), CompressedBase64Data)) {
// set compressed, base 64 encoded data and length of uncompressed data
CompressedParams.set(uCentralProtocol::COMPRESS_64, CompressedBase64Data);
CompressedParams.set(uCentralProtocol::COMPRESS_SZ, UncompressedDataLen);
ConfigParams = CompressedParams;
}
}
}
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
Cmd, Params, *Request, *Response, timeout,
Cmd, ConfigParams, *Request, *Response, timeout,
nullptr, this, Logger_);
if(!Cmd.Executed) {
@@ -1548,4 +1643,105 @@ namespace OpenWifi {
Logger_);
}
// `fixedconfig` command is used set country propery on AP
// This handler uses `fixedconfig` command definitions
void RESTAPI_device_commandHandler::FixedConfig(
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
poco_debug(Logger_, fmt::format("FIXEDCONFIG({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC,
TransactionId_, Requester(), SerialNumber_));
// do not allow `fixedconfig` command for simulated devices
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
// setup and validate fixedconfig object
GWObjects::FixedConfig fixed_config;
if(!fixed_config.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
// setup command message
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::FIXEDCONFIG;
std::ostringstream os;
ParsedBody_->stringify(os);
Cmd.Details = os.str();
Cmd.RunAt = 0;
Cmd.ErrorCode = 0;
Cmd.WaitingForFile = 0;
// send fixedconfig command to device and return status
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::fixedconfig, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
void RESTAPI_device_commandHandler::CableDiagnostics(
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("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("CABLEDIAGNOSTICS({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::CableDiagnostics 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::CABLEDIAGNOSTICS;
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::cablediagnostics, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
// void RESTAPI_device_commandHandler::InstallPackage(
// const std::string &CMD_UUID, uint64_t CMD_RPC,
// [[maybe_unused]] std::chrono::milliseconds timeout,
// [[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
// poco_debug(Logger_, fmt::format("INSTALLPACKAGE({},{}): TID={} user={} serial={}", CMD_UUID,
// CMD_RPC, TransactionId_, Requester(), SerialNumber_));
// if(IsDeviceSimulated(SerialNumber_)) {
// CallCanceled("INSTALLPACKAGE", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
// return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
// }
// GWObjects::PackageList Pkgs;
// if (StorageService()->GetDeviceInstalledPackages(SerialNumber_, Pkgs)) {
// Poco::JSON::Object RetObj;
// Pkgs.to_json(RetObj);
// RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
// return ReturnObject(RetObj);
// }
// NotFound();
// }
} // namespace OpenWifi

View File

@@ -33,6 +33,8 @@ namespace OpenWifi {
void GetStatus();
void GetChecks();
void DeleteChecks();
void GetPackages();
void DeletePackages();
bool IsDeviceSimulated(std::string &Serial);
@@ -70,6 +72,12 @@ namespace OpenWifi {
const GWObjects::DeviceRestrictions &R);
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void FixedConfig(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void PackageInstall(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

@@ -22,9 +22,15 @@ namespace OpenWifi {
std::string FileType;
std::string FileContent;
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType) || FileContent.empty()) {
int WaitingForFile = 0;
if (!StorageService()->GetAttachedFileContent(UUID, SerialNumber, FileContent, FileType, WaitingForFile) && !WaitingForFile) {
return NotFound();
}
else if (WaitingForFile) {
// waiting for file to be uploaded, return Accepted
return Accepted();
}
if (FileType == "pcap") {
SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
}

View File

@@ -0,0 +1,14 @@
//
// Created by Euphokumiko on 2025-05-22.
// Accton Corp.
//
#include "RESTAPI_packages_handler.h"
#include "StorageService.h"
#include "framework/ow_constants.h"
namespace OpenWifi {
void RESTAPI_packages_handler::DoGet() {
}
} // namespace OpenWifi

View File

@@ -0,0 +1,25 @@
//
// Created by Euphokumiko on 2025-05-22.
//
#pragma once
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_packages_handler : public RESTAPIHandler {
public:
RESTAPI_packages_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/packages"}; }
void DoGet() final;
void DoDelete() final{};
void DoPost() final{};
void DoPut() final{};
};
} // namespace OpenWifi

View File

@@ -12,9 +12,9 @@
#include "Daemon.h"
#ifdef TIP_GATEWAY_SERVICE
#include "AP_WS_Server.h"
#include "StorageService.h"
#include "CapabilitiesCache.h"
#include "RADIUSSessionTracker.h"
#include "StorageService.h"
#endif
#include "RESTAPI_GWobjects.h"
@@ -31,7 +31,8 @@ namespace OpenWifi::GWObjects {
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, "blackListed",
StorageService()->IsBlackListed(Utils::MACToInt(SerialNumber)));
#endif
field_to_json(Obj, "macAddress", MACAddress);
field_to_json(Obj, "manufacturer", Manufacturer);
@@ -70,12 +71,12 @@ 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);
auto Res = GS()->GetState(SerialNumber);
if (Res.has_value()) {
Res.value().to_json(SerialNumber, Obj);
#else
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber,Obj);
if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(SerialNumber, Obj);
#endif
} else {
field_to_json(Obj, "ipAddress", "");
@@ -172,17 +173,16 @@ 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;
}
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 DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType);
@@ -275,7 +275,8 @@ namespace OpenWifi::GWObjects {
return false;
}
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) {
void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber,
Poco::JSON::Object &Obj) {
field_to_json(Obj, "ipAddress", Address);
field_to_json(Obj, "txBytes", TX);
field_to_json(Obj, "rxBytes", RX);
@@ -299,12 +300,12 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
field_to_json(Obj, "connectReason", connectReason);
field_to_json(Obj, "uptime", uptime);
field_to_json(Obj, "compatible", Compatible);
field_to_json(Obj, "compatible", Compatible);
#ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
#endif
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions);
field_to_json(Obj, "hasGPS", hasGPS);
field_to_json(Obj, "sanity", sanity);
field_to_json(Obj, "memoryUsed", memoryUsed);
@@ -334,44 +335,44 @@ 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;
}
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);
@@ -799,4 +800,66 @@ namespace OpenWifi::GWObjects {
return false;
}
bool FixedConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "country", country);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool CableDiagnostics::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;
}
bool PackageInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "version", version);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void PackageInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "version", version);
}
bool PackagesOnDevice::from_json(const Poco::JSON::Array::Ptr &Obj) {
try {
std::ostringstream oss;
Poco::JSON::Stringifier::stringify(Obj, oss);
packageStringArray = oss.str();
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void PackagesOnDevice::to_json(Poco::JSON::Object &Obj) const {
Obj.set("serialNumber", serialNumber);
Poco::JSON::Array packageJsonArray;
for (const auto &pkg : packageArray) {
Poco::JSON::Object pkgObj;
pkg.to_json(pkgObj);
packageJsonArray.add(pkgObj);
}
Obj.set("packageArray", packageJsonArray);
Obj.set("FirstUpdate", Poco::UInt64(FirstUpdate));
Obj.set("LastUpdate", Poco::UInt64(LastUpdate));
}
} // namespace OpenWifi::GWObjects

View File

@@ -532,6 +532,49 @@ namespace OpenWifi::GWObjects {
std::uint64_t when;
std::vector<PowerCyclePort> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct FixedConfig {
std::string serialNumber;
std::string country;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct CableDiagnostics {
std::string serialNumber;
std::uint64_t when;
std::vector<std::string> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PackageInfo {
std::string name;
std::string version;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackagesOnDevice {
std::string serialNumber;
std::vector<PackageInfo> packageArray;
uint64_t FirstUpdate = 0;
uint64_t LastUpdate = 0;
std::string packageStringArray;
bool from_json(const Poco::JSON::Array::Ptr &Obj);
void to_json(Poco::JSON::Object &Obj) const;
};
struct PackageInstall {
std::string serialNumber;
std::uint64_t when;
std::string pkgURL;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct PackageRemove {
std::string serialNumber;
std::uint64_t when;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} // namespace OpenWifi::GWObjects

View File

@@ -243,7 +243,7 @@ namespace OpenWifi {
const std::string &Type);
bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
std::string &FileContent, std::string &Type);
std::string &FileContent, std::string &Type, int& WaitingForFile);
bool RemoveAttachedFile(std::string &UUID);
bool SetCommandResult(std::string &UUID, std::string &Result);
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
@@ -282,6 +282,11 @@ namespace OpenWifi {
bool SetDeviceLastRecordedContact(std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool SetDeviceLastRecordedContact(Poco::Data::Session & Session, std::string & SerialNumber, std::uint64_t lastRecordedContact);
bool GetDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool CreateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool UpdateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs);
bool DeleteDeviceInstalledPackages(std::string &SerialNumber);
int Create_Tables();
int Create_Statistics();
int Create_Devices();
@@ -293,6 +298,7 @@ namespace OpenWifi {
int Create_BlackList();
int Create_FileUploads();
int Create_DefaultFirmwares();
int Create_Packages();
bool AnalyzeCommands(Types::CountedMap &R);
bool AnalyzeDevices(GWObjects::Dashboard &D);

View File

@@ -376,18 +376,21 @@ static std::string DefaultAPSchema = R"foo(
"properties": {
"port-mirror": {
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
"type": "object",
"properties": {
"monitor-ports": {
"description": "The list of ports that we want to mirror.",
"type": "array",
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"monitor-ports": {
"description": "The list of ports that we want to mirror.",
"type": "array",
"items": {
"type": "string"
}
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string"
}
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string"
}
}
},
@@ -2411,11 +2414,18 @@ static std::string DefaultAPSchema = R"foo(
"$ref": "#/$defs/interface.ssid.encryption"
},
"multi-psk": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
{
"type": "boolean"
}
]
},
"rrm": {
"$ref": "#/$defs/interface.ssid.rrm"
},
@@ -4645,16 +4655,22 @@ static std::string DefaultSWITCHSchema = R"foo(
"type": "object",
"properties": {
"port-mirror": {
"type": "object",
"properties": {
"monitor-ports": {
"type": "array",
"items": {
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
"type": "array",
"items": {
"type": "object",
"properties": {
"monitor-ports": {
"description": "The list of ports that we want to mirror.",
"type": "array",
"items": {
"type": "string"
}
},
"analysis-port": {
"description": "The port that mirror'ed packets should be sent to.",
"type": "string"
}
},
"analysis-port": {
"type": "string"
}
}
},
@@ -6603,10 +6619,17 @@ static std::string DefaultSWITCHSchema = R"foo(
"$ref": "#/$defs/interface.ssid.encryption"
},
"multi-psk": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
{
"type": "boolean"
}
]
},
"rrm": {
"$ref": "#/$defs/interface.ssid.rrm"

View File

@@ -118,6 +118,10 @@ namespace OpenWifi {
Producer.poll((std::chrono::milliseconds) 0);
}
}
if (Queue_.size() == 0) {
// message queue is empty, flush all previously sent messages
Producer.flush();
}
} catch (const cppkafka::HandleException &E) {
poco_warning(Logger_,
fmt::format("Caught a Kafka exception (producer): {}", E.what()));
@@ -126,10 +130,6 @@ 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();

View File

@@ -431,6 +431,11 @@ namespace OpenWifi {
}
}
inline void Accepted() {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_ACCEPTED);
Response->send();
}
inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
SetCommonHeaders();
@@ -552,8 +557,8 @@ namespace OpenWifi {
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
inline void ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse();
inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
PrepareResponse(Status);
if (Request != nullptr) {
// can we compress ???
auto AcceptedEncoding = Request->find("Accept-Encoding");

View File

@@ -68,6 +68,16 @@ namespace OpenWifi {
Context->addCertificateAuthority(Issuing);
}
if (!client_cas_.empty()) {
// add certificates specified in clientcas
std::vector<Poco::Crypto::X509Certificate> Certs =
Poco::Net::X509Certificate::readPEM(client_cas_);
for (const auto &cert : Certs) {
Context->addChainCertificate(cert);
Context->addCertificateAuthority(cert);
}
}
Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
Context->usePrivateKey(Key);

View File

@@ -45,6 +45,7 @@ namespace OpenWifi {
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
[[nodiscard]] inline auto RootCA() const { return root_ca_; };
[[nodiscard]] inline auto ClientCas() const { return client_cas_; };
[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
[[nodiscard]] inline auto Name() const { return name_; };

View File

@@ -550,6 +550,8 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *DEBUG = "debug";
static const char *SCRIPT = "script";
static const char *TIMEOUT = "timeout";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *NEWPASSWORD = "newPassword";
static const char *USERS = "users";
@@ -580,6 +582,9 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *INTERVAL = "interval";
static const char *UI = "UI";
static const char *BANDWIDTH = "bandwidth";
static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
} // namespace OpenWifi::RESTAPI::Protocol
namespace OpenWifi::uCentralProtocol {
@@ -608,6 +613,7 @@ namespace OpenWifi::uCentralProtocol {
static const char *CFGPENDING = "cfgpending";
static const char *RECOVERY = "recovery";
static const char *COMPRESS_64 = "compress_64";
static const char *COMPRESS_SZ = "compress_sz";
static const char *CAPABILITIES = "capabilities";
static const char *REQUEST_UUID = "request_uuid";
static const char *SANITY = "sanity";
@@ -664,6 +670,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *SIGNATURE = "signature";
static const char *INFO = "info";
static const char *DATE = "date";
static const char *PACKAGE = "package";
static const char *PACKAGES = "packages";
static const char *CATEGORY = "category";
static const char *SERIALNUMBER = "serialNumber";
static const char *COMPATIBLE = "compatible";
@@ -692,6 +701,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *RRM = "rrm";
static const char *ACTIONS = "actions";
static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
} // namespace OpenWifi::uCentralProtocol
namespace OpenWifi::uCentralProtocol::Events {
@@ -726,7 +738,8 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_EVENT,
ET_WIFISCAN,
ET_ALARM,
ET_REBOOTLOG
ET_REBOOTLOG,
ET_PACKAGE
};
inline EVENT_MSG EventFromString(const std::string &Method) {
@@ -760,6 +773,8 @@ namespace OpenWifi::uCentralProtocol::Events {
return ET_ALARM;
else if (strcmp(REBOOTLOG, Method.c_str()) == 0)
return ET_REBOOTLOG;
else if (strcmp(PACKAGE, Method.c_str()) == 0)
return ET_PACKAGE;
return ET_UNKNOWN;
};
} // namespace OpenWifi::uCentralProtocol::Events
@@ -788,6 +803,9 @@ namespace OpenWifi::APCommands {
certupdate,
transfer,
powercycle,
fixedconfig,
cablediagnostics,
package,
unknown
};
@@ -802,7 +820,9 @@ 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, RESTAPI::Protocol::POWERCYCLE,
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS,
RESTAPI::Protocol::PACKAGE
};
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }

View File

@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
return false;
}
//
// Compress given data using utility function and encode it in base64 format.
//
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedBase64Data) {
unsigned long CompressedDataSize = UnCompressedData.size();
std::vector<Bytef> CompressedData(CompressedDataSize);
auto status = compress(&CompressedData[0], &CompressedDataSize,
(Bytef*) UnCompressedData.c_str(), UnCompressedData.size());
if (status == Z_OK) {
CompressedBase64Data = OpenWifi::Utils::base64encode(&CompressedData[0], CompressedDataSize);
}
else {
// failed to compress data
return false;
}
return true;
}
bool IsAlphaNumeric(const std::string &s) {
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
}

View File

@@ -151,6 +151,8 @@ namespace OpenWifi::Utils {
bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData, uint64_t compress_sz);
bool CompressAndEncodeBase64(const std::string& UnCompressedData, std::string& CompressedData);
inline bool match(const char* first, const char* second)
{
// If we reach at the end of both strings, we are done

View File

@@ -644,21 +644,7 @@ namespace OpenWifi {
uint64_t Size = FileContent.str().size();
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Statement(Sess);
std::string StatementStr;
// Get the existing command
StatementStr =
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
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;
@@ -680,7 +666,20 @@ namespace OpenWifi {
} else {
poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
}
// update CommandList here to ensure that file us uploaded
Sess.begin();
Poco::Data::Statement Statement(Sess);
std::string StatementStr;
StatementStr =
"UPDATE CommandList SET WaitingForFile=?, AttachDate=?, AttachSize=? WHERE UUID=?";
Statement << ConvertParams(StatementStr), Poco::Data::Keywords::use(WaitForFile),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Size),
Poco::Data::Keywords::use(UUID);
Statement.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
Logger().log(E);
@@ -689,7 +688,7 @@ namespace OpenWifi {
}
bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
std::string &FileContent, std::string &Type) {
std::string &FileContent, std::string &Type, int &WaitingForFile) {
try {
Poco::Data::BLOB L;
/*
@@ -702,10 +701,10 @@ namespace OpenWifi {
Poco::Data::Statement Select1(Sess);
std::string TmpSerialNumber;
std::string st1{"SELECT SerialNumber, Command FROM CommandList WHERE UUID=?"};
std::string st1{"SELECT SerialNumber, Command , WaitingForFile FROM CommandList WHERE UUID=?"};
std::string Command;
Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
Poco::Data::Keywords::into(Command), Poco::Data::Keywords::use(UUID);
Poco::Data::Keywords::into(Command), Poco::Data::Keywords::into(WaitingForFile), Poco::Data::Keywords::use(UUID);
Select1.execute();
if (TmpSerialNumber != SerialNumber) {
@@ -825,4 +824,4 @@ namespace OpenWifi {
return false;
}
} // namespace OpenWifi
} // namespace OpenWifi

View File

@@ -0,0 +1,124 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Euphokumiko on 2025-05-20.
// Accton Corp.
//
#include "CentralConfig.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "StorageService.h"
#include "framework/utils.h"
#include "fmt/format.h"
namespace OpenWifi {
const static std::string DB_PackageSelectField{"SerialNumber, Packages, FirstUpdate, LastUpdate"};
// serial pkgs f_update l_update
typedef Poco::Tuple<std::string, std::string, uint64_t, uint64_t> PackageTuple;
bool Storage::CreateDeviceInstalledPackages(std::string &SerialNumber,
GWObjects::PackagesOnDevice &Pkgs) {
try {
Poco::Data::Session Sess(Pool_->get());
Poco::Data::Statement UpSert(Sess);
uint64_t Now = Utils::Now();
std::string St{
"INSERT INTO Packages (SerialNumber, Packages, FirstUpdate, LastUpdate) "
"VALUES (?,?,?,?) "
"ON CONFLICT (SerialNumber) DO "
"UPDATE SET Packages = ?, LastUpdate = ?"};
UpSert << ConvertParams(St), Poco::Data::Keywords::use(SerialNumber),
Poco::Data::Keywords::use(Pkgs.packageStringArray),
Poco::Data::Keywords::use(Now), Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(Pkgs.packageStringArray),
Poco::Data::Keywords::use(Now);
UpSert.execute();
Sess.commit();
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));
}
return false;
}
bool Storage::UpdateDeviceInstalledPackages(std::string &SerialNumber, GWObjects::PackagesOnDevice &Pkgs) {
return CreateDeviceInstalledPackages(SerialNumber, Pkgs);
}
bool Storage::GetDeviceInstalledPackages(std::string &SerialNumber,
GWObjects::PackagesOnDevice &DevicePackages) {
try {
Poco::Data::Session Sess(Pool_->get());
Poco::Data::Statement Select(Sess);
PackageTuple packageTuple;
std::string TmpSerialNumber;
std::string packageStringArray;
std::string St{"SELECT " + DB_PackageSelectField +
" FROM Packages WHERE SerialNumber=?"};
Select << ConvertParams(St), Poco::Data::Keywords::into(TmpSerialNumber),
Poco::Data::Keywords::into(packageStringArray),
Poco::Data::Keywords::into(DevicePackages.FirstUpdate),
Poco::Data::Keywords::into(DevicePackages.LastUpdate),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
if (!TmpSerialNumber.empty()) {
Poco::JSON::Parser parser;
Poco::Dynamic::Var result = parser.parse(packageStringArray);
Poco::JSON::Array::Ptr jsonArray = result.extract<Poco::JSON::Array::Ptr>();
DevicePackages.serialNumber = TmpSerialNumber;
DevicePackages.packageArray.clear();
for (const auto &item : *jsonArray) {
Poco::JSON::Object::Ptr obj = item.extract<Poco::JSON::Object::Ptr>();
GWObjects::PackageInfo pkg;
pkg.name = obj->getValue<std::string>("name");
pkg.version = obj->getValue<std::string>("version");
DevicePackages.packageArray.emplace_back(pkg);
}
} else {
DevicePackages.packageArray.clear();
}
return true;
} catch (const Poco::Exception &E) {
poco_warning(Logger(), fmt::format("{}: Failed with: {}", std::string(__func__),
E.displayText()));
}
return false;
}
bool Storage::DeleteDeviceInstalledPackages(std::string &SerialNumber) {
try {
Poco::Data::Session Sess = Pool_->get();
Sess.begin();
Poco::Data::Statement Delete(Sess);
std::string St{"DELETE FROM Packages 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__),
E.displayText()));
}
return false;
}
} // namespace OpenWifi

View File

@@ -22,6 +22,7 @@ namespace OpenWifi {
Create_BlackList();
Create_FileUploads();
Create_DefaultFirmwares();
Create_Packages();
return 0;
}
@@ -49,8 +50,7 @@ namespace OpenWifi {
"Data TEXT, "
"Recorded BIGINT, "
"INDEX StatSerial0 (SerialNumber)), ",
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))",
Poco::Data::Keywords::now;
"INDEX StatSerial (SerialNumber ASC, Recorded ASC))", Poco::Data::Keywords::now;
}
return 0;
} catch (const Poco::Exception &E) {
@@ -154,8 +154,7 @@ namespace OpenWifi {
"alter table devices add column lastRecordedContact bigint",
"alter table devices add column simulated boolean",
"alter table devices add column certificateExpiryDate bigint",
"alter table devices add column connectReason TEXT"
};
"alter table devices add column connectReason TEXT"};
for (const auto &i : Script) {
try {
@@ -279,9 +278,7 @@ namespace OpenWifi {
Poco::Data::Keywords::now;
}
std::vector<std::string> Script{
"alter table DefaultConfigs add column Platform text"
};
std::vector<std::string> Script{"alter table DefaultConfigs add column Platform text"};
for (const auto &i : Script) {
try {
@@ -454,4 +451,23 @@ namespace OpenWifi {
return -1;
}
int Storage::Create_Packages() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS Packages ("
"SerialNumber VARCHAR(30) PRIMARY KEY, "
"Packages JSON, "
"FirstUpdate BIGINT, "
"LastUpdate BIGINT"
")",
Poco::Data::Keywords::now;
return 0;
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return -1;
}
} // namespace OpenWifi

19
verbosity.json Normal file
View File

@@ -0,0 +1,19 @@
[
{
"serialNumber": "xxxxx",
"packages": "akiho - 98-10-16-71a3b533e-1 \n erichi - 98-12-06-98e79a27f-1 \n ucrun - 2022-02-19-05be6abeb-1 \n vxlan - 7 ..."
},
{
"serialNumber": "xxxxx",
"packages": [
{
"packageName": "akiho",
"version": "98-10-16-71a3b533e-1"
},
{
"packageName": "erichi",
"version": "98-12-06-98e79a27f-1"
}
]
}
]