Compare commits

...

34 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
34 changed files with 766 additions and 123 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

@@ -324,6 +324,20 @@ should respond with message indicating failure or success.
}
```
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",

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

@@ -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

@@ -54,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;
@@ -155,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);
}

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);
}
@@ -170,7 +194,7 @@ namespace OpenWifi {
{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() {
@@ -408,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) {
@@ -694,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) {
@@ -1629,4 +1721,27 @@ namespace OpenWifi {
*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);
@@ -74,6 +76,8 @@ namespace OpenWifi {
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);
@@ -819,4 +820,46 @@ namespace OpenWifi::GWObjects {
}
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

@@ -545,6 +545,36 @@ namespace OpenWifi::GWObjects {
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"
}
}
},
@@ -4652,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"
}
}
},

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();

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";
@@ -611,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";
@@ -667,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";
@@ -732,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) {
@@ -766,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
@@ -796,6 +805,7 @@ namespace OpenWifi::APCommands {
powercycle,
fixedconfig,
cablediagnostics,
package,
unknown
};
@@ -811,7 +821,8 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS
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"
}
]
}
]