mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2025-11-02 11:47:47 +00:00
Compare commits
78 Commits
release/v3
...
release/v4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91fe27e973 | ||
|
|
f8d714d04b | ||
|
|
a5d1eebe6d | ||
|
|
ee14f064c8 | ||
|
|
dbf52c1f23 | ||
|
|
9dc6a6bf97 | ||
|
|
1c0556f8bf | ||
|
|
d298139525 | ||
|
|
a37c961f5b | ||
|
|
75bcbd748c | ||
|
|
b6eba2a96d | ||
|
|
17082803d4 | ||
|
|
26b9a96506 | ||
|
|
5ce8dae9ec | ||
|
|
7da135c1e5 | ||
|
|
50ee4ba5cb | ||
|
|
3a8109d7ad | ||
|
|
56232966ec | ||
|
|
1ecf98d712 | ||
|
|
f5b60ced61 | ||
|
|
e4d141bb8e | ||
|
|
25b4288050 | ||
|
|
82430c2d5d | ||
|
|
7b68ec0536 | ||
|
|
839f4fec44 | ||
|
|
c4178209bb | ||
|
|
79ab67db50 | ||
|
|
00bc77feea | ||
|
|
4f00d77d2b | ||
|
|
c679d4ac40 | ||
|
|
4a150a9fcb | ||
|
|
83eb603f0a | ||
|
|
38bc0f0d69 | ||
|
|
e7362c2020 | ||
|
|
9c9987e190 | ||
|
|
4ac7b6ba0b | ||
|
|
f9ee19af91 | ||
|
|
cd2ab8660f | ||
|
|
b9f00f6603 | ||
|
|
596cfd49e1 | ||
|
|
b3deba5606 | ||
|
|
a97d49a06b | ||
|
|
b1be0604d6 | ||
|
|
b29f7f7dc4 | ||
|
|
132b31b06b | ||
|
|
3114ff8a32 | ||
|
|
9c5aeda5dd | ||
|
|
783ec99930 | ||
|
|
0c661b8b93 | ||
|
|
9d7f4da504 | ||
|
|
a3b6e7c315 | ||
|
|
451680cd5a | ||
|
|
7be48c3cfc | ||
|
|
b59d1cb4da | ||
|
|
c3a709c2b9 | ||
|
|
5d89107827 | ||
|
|
3c15c6dc4f | ||
|
|
7b33a692b2 | ||
|
|
b118dcbcec | ||
|
|
02a0eef44a | ||
|
|
c7ed7fb264 | ||
|
|
1d88bb50d9 | ||
|
|
3b613ea159 | ||
|
|
d00d409fca | ||
|
|
8382818e2d | ||
|
|
ed4670d239 | ||
|
|
cca3619e91 | ||
|
|
9a834c29a2 | ||
|
|
2b06a0bcf6 | ||
|
|
03dabed878 | ||
|
|
e133a9c3ab | ||
|
|
23b33fab20 | ||
|
|
909b4c889e | ||
|
|
a04c5336d2 | ||
|
|
4df1bf985d | ||
|
|
26a89f3eb5 | ||
|
|
b055711993 | ||
|
|
fcdb7423ef |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -21,7 +21,7 @@ defaults:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
|
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||||
DOCKER_REGISTRY_USERNAME: ucentral
|
DOCKER_REGISTRY_USERNAME: ucentral
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -11,7 +11,7 @@ defaults:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
helm-package:
|
helm-package:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
|
||||||
HELM_REPO_USERNAME: ucentral
|
HELM_REPO_USERNAME: ucentral
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(owgw VERSION 3.0.2)
|
project(owgw VERSION 4.0.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
ARG DEBIAN_VERSION=11.5-slim
|
ARG DEBIAN_VERSION=11.5-slim
|
||||||
ARG POCO_VERSION=poco-tip-v2
|
ARG POCO_VERSION=poco-tip-v2
|
||||||
ARG CPPKAFKA_VERSION=tip-v1
|
ARG CPPKAFKA_VERSION=tip-v1
|
||||||
ARG VALIJASON_VERSION=tip-v1
|
ARG VALIJASON_VERSION=tip-v1.0.2
|
||||||
ARG APP_NAME=owgw
|
ARG APP_NAME=owgw
|
||||||
ARG APP_HOME_DIR=/openwifi
|
ARG APP_HOME_DIR=/openwifi
|
||||||
|
|
||||||
|
|||||||
46
PROTOCOL.md
46
PROTOCOL.md
@@ -306,8 +306,54 @@ The device should answer:
|
|||||||
},
|
},
|
||||||
"id" : <same number>
|
"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 Answer
|
||||||
The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
|
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
|
appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ fullnameOverride: ""
|
|||||||
images:
|
images:
|
||||||
owgw:
|
owgw:
|
||||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||||
tag: master
|
tag: v4.0.0
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
# regcred:
|
# regcred:
|
||||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ info:
|
|||||||
url: https://www.ucentral.info/support
|
url: https://www.ucentral.info/support
|
||||||
|
|
||||||
servers:
|
servers:
|
||||||
- url: 'https://localhost:16001/api/v1'
|
- url: 'https://localhost:16002/api/v1'
|
||||||
|
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
@@ -1702,6 +1702,11 @@ paths:
|
|||||||
- ap
|
- ap
|
||||||
- switch
|
- switch
|
||||||
required: false
|
required: false
|
||||||
|
- in: query
|
||||||
|
description: only devices which are not provisioned
|
||||||
|
name: includeProvisioned
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: List devices
|
description: List devices
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace OpenWifi {
|
|||||||
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
|
State_.Address = Utils::FormatIPv6(WS_->peerAddress().toString());
|
||||||
CId_ = SerialNumber_ + "@" + CId_;
|
CId_ = SerialNumber_ + "@" + CId_;
|
||||||
|
|
||||||
auto &Platform = Caps.Platform();
|
auto Platform = Poco::toLower(Caps.Platform());
|
||||||
|
|
||||||
if(ParamsObj->has("reason")) {
|
if(ParamsObj->has("reason")) {
|
||||||
State_.connectReason = ParamsObj->get("reason").toString();
|
State_.connectReason = ParamsObj->get("reason").toString();
|
||||||
|
|||||||
@@ -71,14 +71,18 @@ namespace OpenWifi {
|
|||||||
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
|
bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
|
||||||
const Poco::Crypto::X509Certificate &Certificate) {
|
const Poco::Crypto::X509Certificate &Certificate) {
|
||||||
if (IsCertOk()) {
|
if (IsCertOk()) {
|
||||||
if (!Certificate.issuedBy(*IssuerCert_)) {
|
// validate certificate agains trusted chain
|
||||||
poco_warning(
|
for (const auto &cert : ClientCasCerts_) {
|
||||||
Logger(),
|
if (Certificate.issuedBy(cert)) {
|
||||||
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
|
return true;
|
||||||
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
poco_warning(
|
||||||
|
Logger(),
|
||||||
|
fmt::format(
|
||||||
|
"CERTIFICATE({}): issuer mismatch. Certificate not issued by any trusted CA",
|
||||||
|
ConnectionId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -133,6 +137,13 @@ namespace OpenWifi {
|
|||||||
Context->addChainCertificate(Issuing);
|
Context->addChainCertificate(Issuing);
|
||||||
Context->addCertificateAuthority(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());
|
Poco::Crypto::RSAKey Key("", Svr.KeyFile(), Svr.KeyFilePassword());
|
||||||
Context->usePrivateKey(Key);
|
Context->usePrivateKey(Key);
|
||||||
|
|
||||||
@@ -207,6 +218,28 @@ namespace OpenWifi {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AP_WS_Server::Disconnect(uint64_t SerialNumber) {
|
||||||
|
std::shared_ptr<AP_WS_Connection> Connection;
|
||||||
|
{
|
||||||
|
auto hashIndex = MACHash::Hash(SerialNumber);
|
||||||
|
std::lock_guard DeviceLock(SerialNumbersMutex_[hashIndex]);
|
||||||
|
auto DeviceHint = SerialNumbers_[hashIndex].find(SerialNumber);
|
||||||
|
if (DeviceHint == SerialNumbers_[hashIndex].end() || DeviceHint->second == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Connection = DeviceHint->second;
|
||||||
|
SerialNumbers_[hashIndex].erase(DeviceHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto H = SessionHash::Hash(Connection->State_.sessionId);
|
||||||
|
std::lock_guard SessionLock(SessionMutex_[H]);
|
||||||
|
Sessions_[H].erase(Connection->State_.sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void AP_WS_Server::CleanupSessions() {
|
void AP_WS_Server::CleanupSessions() {
|
||||||
|
|
||||||
while(Running_) {
|
while(Running_) {
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
|
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
|
||||||
bool Connected(uint64_t SerialNumber) const;
|
bool Connected(uint64_t SerialNumber) const;
|
||||||
|
bool Disconnect(uint64_t SerialNumber);
|
||||||
bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
|
bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
|
||||||
bool SendRadiusAuthenticationData(const std::string &SerialNumber,
|
bool SendRadiusAuthenticationData(const std::string &SerialNumber,
|
||||||
const unsigned char *buffer, std::size_t size);
|
const unsigned char *buffer, std::size_t size);
|
||||||
@@ -222,6 +223,7 @@ namespace OpenWifi {
|
|||||||
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
|
mutable std::array<std::mutex,MACHashMax> SerialNumbersMutex_;
|
||||||
|
|
||||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||||
|
std::vector<Poco::Crypto::X509Certificate> ClientCasCerts_;
|
||||||
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
|
||||||
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
|
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 4, 256};
|
||||||
Poco::Net::SocketReactor Reactor_;
|
Poco::Net::SocketReactor Reactor_;
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ namespace OpenWifi {
|
|||||||
i >> cache;
|
i >> cache;
|
||||||
|
|
||||||
for (const auto &[Type, Platform] : cache.items()) {
|
for (const auto &[Type, Platform] : cache.items()) {
|
||||||
Platforms_[Type] = Poco::toLower(to_string(Platform));
|
Platforms_[Type] = Poco::toLower(Platform.get<std::string>());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,11 @@ namespace OpenWifi::Config {
|
|||||||
Model_ = Caps->get("model").toString();
|
Model_ = Caps->get("model").toString();
|
||||||
|
|
||||||
if (Caps->has("platform"))
|
if (Caps->has("platform"))
|
||||||
Platform_ = Caps->get("platform").toString();
|
Platform_ = Poco::toLower(Caps->get("platform").toString());
|
||||||
|
|
||||||
|
if(Compatible_.empty()) {
|
||||||
|
Compatible_ = Model_;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostringstream OS;
|
std::ostringstream OS;
|
||||||
Caps->stringify(OS);
|
Caps->stringify(OS);
|
||||||
|
|||||||
@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
|
|||||||
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
|
||||||
Poco::JSON::Object RetObj;
|
Poco::JSON::Object RetObj;
|
||||||
Cmd.to_json(RetObj);
|
Cmd.to_json(RetObj);
|
||||||
if (Handler != nullptr)
|
if (Handler == nullptr) {
|
||||||
return Handler->ReturnObject(RetObj);
|
// nothing to process/return
|
||||||
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)
|
if (Handler != nullptr)
|
||||||
return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
|
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,
|
std::chrono::milliseconds WaitTimeInMs, Poco::JSON::Object *ObjectToReturn,
|
||||||
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
|
RESTAPIHandler *Handler, Poco::Logger &Logger, bool Deferred) {
|
||||||
|
|
||||||
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={}. ", Cmd.UUID,
|
Logger.information(fmt::format("{},{}: New {} command. User={} Serial={} Details={}. ", Cmd.UUID,
|
||||||
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber));
|
RPCID, Cmd.Command, Cmd.SubmittedBy, Cmd.SerialNumber, Cmd.Details));
|
||||||
Cmd.Submitted = Utils::Now();
|
Cmd.Submitted = Utils::Now();
|
||||||
Cmd.Executed = 0;
|
Cmd.Executed = 0;
|
||||||
|
|
||||||
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
|
|||||||
Cmd.AttachType = "";
|
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) {
|
if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
|
||||||
// we need to post a kafka event for this.
|
// we need to post a kafka event for this.
|
||||||
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
|
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
|
||||||
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
|
|||||||
DeviceConfigurationChangeKafkaEvent KEvent(
|
DeviceConfigurationChangeKafkaEvent KEvent(
|
||||||
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
|
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
|
||||||
Config);
|
Config);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,10 @@ namespace OpenWifi {
|
|||||||
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
|
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
|
||||||
{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
|
{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
|
||||||
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 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},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void RESTAPI_device_commandHandler::DoPost() {
|
void RESTAPI_device_commandHandler::DoPost() {
|
||||||
@@ -691,9 +694,31 @@ namespace OpenWifi {
|
|||||||
Params.stringify(ParamStream);
|
Params.stringify(ParamStream);
|
||||||
Cmd.Details = ParamStream.str();
|
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);
|
// AP_WS_Server()->SetPendingUUID(SerialNumber_, NewUUID);
|
||||||
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
|
RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::configure, true,
|
||||||
Cmd, Params, *Request, *Response, timeout,
|
Cmd, ConfigParams, *Request, *Response, timeout,
|
||||||
nullptr, this, Logger_);
|
nullptr, this, Logger_);
|
||||||
|
|
||||||
if(!Cmd.Executed) {
|
if(!Cmd.Executed) {
|
||||||
@@ -1548,4 +1573,82 @@ namespace OpenWifi {
|
|||||||
Logger_);
|
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_);
|
||||||
|
}
|
||||||
} // namespace OpenWifi
|
} // namespace OpenWifi
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ namespace OpenWifi {
|
|||||||
const GWObjects::DeviceRestrictions &R);
|
const GWObjects::DeviceRestrictions &R);
|
||||||
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
|
||||||
const GWObjects::DeviceRestrictions &R);
|
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);
|
||||||
|
|
||||||
static auto PathName() {
|
static auto PathName() {
|
||||||
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
|
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
#include "RESTAPI_device_helper.h"
|
#include "RESTAPI_device_helper.h"
|
||||||
|
|
||||||
|
#include "AP_WS_Server.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
void RESTAPI_device_handler::DoGet() {
|
void RESTAPI_device_handler::DoGet() {
|
||||||
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
|
||||||
@@ -80,6 +82,9 @@ namespace OpenWifi {
|
|||||||
return OK();
|
return OK();
|
||||||
|
|
||||||
} else if (StorageService()->DeleteDevice(SerialNumber)) {
|
} else if (StorageService()->DeleteDevice(SerialNumber)) {
|
||||||
|
if(AP_WS_Server()->Connected(Utils::SerialNumberToInt(SerialNumber))) {
|
||||||
|
AP_WS_Server()->Disconnect(Utils::SerialNumberToInt(SerialNumber));
|
||||||
|
}
|
||||||
return OK();
|
return OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ namespace OpenWifi {
|
|||||||
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
|
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
|
||||||
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
|
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
|
||||||
auto completeInfo = GetBoolParameter("completeInfo", false);
|
auto completeInfo = GetBoolParameter("completeInfo", false);
|
||||||
|
auto includeProvisioned = GetBoolParameter("includeProvisioned", true);
|
||||||
|
|
||||||
if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
|
if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
|
||||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||||
@@ -131,7 +132,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
} else if (serialOnly) {
|
} else if (serialOnly) {
|
||||||
std::vector<std::string> SerialNumbers;
|
std::vector<std::string> SerialNumbers;
|
||||||
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform);
|
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform, includeProvisioned);
|
||||||
Poco::JSON::Array Objects;
|
Poco::JSON::Array Objects;
|
||||||
for (const auto &i : SerialNumbers) {
|
for (const auto &i : SerialNumbers) {
|
||||||
Objects.add(i);
|
Objects.add(i);
|
||||||
@@ -149,7 +150,7 @@ namespace OpenWifi {
|
|||||||
RetObj.set("serialNumbers", Objects);
|
RetObj.set("serialNumbers", Objects);
|
||||||
} else {
|
} else {
|
||||||
std::vector<GWObjects::Device> Devices;
|
std::vector<GWObjects::Device> Devices;
|
||||||
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform);
|
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform, includeProvisioned);
|
||||||
Poco::JSON::Array Objects;
|
Poco::JSON::Array Objects;
|
||||||
for (const auto &i : Devices) {
|
for (const auto &i : Devices) {
|
||||||
Poco::JSON::Object Obj;
|
Poco::JSON::Object Obj;
|
||||||
|
|||||||
@@ -22,9 +22,15 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
std::string FileType;
|
std::string FileType;
|
||||||
std::string FileContent;
|
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();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
else if (WaitingForFile) {
|
||||||
|
// waiting for file to be uploaded, return Accepted
|
||||||
|
return Accepted();
|
||||||
|
}
|
||||||
|
|
||||||
if (FileType == "pcap") {
|
if (FileType == "pcap") {
|
||||||
SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
|
SendFileContent(FileContent, "application/vnd.tcpdump.pcap", UUID + ".pcap");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
void Device::to_json(Poco::JSON::Object &Obj) const {
|
void Device::to_json(Poco::JSON::Object &Obj) const {
|
||||||
field_to_json(Obj, "serialNumber", SerialNumber);
|
field_to_json(Obj, "serialNumber", SerialNumber);
|
||||||
#ifdef TIP_GATEWAY_SERVICE
|
#ifdef TIP_GATEWAY_SERVICE
|
||||||
field_to_json(Obj, "deviceType", CapabilitiesCache::instance()->GetPlatform(Compatible));
|
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
|
#endif
|
||||||
field_to_json(Obj, "macAddress", MACAddress);
|
field_to_json(Obj, "macAddress", MACAddress);
|
||||||
@@ -799,4 +799,24 @@ namespace OpenWifi::GWObjects {
|
|||||||
return false;
|
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;
|
||||||
|
}
|
||||||
} // namespace OpenWifi::GWObjects
|
} // namespace OpenWifi::GWObjects
|
||||||
|
|||||||
@@ -532,6 +532,19 @@ namespace OpenWifi::GWObjects {
|
|||||||
std::uint64_t when;
|
std::uint64_t when;
|
||||||
std::vector<PowerCyclePort> ports;
|
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);
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
} // namespace OpenWifi::GWObjects
|
} // namespace OpenWifi::GWObjects
|
||||||
|
|||||||
@@ -148,12 +148,14 @@ namespace OpenWifi {
|
|||||||
bool GetDevice(const std::string &SerialNumber, GWObjects::Device &);
|
bool GetDevice(const std::string &SerialNumber, GWObjects::Device &);
|
||||||
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
|
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
|
||||||
const std::string &orderBy = "",
|
const std::string &orderBy = "",
|
||||||
const std::string &platform = "");
|
const std::string &platform = "",
|
||||||
|
bool includeProvisioned = true);
|
||||||
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
|
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
|
||||||
// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
|
// std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
|
||||||
bool DeleteDevice(std::string &SerialNumber);
|
bool DeleteDevice(std::string &SerialNumber);
|
||||||
bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
|
bool DeleteDevices(std::string &SerialPattern, bool SimulatedOnly);
|
||||||
bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
|
bool DeleteDevices(std::uint64_t OlderContact, bool SimulatedOnly);
|
||||||
|
std::string GetPlatform(const std::string &SerialNumber);
|
||||||
|
|
||||||
bool UpdateDevice(GWObjects::Device &);
|
bool UpdateDevice(GWObjects::Device &);
|
||||||
bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
|
bool UpdateDevice(LockedDbSession &Session, GWObjects::Device &);
|
||||||
@@ -164,7 +166,8 @@ namespace OpenWifi {
|
|||||||
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||||
std::vector<std::string> &SerialNumbers,
|
std::vector<std::string> &SerialNumbers,
|
||||||
const std::string &orderBy = "",
|
const std::string &orderBy = "",
|
||||||
const std::string &platform = "");
|
const std::string &platform = "",
|
||||||
|
bool includeProvisioned = true);
|
||||||
bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
|
bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
|
||||||
bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
|
bool SetDevicePassword(LockedDbSession &Session, std::string &SerialNumber, std::string &Password);
|
||||||
bool UpdateSerialNumberCache();
|
bool UpdateSerialNumberCache();
|
||||||
@@ -240,7 +243,7 @@ namespace OpenWifi {
|
|||||||
const std::string &Type);
|
const std::string &Type);
|
||||||
bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
|
bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
|
||||||
bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
|
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 RemoveAttachedFile(std::string &UUID);
|
||||||
bool SetCommandResult(std::string &UUID, std::string &Result);
|
bool SetCommandResult(std::string &UUID, std::string &Result);
|
||||||
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
|
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ static const std::vector<std::string> GitJSONSchemaURLs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static std::string DefaultAPSchema = R"foo(
|
static std::string DefaultAPSchema = R"foo(
|
||||||
|
|
||||||
{
|
{
|
||||||
"$id": "https://openwrt.org/ucentral.schema.json",
|
"$id": "https://openwrt.org/ucentral.schema.json",
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
@@ -354,14 +353,6 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
10000
|
10000
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"duplex": {
|
|
||||||
"description": "The duplex mode that shall be forced.",
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"half",
|
|
||||||
"full"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"description": "This allows forcing the port to down state by default.",
|
"description": "This allows forcing the port to down state by default.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@@ -385,18 +376,21 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
"properties": {
|
"properties": {
|
||||||
"port-mirror": {
|
"port-mirror": {
|
||||||
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
|
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
|
||||||
"type": "object",
|
"type": "array",
|
||||||
"properties": {
|
"items": {
|
||||||
"monitor-ports": {
|
"type": "object",
|
||||||
"description": "The list of ports that we want to mirror.",
|
"properties": {
|
||||||
"type": "array",
|
"monitor-ports": {
|
||||||
"items": {
|
"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"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"analysis-port": {
|
|
||||||
"description": "The port that mirror'ed packets should be sent to.",
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -490,7 +484,59 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
"bss-color": {
|
"bss-color": {
|
||||||
"description": "This enables BSS Coloring on the PHY. setting it to 0 disables the feature 1-63 sets the color and 64 will make hostapd pick a random color.",
|
"description": "This enables BSS Coloring on the PHY. setting it to 0 disables the feature 1-63 sets the color and 64 will make hostapd pick a random color.",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"default": 64
|
"minimum": 0,
|
||||||
|
"maximum": 64,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"radio.he-6ghz": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"power-type": {
|
||||||
|
"description": "This config is to set the 6 GHz Access Point type",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"indoor-power-indoor",
|
||||||
|
"standard-power",
|
||||||
|
"very-low-power"
|
||||||
|
],
|
||||||
|
"default": "very-low-power"
|
||||||
|
},
|
||||||
|
"controller": {
|
||||||
|
"description": "The URL of the AFC controller that the AP shall connect to.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"ca-certificate": {
|
||||||
|
"description": "The CA of the server. This enables mTLS.",
|
||||||
|
"type": "string",
|
||||||
|
"format": "uc-base64"
|
||||||
|
},
|
||||||
|
"serial-number": {
|
||||||
|
"description": "The serial number that the AP shall send to the AFC controller.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"certificate-ids": {
|
||||||
|
"description": "The certificate IDs that the AP shall send to the AFC controller.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minimum-power": {
|
||||||
|
"description": "The minimum power that the AP shall request from to the AFC controller.",
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"frequency-ranges": {
|
||||||
|
"description": "The list of frequency ranges that the AP shall request from to the AFC controller.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"operating-classes": {
|
||||||
|
"description": "The list of frequency ranges that the AP shall request from to the AFC controller.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -635,6 +681,9 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
"he-settings": {
|
"he-settings": {
|
||||||
"$ref": "#/$defs/radio.he"
|
"$ref": "#/$defs/radio.he"
|
||||||
},
|
},
|
||||||
|
"he-6ghz-settings": {
|
||||||
|
"$ref": "#/$defs/radio.he-6ghz"
|
||||||
|
},
|
||||||
"hostapd-iface-raw": {
|
"hostapd-iface-raw": {
|
||||||
"description": "This array allows passing raw hostapd.conf lines.",
|
"description": "This array allows passing raw hostapd.conf lines.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -784,8 +833,19 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
},
|
},
|
||||||
"use-dns": {
|
"use-dns": {
|
||||||
"description": "The DNS server sent to clients as DHCP option 6.",
|
"description": "The DNS server sent to clients as DHCP option 6.",
|
||||||
"type": "string",
|
"anyOf": [
|
||||||
"format": "uc-ip"
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1313,8 +1373,7 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
"domain-identifier": {
|
"domain-identifier": {
|
||||||
"description": "Mobility Domain identifier (dot11FTMobilityDomainID, MDID).",
|
"description": "Mobility Domain identifier (dot11FTMobilityDomainID, MDID).",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"maxLength": 4,
|
"format": "uc-mobility",
|
||||||
"minLength": 4,
|
|
||||||
"examples": [
|
"examples": [
|
||||||
"abcd"
|
"abcd"
|
||||||
]
|
]
|
||||||
@@ -2355,11 +2414,18 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
"$ref": "#/$defs/interface.ssid.encryption"
|
"$ref": "#/$defs/interface.ssid.encryption"
|
||||||
},
|
},
|
||||||
"multi-psk": {
|
"multi-psk": {
|
||||||
"type": "array",
|
"anyOf": [
|
||||||
"items": {
|
{
|
||||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
"type": "array",
|
||||||
}
|
"items": {
|
||||||
},
|
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"rrm": {
|
"rrm": {
|
||||||
"$ref": "#/$defs/interface.ssid.rrm"
|
"$ref": "#/$defs/interface.ssid.rrm"
|
||||||
},
|
},
|
||||||
@@ -3701,6 +3767,42 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"service.fingerprint": {
|
||||||
|
"description": "This section can be used to configure device fingerprinting.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"mode": {
|
||||||
|
"description": "Enable this option if you would like to enable the MDNS server on the unit.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"polled",
|
||||||
|
"final",
|
||||||
|
"raw-data"
|
||||||
|
],
|
||||||
|
"default": "final"
|
||||||
|
},
|
||||||
|
"minimum-age": {
|
||||||
|
"description": "The minimum age a fingerprint must have before it is reported.",
|
||||||
|
"type": "number",
|
||||||
|
"default": 60
|
||||||
|
},
|
||||||
|
"maximum-age": {
|
||||||
|
"description": "The age at which fingerprints get flushed from the local state.",
|
||||||
|
"type": "number",
|
||||||
|
"default": 60
|
||||||
|
},
|
||||||
|
"periodicity": {
|
||||||
|
"description": "This value defines the period at which entries get reported.",
|
||||||
|
"type": "number",
|
||||||
|
"default": 600
|
||||||
|
},
|
||||||
|
"allow-wan": {
|
||||||
|
"description": "Allow fingerprinting devices found on the WAN port.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"description": "This section describes all of the services that may be present on the AP. Each service is then referenced via its name inside an interface, ssid, ...",
|
"description": "This section describes all of the services that may be present on the AP. Each service is then referenced via its name inside an interface, ssid, ...",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3770,6 +3872,9 @@ static std::string DefaultAPSchema = R"foo(
|
|||||||
},
|
},
|
||||||
"rrm": {
|
"rrm": {
|
||||||
"$ref": "#/$defs/service.rrm"
|
"$ref": "#/$defs/service.rrm"
|
||||||
|
},
|
||||||
|
"fingerprint": {
|
||||||
|
"$ref": "#/$defs/service.fingerprint"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4550,16 +4655,22 @@ static std::string DefaultSWITCHSchema = R"foo(
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"port-mirror": {
|
"port-mirror": {
|
||||||
"type": "object",
|
"description": "Enable mirror of traffic from multiple minotor ports to a single analysis port.",
|
||||||
"properties": {
|
"type": "array",
|
||||||
"monitor-ports": {
|
"items": {
|
||||||
"type": "array",
|
"type": "object",
|
||||||
"items": {
|
"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"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"analysis-port": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -6508,10 +6619,17 @@ static std::string DefaultSWITCHSchema = R"foo(
|
|||||||
"$ref": "#/$defs/interface.ssid.encryption"
|
"$ref": "#/$defs/interface.ssid.encryption"
|
||||||
},
|
},
|
||||||
"multi-psk": {
|
"multi-psk": {
|
||||||
"type": "array",
|
"anyOf": [
|
||||||
"items": {
|
{
|
||||||
"$ref": "#/$defs/interface.ssid.multi-psk"
|
"type": "array",
|
||||||
}
|
"items": {
|
||||||
|
"$ref": "#/$defs/interface.ssid.multi-psk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"rrm": {
|
"rrm": {
|
||||||
"$ref": "#/$defs/interface.ssid.rrm"
|
"$ref": "#/$defs/interface.ssid.rrm"
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace OpenWifi {
|
|||||||
void reinitialize(Poco::Util::Application &self) override;
|
void reinitialize(Poco::Util::Application &self) override;
|
||||||
|
|
||||||
inline static ConfigurationType GetType(const std::string &type) {
|
inline static ConfigurationType GetType(const std::string &type) {
|
||||||
std::string Type = Poco::toUpper(type);
|
std::string Type = Poco::toLower(type);
|
||||||
if (Type == Platforms::AP)
|
if (Type == Platforms::AP)
|
||||||
return ConfigurationType::AP;
|
return ConfigurationType::AP;
|
||||||
if (Type == Platforms::SWITCH)
|
if (Type == Platforms::SWITCH)
|
||||||
|
|||||||
@@ -107,6 +107,19 @@ namespace OpenWifi {
|
|||||||
NewMessage.partition(0);
|
NewMessage.partition(0);
|
||||||
NewMessage.payload(Msg->Payload());
|
NewMessage.payload(Msg->Payload());
|
||||||
Producer.produce(NewMessage);
|
Producer.produce(NewMessage);
|
||||||
|
if (Queue_.size() < 100) {
|
||||||
|
// use flush when internal queue is lightly loaded, i.e. flush after each
|
||||||
|
// message
|
||||||
|
Producer.flush();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// use poll when internal queue is loaded to allow messages to be sent in
|
||||||
|
// batches
|
||||||
|
Producer.poll((std::chrono::milliseconds) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Queue_.size() == 0) {
|
||||||
|
// message queue is empty, flush all previously sent messages
|
||||||
Producer.flush();
|
Producer.flush();
|
||||||
}
|
}
|
||||||
} catch (const cppkafka::HandleException &E) {
|
} catch (const cppkafka::HandleException &E) {
|
||||||
@@ -119,6 +132,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
Note = Queue_.waitDequeueNotification();
|
Note = Queue_.waitDequeueNotification();
|
||||||
}
|
}
|
||||||
|
Producer.flush();
|
||||||
poco_information(Logger_, "Stopped...");
|
poco_information(Logger_, "Stopped...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,4 +338,4 @@ namespace OpenWifi {
|
|||||||
partitions.front().get_partition()));
|
partitions.front().get_partition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace OpenWifi
|
} // namespace OpenWifi
|
||||||
|
|||||||
@@ -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) {
|
inline void SendCompressedTarFile(const std::string &FileName, const std::string &Content) {
|
||||||
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
|
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
|
||||||
SetCommonHeaders();
|
SetCommonHeaders();
|
||||||
@@ -552,8 +557,8 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
|
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
|
||||||
|
|
||||||
inline void ReturnObject(Poco::JSON::Object &Object) {
|
inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
|
||||||
PrepareResponse();
|
PrepareResponse(Status);
|
||||||
if (Request != nullptr) {
|
if (Request != nullptr) {
|
||||||
// can we compress ???
|
// can we compress ???
|
||||||
auto AcceptedEncoding = Request->find("Accept-Encoding");
|
auto AcceptedEncoding = Request->find("Accept-Encoding");
|
||||||
|
|||||||
@@ -68,6 +68,16 @@ namespace OpenWifi {
|
|||||||
Context->addCertificateAuthority(Issuing);
|
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_);
|
Poco::Crypto::RSAKey Key("", key_file_, key_file_password_);
|
||||||
Context->usePrivateKey(Key);
|
Context->usePrivateKey(Key);
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace OpenWifi {
|
|||||||
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
|
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
|
||||||
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
|
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
|
||||||
[[nodiscard]] inline auto RootCA() const { return root_ca_; };
|
[[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 KeyFilePassword() const { return key_file_password_; };
|
||||||
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
|
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
|
||||||
[[nodiscard]] inline auto Name() const { return name_; };
|
[[nodiscard]] inline auto Name() const { return name_; };
|
||||||
|
|||||||
@@ -580,6 +580,9 @@ namespace OpenWifi::RESTAPI::Protocol {
|
|||||||
static const char *INTERVAL = "interval";
|
static const char *INTERVAL = "interval";
|
||||||
static const char *UI = "UI";
|
static const char *UI = "UI";
|
||||||
static const char *BANDWIDTH = "bandwidth";
|
static const char *BANDWIDTH = "bandwidth";
|
||||||
|
|
||||||
|
static const char *FIXEDCONFIG = "fixedconfig";
|
||||||
|
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
|
||||||
} // namespace OpenWifi::RESTAPI::Protocol
|
} // namespace OpenWifi::RESTAPI::Protocol
|
||||||
|
|
||||||
namespace OpenWifi::uCentralProtocol {
|
namespace OpenWifi::uCentralProtocol {
|
||||||
@@ -608,6 +611,7 @@ namespace OpenWifi::uCentralProtocol {
|
|||||||
static const char *CFGPENDING = "cfgpending";
|
static const char *CFGPENDING = "cfgpending";
|
||||||
static const char *RECOVERY = "recovery";
|
static const char *RECOVERY = "recovery";
|
||||||
static const char *COMPRESS_64 = "compress_64";
|
static const char *COMPRESS_64 = "compress_64";
|
||||||
|
static const char *COMPRESS_SZ = "compress_sz";
|
||||||
static const char *CAPABILITIES = "capabilities";
|
static const char *CAPABILITIES = "capabilities";
|
||||||
static const char *REQUEST_UUID = "request_uuid";
|
static const char *REQUEST_UUID = "request_uuid";
|
||||||
static const char *SANITY = "sanity";
|
static const char *SANITY = "sanity";
|
||||||
@@ -692,6 +696,9 @@ namespace OpenWifi::uCentralProtocol {
|
|||||||
static const char *RRM = "rrm";
|
static const char *RRM = "rrm";
|
||||||
static const char *ACTIONS = "actions";
|
static const char *ACTIONS = "actions";
|
||||||
|
|
||||||
|
static const char *FIXEDCONFIG = "fixedconfig";
|
||||||
|
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
|
||||||
|
|
||||||
} // namespace OpenWifi::uCentralProtocol
|
} // namespace OpenWifi::uCentralProtocol
|
||||||
|
|
||||||
namespace OpenWifi::uCentralProtocol::Events {
|
namespace OpenWifi::uCentralProtocol::Events {
|
||||||
@@ -788,6 +795,8 @@ namespace OpenWifi::APCommands {
|
|||||||
certupdate,
|
certupdate,
|
||||||
transfer,
|
transfer,
|
||||||
powercycle,
|
powercycle,
|
||||||
|
fixedconfig,
|
||||||
|
cablediagnostics,
|
||||||
unknown
|
unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -802,7 +811,8 @@ namespace OpenWifi::APCommands {
|
|||||||
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
|
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
|
||||||
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
|
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
|
||||||
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
|
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
|
||||||
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE
|
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
|
||||||
|
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
|
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
|
||||||
|
|||||||
@@ -590,6 +590,26 @@ namespace OpenWifi::Utils {
|
|||||||
return false;
|
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) {
|
bool IsAlphaNumeric(const std::string &s) {
|
||||||
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
|
return std::all_of(s.begin(), s.end(), [](char c) -> bool { return isalnum(c); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ namespace OpenWifi::Utils {
|
|||||||
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
bool ExtractBase64CompressedData(const std::string &CompressedData,
|
||||||
std::string &UnCompressedData, uint64_t compress_sz);
|
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)
|
inline bool match(const char* first, const char* second)
|
||||||
{
|
{
|
||||||
// If we reach at the end of both strings, we are done
|
// If we reach at the end of both strings, we are done
|
||||||
|
|||||||
@@ -644,21 +644,7 @@ namespace OpenWifi {
|
|||||||
uint64_t Size = FileContent.str().size();
|
uint64_t Size = FileContent.str().size();
|
||||||
|
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
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()) {
|
if (Size < FileUploader()->MaxSize()) {
|
||||||
|
|
||||||
Poco::Data::BLOB TheBlob;
|
Poco::Data::BLOB TheBlob;
|
||||||
@@ -680,7 +666,20 @@ namespace OpenWifi {
|
|||||||
} else {
|
} else {
|
||||||
poco_warning(Logger(), fmt::format("File {} is too large.", UUID));
|
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();
|
Sess.commit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const Poco::Exception &E) {
|
} catch (const Poco::Exception &E) {
|
||||||
Logger().log(E);
|
Logger().log(E);
|
||||||
@@ -689,7 +688,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
|
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 {
|
try {
|
||||||
Poco::Data::BLOB L;
|
Poco::Data::BLOB L;
|
||||||
/*
|
/*
|
||||||
@@ -702,10 +701,10 @@ namespace OpenWifi {
|
|||||||
Poco::Data::Statement Select1(Sess);
|
Poco::Data::Statement Select1(Sess);
|
||||||
|
|
||||||
std::string TmpSerialNumber;
|
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;
|
std::string Command;
|
||||||
Select1 << ConvertParams(st1), Poco::Data::Keywords::into(TmpSerialNumber),
|
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();
|
Select1.execute();
|
||||||
|
|
||||||
if (TmpSerialNumber != SerialNumber) {
|
if (TmpSerialNumber != SerialNumber) {
|
||||||
@@ -825,4 +824,4 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace OpenWifi
|
} // namespace OpenWifi
|
||||||
|
|||||||
@@ -195,17 +195,32 @@ namespace OpenWifi {
|
|||||||
bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
bool Storage::GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
|
||||||
std::vector<std::string> &SerialNumbers,
|
std::vector<std::string> &SerialNumbers,
|
||||||
const std::string &orderBy,
|
const std::string &orderBy,
|
||||||
const std::string &platform) {
|
const std::string &platform, bool includeProvisioned) {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Select(Sess);
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
std::string st;
|
std::string st;
|
||||||
|
std::string whereClause = "";
|
||||||
if(!platform.empty()) {
|
if(!platform.empty()) {
|
||||||
st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
|
if (includeProvisioned == false) {
|
||||||
|
|
||||||
|
whereClause = fmt::format("WHERE entity='' and venue='' and DeviceType='" + platform + "'");
|
||||||
|
} else {
|
||||||
|
whereClause = fmt::format("WHERE DeviceType='" + platform + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//st = "SELECT SerialNumber From Devices WHERE DeviceType='" + platform + "' ";
|
||||||
} else {
|
} else {
|
||||||
st = "SELECT SerialNumber From Devices ";
|
if (includeProvisioned == false) {
|
||||||
|
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||||
|
}
|
||||||
|
//st = "SELECT SerialNumber From Devices ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
st = fmt::format("SELECT SerialNumber From Devices {}", whereClause);
|
||||||
|
|
||||||
if (orderBy.empty())
|
if (orderBy.empty())
|
||||||
st += " ORDER BY SerialNumber ASC ";
|
st += " ORDER BY SerialNumber ASC ";
|
||||||
else
|
else
|
||||||
@@ -600,7 +615,9 @@ namespace OpenWifi {
|
|||||||
D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
|
D.locale = InsertRadiosCountyRegulation(D.Configuration, IPAddress);
|
||||||
D.SerialNumber = Poco::toLower(SerialNumber);
|
D.SerialNumber = Poco::toLower(SerialNumber);
|
||||||
D.Compatible = Caps.Compatible();
|
D.Compatible = Caps.Compatible();
|
||||||
D.DeviceType = Caps.Platform();
|
if(D.Compatible.empty())
|
||||||
|
D.Compatible = Caps.Model();
|
||||||
|
D.DeviceType = Poco::toLower(Caps.Platform());
|
||||||
D.MACAddress = Utils::SerialToMAC(SerialNumber);
|
D.MACAddress = Utils::SerialToMAC(SerialNumber);
|
||||||
D.Manufacturer = Caps.Model();
|
D.Manufacturer = Caps.Model();
|
||||||
D.Firmware = Firmware;
|
D.Firmware = Firmware;
|
||||||
@@ -649,6 +666,22 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Storage::GetPlatform(const std::string &SerialNumber) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
|
std::string St = fmt::format("SELECT DeviceType FROM Devices WHERE SerialNumber='{}'", SerialNumber);
|
||||||
|
std::string Platform;
|
||||||
|
Select << ConvertParams(St), Poco::Data::Keywords::into(Platform);
|
||||||
|
Select.execute();
|
||||||
|
return Platform;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger().log(E);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
bool Storage::DeleteDevice(std::string &SerialNumber) {
|
bool Storage::DeleteDevice(std::string &SerialNumber) {
|
||||||
try {
|
try {
|
||||||
std::vector<std::string> TableNames{"Devices", "Statistics", "CommandList",
|
std::vector<std::string> TableNames{"Devices", "Statistics", "CommandList",
|
||||||
@@ -843,25 +876,38 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
|
bool Storage::GetDevices(uint64_t From, uint64_t HowMany,
|
||||||
std::vector<GWObjects::Device> &Devices, const std::string &orderBy, const std::string &platform) {
|
std::vector<GWObjects::Device> &Devices, const std::string &orderBy, const std::string &platform,
|
||||||
|
bool includeProvisioned) {
|
||||||
DeviceRecordList Records;
|
DeviceRecordList Records;
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Select(Sess);
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
std::string st;
|
std::string st;
|
||||||
|
std::string whereClause = "";
|
||||||
if(platform.empty()) {
|
if(platform.empty()) {
|
||||||
st =
|
|
||||||
fmt::format("SELECT {} FROM Devices {} {}", DB_DeviceSelectFields,
|
if (includeProvisioned == false) {
|
||||||
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
whereClause = fmt::format("WHERE entity='' and venue=''");
|
||||||
ComputeRange(From, HowMany));
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
st =
|
|
||||||
fmt::format("SELECT {} FROM Devices WHERE DeviceType='{}' {} {}", DB_DeviceSelectFields, platform,
|
if (includeProvisioned == false) {
|
||||||
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
whereClause = fmt::format("WHERE DeviceType='{}' and entity='' and venue=''",platform);
|
||||||
ComputeRange(From, HowMany));
|
} else {
|
||||||
|
whereClause = fmt::format("WHERE DeviceType='{}'", platform);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
st =
|
||||||
|
fmt::format("SELECT {} FROM Devices {} {} {}", DB_DeviceSelectFields, whereClause,
|
||||||
|
orderBy.empty() ? " ORDER BY SerialNumber ASC " : orderBy,
|
||||||
|
ComputeRange(From, HowMany));
|
||||||
|
|
||||||
|
//Logger().information(fmt::format(" GetDevices st is {} ", st));
|
||||||
|
|
||||||
Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
|
Select << ConvertParams(st), Poco::Data::Keywords::into(Records);
|
||||||
Select.execute();
|
Select.execute();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user