Compare commits

...

14 Commits

Author SHA1 Message Date
TIP Automation User
a63dec7f8b Chg: update image tag in helm values to v2.10.0 2023-06-30 15:30:50 +00:00
TIP Automation User
9c5ed40d57 Chg: update image tag in helm values to v2.10.0-RC2 2023-06-21 16:24:32 +00:00
Stephane Bourque
e1ec4d9491 Merge pull request #90 from Telecominfraproject/main
https://telecominfraproject.atlassian.net/browse/WIFI-12689
2023-06-20 09:02:22 -07:00
Stephane Bourque
0437031d78 Merge pull request #89 from pcosmo/patch-1
Update owprov.yaml
2023-06-20 09:00:19 -07:00
stephb9959
2242b02f0f https://telecominfraproject.atlassian.net/browse/WIFI-12689
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-06-20 08:42:15 -07:00
pcosmo
8287628583 Update owprov.yaml
Fixed typo in configuration commands, e.g.:

 getCponfiguration -> getConfiguration
2023-06-15 11:29:11 -04:00
TIP Automation User
f925ce12be Chg: update image tag in helm values to v2.10.0-RC1 2023-06-09 13:34:31 +00:00
stephb9959
7b3de5d5ef https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-05-18 09:01:31 -07:00
stephb9959
6007c1f06f https://telecominfraproject.atlassian.net/browse/WIFI-12597
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-05-11 07:32:22 -07:00
stephb9959
74916abdbd https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-05-03 07:50:37 -07:00
stephb9959
0899c6f2d9 https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-04-19 14:09:37 -07:00
stephb9959
f51b2bd11e https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-04-19 14:03:43 -07:00
stephb9959
8b21ef16a1 https://telecominfraproject.atlassian.net/browse/WIFI-12525
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-04-19 14:03:31 -07:00
stephb9959
7ad4de4960 https://telecominfraproject.atlassian.net/browse/WIFI-12361
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2023-03-08 09:32:14 -08:00
58 changed files with 6104 additions and 5369 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owprov VERSION 2.9.0) project(owprov VERSION 2.10.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -117,6 +117,7 @@ add_executable(owprov
src/framework/MicroServiceExtra.h src/framework/MicroServiceExtra.h
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.cpp
src/framework/ConfigurationValidator.h src/framework/ConfigurationValidator.h
src/framework/default_device_types.h
src/UI_Prov_WebSocketNotifications.h src/UI_Prov_WebSocketNotifications.h
src/UI_Prov_WebSocketNotifications.cpp src/UI_Prov_WebSocketNotifications.cpp
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp

2
build
View File

@@ -1 +1 @@
21 32

View File

@@ -42,6 +42,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owprov"} \ STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owprov"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owprov"} \ STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owprov"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \ STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
RRM_PROVIDERS=${RRM_PROVIDERS:-"owrrm"} \
envsubst < /owprov.properties.tmpl > $OWPROV_CONFIG/owprov.properties envsubst < /owprov.properties.tmpl > $OWPROV_CONFIG/owprov.properties
fi fi

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images: images:
owprov: owprov:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov
tag: main tag: v2.10.0
pullPolicy: Always pullPolicy: Always
# regcred: # regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io # registry: tip-tip-wlan-cloud-ucentral.jfrog.io

View File

@@ -2258,7 +2258,7 @@ paths:
get: get:
tags: tags:
- Configuration Overrides - Configuration Overrides
operationId: getCponfigurationOverrides operationId: getConfigurationOverrides
summary: retrieve a list of configuration overrides for a given device summary: retrieve a list of configuration overrides for a given device
parameters: parameters:
- in: path - in: path
@@ -2282,7 +2282,7 @@ paths:
delete: delete:
tags: tags:
- Configuration Overrides - Configuration Overrides
operationId: deleteCponfigurationOverrides operationId: deleteConfigurationOverrides
summary: delete all configuration overrides for a given device from a given source summary: delete all configuration overrides for a given device from a given source
parameters: parameters:
- in: path - in: path

View File

@@ -37,10 +37,12 @@ openwifi.system.data = ${SYSTEM_DATA}
openwifi.system.debug = false openwifi.system.debug = false
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE} openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.commandchannel = /tmp/app.ucentralfms openwifi.system.commandchannel = /tmp/app.owprov
openwifi.system.uri.ui = ${SYSTEM_URI_UI} openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE} openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE}
rrm.providers = ${RRM_PROVIDERS}
############################# #############################
# Generic information for all micro services # Generic information for all micro services
############################# #############################

View File

@@ -41,7 +41,7 @@ namespace OpenWifi {
Payload.set("ObjectType", OT); Payload.set("ObjectType", OT);
std::ostringstream OS; std::ostringstream OS;
Payload.stringify(OS); Payload.stringify(OS);
KafkaManager()->PostMessage(KafkaTopics::PROVISIONING_CHANGE, Ops[op], OS.str()); KafkaManager()->PostMessage(KafkaTopics::PROVISIONING_CHANGE, Ops[op], std::make_shared<std::string>(OS.str()));
return true; return true;
} }

View File

@@ -13,6 +13,7 @@
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "CapabilitiesCache.h" #include "CapabilitiesCache.h"
#include "RADIUSSessionTracker.h"
#endif #endif
#include "RESTAPI_GWobjects.h" #include "RESTAPI_GWobjects.h"
@@ -29,6 +30,7 @@ namespace OpenWifi::GWObjects {
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", CapabilitiesCache::instance()->GetPlatform(Compatible));
field_to_json(Obj, "hasRADIUSSessions", RADIUSSessionTracker()->HasSessions(SerialNumber));
#endif #endif
field_to_json(Obj, "macAddress", MACAddress); field_to_json(Obj, "macAddress", MACAddress);
field_to_json(Obj, "manufacturer", Manufacturer); field_to_json(Obj, "manufacturer", Manufacturer);
@@ -54,6 +56,9 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "pendingConfiguration", pendingConfiguration); field_to_json(Obj, "pendingConfiguration", pendingConfiguration);
field_to_json(Obj, "pendingConfigurationCmd", pendingConfigurationCmd); field_to_json(Obj, "pendingConfigurationCmd", pendingConfigurationCmd);
field_to_json(Obj, "restrictionDetails", restrictionDetails); field_to_json(Obj, "restrictionDetails", restrictionDetails);
field_to_json(Obj, "pendingUUID", pendingUUID);
field_to_json(Obj, "simulated", simulated);
field_to_json(Obj, "lastRecordedContact", lastRecordedContact);
} }
void Device::to_json_with_status(Poco::JSON::Object &Obj) const { void Device::to_json_with_status(Poco::JSON::Object &Obj) const {
@@ -63,7 +68,7 @@ namespace OpenWifi::GWObjects {
ConnectionState ConState; ConnectionState ConState;
if (AP_WS_Server()->GetState(SerialNumber, ConState)) { if (AP_WS_Server()->GetState(SerialNumber, ConState)) {
ConState.to_json(Obj); ConState.to_json(SerialNumber,Obj);
} else { } else {
field_to_json(Obj, "ipAddress", ""); field_to_json(Obj, "ipAddress", "");
field_to_json(Obj, "txBytes", (uint64_t)0); field_to_json(Obj, "txBytes", (uint64_t)0);
@@ -75,6 +80,13 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "associations_2G", (uint64_t)0); field_to_json(Obj, "associations_2G", (uint64_t)0);
field_to_json(Obj, "associations_5G", (uint64_t)0); field_to_json(Obj, "associations_5G", (uint64_t)0);
field_to_json(Obj, "associations_6G", (uint64_t)0); field_to_json(Obj, "associations_6G", (uint64_t)0);
field_to_json(Obj, "hasRADIUSSessions", false);
field_to_json(Obj, "hasGPS", ConState.hasGPS);
field_to_json(Obj, "sanity", ConState.sanity);
field_to_json(Obj, "memoryUsed", ConState.memoryUsed);
field_to_json(Obj, "sanity", ConState.sanity);
field_to_json(Obj, "load", ConState.load);
field_to_json(Obj, "temperature", ConState.temperature);
} }
#endif #endif
} }
@@ -84,20 +96,32 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj, "serialNumber", SerialNumber); field_from_json(Obj, "serialNumber", SerialNumber);
field_from_json(Obj, "deviceType", DeviceType); field_from_json(Obj, "deviceType", DeviceType);
field_from_json(Obj, "macAddress", MACAddress); field_from_json(Obj, "macAddress", MACAddress);
field_from_json(Obj, "manufacturer", Manufacturer);
field_from_json(Obj, "UUID", UUID);
field_from_json(Obj, "configuration", Configuration); field_from_json(Obj, "configuration", Configuration);
field_from_json(Obj, "notes", Notes); field_from_json(Obj, "notes", Notes);
field_from_json(Obj, "manufacturer", Manufacturer); field_from_json(Obj, "createdTimestamp", CreationTimestamp);
field_from_json(Obj, "lastConfigurationChange", LastConfigurationChange);
field_from_json(Obj, "lastConfigurationDownload", LastConfigurationDownload);
field_from_json(Obj, "lastFWUpdate", LastFWUpdate);
field_from_json(Obj, "owner", Owner); field_from_json(Obj, "owner", Owner);
field_from_json(Obj, "location", Location); field_from_json(Obj, "location", Location);
field_from_json(Obj, "venue", Venue); field_from_json(Obj, "venue", Venue);
field_from_json(Obj, "firmware", Firmware);
field_from_json(Obj, "compatible", Compatible); field_from_json(Obj, "compatible", Compatible);
field_from_json(Obj, "fwUpdatePolicy", FWUpdatePolicy);
field_from_json(Obj, "devicePassword", DevicePassword);
field_from_json(Obj, "subscriber", subscriber); field_from_json(Obj, "subscriber", subscriber);
field_from_json(Obj, "entity", entity); field_from_json(Obj, "entity", entity);
field_from_json(Obj, "modified", modified);
field_from_json(Obj, "locale", locale); field_from_json(Obj, "locale", locale);
field_from_json(Obj, "restrictedDevice", restrictedDevice); field_from_json(Obj, "restrictedDevice", restrictedDevice);
field_from_json(Obj, "pendingConfiguration", pendingConfiguration); field_from_json(Obj, "pendingConfiguration", pendingConfiguration);
field_from_json(Obj, "pendingConfigurationCmd", pendingConfigurationCmd); field_from_json(Obj, "pendingConfigurationCmd", pendingConfigurationCmd);
field_from_json(Obj, "restrictionDetails", restrictionDetails); field_from_json(Obj, "restrictionDetails", restrictionDetails);
field_from_json(Obj, "pendingUUID", pendingUUID);
field_from_json(Obj, "simulated", simulated);
field_from_json(Obj, "lastRecordedContact", lastRecordedContact);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }
@@ -165,6 +189,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "waitingForFile", WaitingForFile); field_to_json(Obj, "waitingForFile", WaitingForFile);
field_to_json(Obj, "attachFile", AttachDate); field_to_json(Obj, "attachFile", AttachDate);
field_to_json(Obj, "executionTime", executionTime); field_to_json(Obj, "executionTime", executionTime);
field_to_json(Obj, "lastTry", lastTry);
field_to_json(Obj, "deferred", deferred);
} }
bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -198,7 +224,7 @@ namespace OpenWifi::GWObjects {
return false; return false;
} }
void ConnectionState::to_json(Poco::JSON::Object &Obj) const { void ConnectionState::to_json([[maybe_unused]] const std::string &SerialNumber, Poco::JSON::Object &Obj) {
field_to_json(Obj, "ipAddress", Address); field_to_json(Obj, "ipAddress", Address);
field_to_json(Obj, "txBytes", TX); field_to_json(Obj, "txBytes", TX);
field_to_json(Obj, "rxBytes", RX); field_to_json(Obj, "rxBytes", RX);
@@ -220,6 +246,20 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime); field_to_json(Obj, "connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj, "totalConnectionTime", Utils::Now() - started); field_to_json(Obj, "totalConnectionTime", Utils::Now() - started);
field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate); field_to_json(Obj, "certificateExpiryDate", certificateExpiryDate);
#ifdef TIP_GATEWAY_SERVICE
hasRADIUSSessions = RADIUSSessionTracker()->HasSessions(SerialNumber);
AP_WS_Server()->ExtendedAttributes(SerialNumber, hasGPS, sanity,
memoryUsed,
load,
temperature);
#endif
field_to_json(Obj, "hasRADIUSSessions", hasRADIUSSessions );
field_to_json(Obj, "hasGPS", hasGPS);
field_to_json(Obj, "sanity", sanity);
field_to_json(Obj, "memoryUsed", memoryUsed);
field_to_json(Obj, "sanity", sanity);
field_to_json(Obj, "load", load);
field_to_json(Obj, "temperature", temperature);
switch (VerifiedCertificate) { switch (VerifiedCertificate) {
case NO_CERTIFICATE: case NO_CERTIFICATE:
@@ -234,6 +274,9 @@ namespace OpenWifi::GWObjects {
case VERIFIED: case VERIFIED:
field_to_json(Obj, "verifiedCertificate", "VERIFIED"); field_to_json(Obj, "verifiedCertificate", "VERIFIED");
break; break;
case SIMULATED:
field_to_json(Obj, "verifiedCertificate", "SIMULATED");
break;
default: default:
field_to_json(Obj, "verifiedCertificate", "NO_CERTIFICATE"); field_to_json(Obj, "verifiedCertificate", "NO_CERTIFICATE");
break; break;
@@ -490,6 +533,29 @@ namespace OpenWifi::GWObjects {
return false; return false;
} }
void RangeOptions::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "NO_IR", NO_IR);
field_to_json(Obj, "AUTO_BW", AUTO_BW);
field_to_json(Obj, "DFS", DFS);
field_to_json(Obj, "NO_OUTDOOR", NO_OUTDOOR);
field_to_json(Obj, "wmmrule_ETSI", wmmrule_ETSI);
field_to_json(Obj, "NO_OFDM", NO_OFDM);
}
void FrequencyRange::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "from", from);
field_to_json(Obj, "to", to);
field_to_json(Obj, "channelWidth", channelWidth);
field_to_json(Obj, "powerDb", powerDb);
field_to_json(Obj, "options", options);
}
void RegulatoryCountryInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "country", country);
field_to_json(Obj, "domain", domain);
field_to_json(Obj, "ranges", ranges);
}
void DeviceRestrictionsKeyInfo::to_json(Poco::JSON::Object &Obj) const { void DeviceRestrictionsKeyInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "vendor", vendor); field_to_json(Obj, "vendor", vendor);
field_to_json(Obj, "algo", algo); field_to_json(Obj, "algo", algo);
@@ -544,4 +610,42 @@ namespace OpenWifi::GWObjects {
(T.commands != commands) || (T.developer != developer) || (T.ssh != ssh) || (T.commands != commands) || (T.developer != developer) || (T.ssh != ssh) ||
(T.key_info != key_info) || (T.country != country)); (T.key_info != key_info) || (T.country != country));
} }
void RADIUSSession::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "started", started);
field_to_json(Obj, "lastTransaction", lastTransaction);
field_to_json(Obj, "destination", destination);
field_to_json(Obj, "serialNumber", serialNumber);
field_to_json(Obj, "userName", userName);
field_to_json(Obj, "accountingSessionId", accountingSessionId);
field_to_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
field_to_json(Obj, "inputPackets", inputPackets);
field_to_json(Obj, "outputPackets", outputPackets);
field_to_json(Obj, "inputOctets", inputOctets);
field_to_json(Obj, "outputOctets", outputOctets);
field_to_json(Obj, "inputGigaWords", inputGigaWords);
field_to_json(Obj, "outputGigaWords", outputGigaWords);
field_to_json(Obj, "sessionTime", sessionTime);
field_to_json(Obj, "callingStationId", callingStationId);
field_to_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
field_to_json(Obj, "interface", interface);
field_to_json(Obj, "secret", secret);
}
void RADIUSSessionList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "sessions", sessions);
}
bool RadiusCoADMParameters::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "accountingSessionId", accountingSessionId);
field_from_json(Obj, "accountingMultiSessionId", accountingMultiSessionId);
field_from_json(Obj, "callingStationId", callingStationId);
field_from_json(Obj, "chargeableUserIdentity", chargeableUserIdentity);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
} // namespace OpenWifi::GWObjects } // namespace OpenWifi::GWObjects

View File

@@ -11,9 +11,13 @@
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "RESTAPI_SecurityObjects.h" #include "RESTAPI_SecurityObjects.h"
#ifdef TIP_GATEWAY_SERVICE
#include <RADIUS_helpers.h>
#endif
namespace OpenWifi::GWObjects { namespace OpenWifi::GWObjects {
enum CertificateValidation { NO_CERTIFICATE, VALID_CERTIFICATE, MISMATCH_SERIAL, VERIFIED }; enum CertificateValidation { NO_CERTIFICATE, VALID_CERTIFICATE, MISMATCH_SERIAL, VERIFIED, SIMULATED };
struct ConnectionState { struct ConnectionState {
uint64_t MessageCount = 0; uint64_t MessageCount = 0;
@@ -38,8 +42,14 @@ namespace OpenWifi::GWObjects {
uint64_t sessionId = 0; uint64_t sessionId = 0;
double connectionCompletionTime = 0.0; double connectionCompletionTime = 0.0;
std::uint64_t certificateExpiryDate = 0; std::uint64_t certificateExpiryDate = 0;
bool hasRADIUSSessions = false;
bool hasGPS = false;
std::uint64_t sanity=0;
std::double_t memoryUsed=0.0;
std::double_t load=0.0;
std::double_t temperature=0.0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(const std::string &SerialNumber, Poco::JSON::Object &Obj) ;
}; };
struct DeviceRestrictionsKeyInfo { struct DeviceRestrictionsKeyInfo {
@@ -96,6 +106,9 @@ namespace OpenWifi::GWObjects {
std::string pendingConfiguration; std::string pendingConfiguration;
std::string pendingConfigurationCmd; std::string pendingConfigurationCmd;
DeviceRestrictions restrictionDetails; DeviceRestrictions restrictionDetails;
std::uint64_t pendingUUID = 0;
bool simulated=false;
std::uint64_t lastRecordedContact=0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
void to_json_with_status(Poco::JSON::Object &Obj) const; void to_json_with_status(Poco::JSON::Object &Obj) const;
@@ -188,7 +201,11 @@ namespace OpenWifi::GWObjects {
uint64_t AttachSize = 0; uint64_t AttachSize = 0;
std::string AttachType; std::string AttachType;
double executionTime = 0.0; double executionTime = 0.0;
std::uint64_t lastTry = 0;
bool deferred = false;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct BlackListedDevice { struct BlackListedDevice {
@@ -334,4 +351,76 @@ namespace OpenWifi::GWObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct RangeOptions {
bool NO_IR=false;
bool AUTO_BW=false;
bool DFS=false;
bool NO_OUTDOOR=false;
bool wmmrule_ETSI=false;
bool NO_OFDM=false;
void to_json(Poco::JSON::Object &Obj) const;
};
struct FrequencyRange {
float from = 0.0;
float to = 0.0;
int channelWidth = 0;
int powerDb = 0;
RangeOptions options;
void to_json(Poco::JSON::Object &Obj) const;
};
struct RegulatoryCountryInfo {
std::string country;
std::string domain;
std::vector<FrequencyRange> ranges;
void to_json(Poco::JSON::Object &Obj) const;
};
using RegulatoryInfoCountryMap = std::map<std::string,RegulatoryCountryInfo>;
struct RADIUSSession {
std::uint64_t started=0,
lastTransaction=0;
std::string serialNumber,
destination,
userName,
accountingSessionId,
accountingMultiSessionId,
callingStationId,
chargeableUserIdentity,
secret,
interface;
std::uint64_t inputPackets = 0,
outputPackets = 0,
inputOctets = 0,
outputOctets = 0,
inputGigaWords = 0,
outputGigaWords = 0;
std::uint32_t sessionTime = 0;
#ifdef TIP_GATEWAY_SERVICE
RADIUS::RadiusPacket accountingPacket;
#endif
void to_json(Poco::JSON::Object &Obj) const;
};
struct RADIUSSessionList {
std::vector<RADIUSSession> sessions;
void to_json(Poco::JSON::Object &Obj) const;
};
struct RadiusCoADMParameters {
std::string accountingSessionId,
accountingMultiSessionId,
callingStationId,
chargeableUserIdentity;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} // namespace OpenWifi::GWObjects } // namespace OpenWifi::GWObjects

View File

@@ -4,17 +4,19 @@
#include "ALBserver.h" #include "ALBserver.h"
#include "framework/utils.h"
#include "framework/MicroServiceFuncs.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
void ALBRequestHandler::handleRequest([[maybe_unused]] Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) { void ALBRequestHandler::handleRequest([[maybe_unused]] Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
Utils::SetThreadName("alb-request"); Utils::SetThreadName("alb-request");
try { try {
if ((id_ % 100) == 0) { if ((id_ % 100) == 0) {
Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.", Request.clientAddress().toString(), id_)); Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.",
Request.clientAddress().toString(), id_));
} }
Response.setChunkedTransferEncoding(true); Response.setChunkedTransferEncoding(true);
Response.setContentType("text/html"); Response.setContentType("text/html");
@@ -26,25 +28,21 @@ namespace OpenWifi {
std::ostream &Answer = Response.send(); std::ostream &Answer = Response.send();
Answer << "process Alive and kicking!"; Answer << "process Alive and kicking!";
} catch (...) { } catch (...) {
} }
} }
ALBRequestHandlerFactory::ALBRequestHandlerFactory(Poco::Logger & L): ALBRequestHandlerFactory::ALBRequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
Logger_(L) {
}
ALBRequestHandler* ALBRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request) { ALBRequestHandler *
ALBRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &request) {
if (request.getURI() == "/") if (request.getURI() == "/")
return new ALBRequestHandler(Logger_, req_id_++); return new ALBRequestHandler(Logger_, req_id_++);
else else
return nullptr; return nullptr;
} }
ALBHealthCheckServer::ALBHealthCheckServer() : ALBHealthCheckServer::ALBHealthCheckServer()
SubSystemServer("ALBHealthCheckServer", "ALB-SVR", "alb") : SubSystemServer("ALBHealthCheckServer", "ALB-SVR", "alb") {}
{
}
int ALBHealthCheckServer::Start() { int ALBHealthCheckServer::Start() {
if (MicroServiceConfigGetBool("alb.enable", false)) { if (MicroServiceConfigGetBool("alb.enable", false)) {
@@ -60,7 +58,8 @@ namespace OpenWifi {
Socket_ = std::make_unique<Poco::Net::ServerSocket>(SockAddr, Port_); Socket_ = std::make_unique<Poco::Net::ServerSocket>(SockAddr, Port_);
auto Params = new Poco::Net::HTTPServerParams; auto Params = new Poco::Net::HTTPServerParams;
Params->setName("ws:alb"); Params->setName("ws:alb");
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger()), *Socket_, Params); Server_ = std::make_unique<Poco::Net::HTTPServer>(
new ALBRequestHandlerFactory(Logger()), *Socket_, Params);
Server_->start(); Server_->start();
} }

View File

@@ -7,31 +7,30 @@
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include "Poco/Net/HTTPRequestHandler.h" #include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h" #include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h" #include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
namespace OpenWifi { namespace OpenWifi {
class ALBRequestHandler : public Poco::Net::HTTPRequestHandler { class ALBRequestHandler : public Poco::Net::HTTPRequestHandler {
public: public:
explicit ALBRequestHandler(Poco::Logger & L, uint64_t id) explicit ALBRequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id) {}
: Logger_(L), id_(id) {
}
void handleRequest([[maybe_unused]] Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override; void handleRequest([[maybe_unused]] Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override;
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
uint64_t id_; uint64_t id_;
}; };
class ALBRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory class ALBRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
{
public: public:
explicit ALBRequestHandlerFactory(Poco::Logger &L); explicit ALBRequestHandlerFactory(Poco::Logger &L);
ALBRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override; ALBRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
@@ -60,4 +59,3 @@ namespace OpenWifi {
inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -4,22 +4,19 @@
#pragma once #pragma once
#include "Poco/Logger.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/Logger.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
inline void API_Proxy( Poco::Logger &Logger, inline void API_Proxy(Poco::Logger &Logger, Poco::Net::HTTPServerRequest *Request,
Poco::Net::HTTPServerRequest *Request, Poco::Net::HTTPServerResponse *Response, const char *ServiceType,
Poco::Net::HTTPServerResponse *Response, const char *PathRewrite, uint64_t msTimeout_ = 10000) {
const char * ServiceType,
const char * PathRewrite,
uint64_t msTimeout_ = 10000 ) {
try { try {
auto Services = MicroServiceGetServices(ServiceType); auto Services = MicroServiceGetServices(ServiceType);
for (auto const &Svc : Services) { for (auto const &Svc : Services) {
@@ -31,7 +28,8 @@ namespace OpenWifi {
// std::cout << " Source: " << SourceURI.toString() << std::endl; // std::cout << " Source: " << SourceURI.toString() << std::endl;
// std::cout << "Destination: " << DestinationURI.toString() << std::endl; // std::cout << "Destination: " << DestinationURI.toString() << std::endl;
Poco::Net::HTTPSClientSession Session(DestinationURI.getHost(), DestinationURI.getPort()); Poco::Net::HTTPSClientSession Session(DestinationURI.getHost(),
DestinationURI.getPort());
Session.setKeepAlive(true); Session.setKeepAlive(true);
Session.setTimeout(Poco::Timespan(msTimeout_ / 1000, msTimeout_ % 1000)); Session.setTimeout(Poco::Timespan(msTimeout_ / 1000, msTimeout_ % 1000));
Poco::Net::HTTPRequest ProxyRequest(Request->getMethod(), Poco::Net::HTTPRequest ProxyRequest(Request->getMethod(),
@@ -76,7 +74,8 @@ namespace OpenWifi {
try { try {
std::istream &ProxyResponseStream = Session.receiveResponse(ProxyResponse); std::istream &ProxyResponseStream = Session.receiveResponse(ProxyResponse);
Poco::JSON::Parser P2; Poco::JSON::Parser P2;
auto ProxyResponseBody = P2.parse(ProxyResponseStream).extract<Poco::JSON::Object::Ptr>(); auto ProxyResponseBody =
P2.parse(ProxyResponseStream).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Stringifier::condense(ProxyResponseBody, SSR); Poco::JSON::Stringifier::condense(ProxyResponseBody, SSR);
Response->setContentType("application/json"); Response->setContentType("application/json");
Response->setContentLength(SSR.str().size()); Response->setContentLength(SSR.str().size());
@@ -84,7 +83,6 @@ namespace OpenWifi {
Response->sendBuffer(SSR.str().c_str(), SSR.str().size()); Response->sendBuffer(SSR.str().c_str(), SSR.str().size());
return; return;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }
Response->setStatus(ProxyResponse.getStatus()); Response->setStatus(ProxyResponse.getStatus());
Response->send(); Response->send();
@@ -96,4 +94,4 @@ namespace OpenWifi {
Logger.log(E); Logger.log(E);
} }
} }
} } // namespace OpenWifi

View File

@@ -4,13 +4,13 @@
#pragma once #pragma once
#include <string>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <string>
#include "Poco/StreamCopier.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "Poco/StreamCopier.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
@@ -18,7 +18,6 @@
namespace OpenWifi { namespace OpenWifi {
class AppServiceRegistry { class AppServiceRegistry {
public: public:
AppServiceRegistry() { AppServiceRegistry() {
@@ -42,9 +41,7 @@ namespace OpenWifi {
return *instance_; return *instance_;
} }
inline ~AppServiceRegistry() { inline ~AppServiceRegistry() { Save(); }
Save();
}
inline void Save() { inline void Save() {
std::istringstream IS(to_string(Registry_)); std::istringstream IS(to_string(Registry_));
@@ -99,4 +96,4 @@ namespace OpenWifi {
inline auto AppServiceRegistry() { return AppServiceRegistry::instance(); } inline auto AppServiceRegistry() { return AppServiceRegistry::instance(); }
} } // namespace OpenWifi

View File

@@ -4,28 +4,27 @@
#include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPServerResponse.h"
#include "fmt/format.h"
#include "framework/AuthClient.h" #include "framework/AuthClient.h"
#include "framework/MicroServiceNames.h" #include "framework/MicroServiceNames.h"
#include "framework/OpenAPIRequests.h" #include "framework/OpenAPIRequests.h"
#include "framework/utils.h" #include "framework/utils.h"
#include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
bool AuthClient::RetrieveTokenInformation(const std::string &SessionToken, bool AuthClient::RetrieveTokenInformation(const std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy &UInfo, SecurityObjects::UserInfoAndPolicy &UInfo,
std::uint64_t TID, std::uint64_t TID, bool &Expired, bool &Contacted,
bool & Expired, bool & Contacted, bool Sub) { bool Sub) {
try { try {
Types::StringPairVec QueryData; Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token", SessionToken)); QueryData.push_back(std::make_pair("token", SessionToken));
std::string AlternateURIForLogging = fmt::format("{}?token={}", Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken", Utils::SanitizeToken(SessionToken)); std::string AlternateURIForLogging = fmt::format(
"{}?token={}", Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken",
Utils::SanitizeToken(SessionToken));
OpenAPIRequestGet Req(uSERVICE_SECURITY, OpenAPIRequestGet Req(uSERVICE_SECURITY,
Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken", Sub ? "/api/v1/validateSubToken" : "/api/v1/validateToken",
QueryData, QueryData, 10000, AlternateURIForLogging);
10000,
AlternateURIForLogging
);
Poco::JSON::Object::Ptr Response; Poco::JSON::Object::Ptr Response;
auto StatusCode = Req.Do(Response); auto StatusCode = Req.Do(Response);
@@ -50,14 +49,15 @@ namespace OpenWifi {
} }
} }
} catch (...) { } catch (...) {
poco_error(Logger(),fmt::format("Failed to retrieve token={} for TID={}", Utils::SanitizeToken(SessionToken), TID)); poco_error(Logger(), fmt::format("Failed to retrieve token={} for TID={}",
Utils::SanitizeToken(SessionToken), TID));
} }
Expired = false; Expired = false;
return false; return false;
} }
bool AuthClient::IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool AuthClient::IsAuthorized(const std::string &SessionToken,
std::uint64_t TID, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
bool &Expired, bool &Contacted, bool Sub) { bool &Expired, bool &Contacted, bool Sub) {
auto User = Cache_.get(SessionToken); auto User = Cache_.get(SessionToken);
if (!User.isNull()) { if (!User.isNull()) {
@@ -75,16 +75,14 @@ namespace OpenWifi {
bool AuthClient::RetrieveApiKeyInformation(const std::string &SessionToken, bool AuthClient::RetrieveApiKeyInformation(const std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy &UInfo, SecurityObjects::UserInfoAndPolicy &UInfo,
std::uint64_t TID, std::uint64_t TID, bool &Expired, bool &Contacted,
bool & Expired, bool & Contacted, [[maybe_unused]] bool & Suspended) { [[maybe_unused]] bool &Suspended) {
try { try {
Types::StringPairVec QueryData; Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("apikey", SessionToken)); QueryData.push_back(std::make_pair("apikey", SessionToken));
std::string AlternateURIForLogging = fmt::format("/api/v1/validateApiKey?apiKey={}", Utils::SanitizeToken(SessionToken)); std::string AlternateURIForLogging =
OpenAPIRequestGet Req( uSERVICE_SECURITY, fmt::format("/api/v1/validateApiKey?apiKey={}", Utils::SanitizeToken(SessionToken));
"/api/v1/validateApiKey" , OpenAPIRequestGet Req(uSERVICE_SECURITY, "/api/v1/validateApiKey", QueryData, 10000,
QueryData,
10000,
AlternateURIForLogging); AlternateURIForLogging);
Poco::JSON::Object::Ptr Response; Poco::JSON::Object::Ptr Response;
@@ -96,24 +94,29 @@ namespace OpenWifi {
Contacted = true; Contacted = true;
if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_OK) { if (StatusCode == Poco::Net::HTTPServerResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo") && Response->has("expiresOn")) { if (Response->has("tokenInfo") && Response->has("userInfo") &&
Response->has("expiresOn")) {
UInfo.from_json(Response); UInfo.from_json(Response);
Expired = false; Expired = false;
ApiKeyCache_.update(SessionToken, ApiKeyCacheEntry{ .UserInfo = UInfo, .ExpiresOn = Response->get("expiresOn")}); ApiKeyCache_.update(SessionToken,
ApiKeyCacheEntry{.UserInfo = UInfo,
.ExpiresOn = Response->get("expiresOn")});
return true; return true;
} else { } else {
return false; return false;
} }
} }
} catch (...) { } catch (...) {
poco_error(Logger(),fmt::format("Failed to retrieve api key={} for TID={}", Utils::SanitizeToken(SessionToken), TID)); poco_error(Logger(), fmt::format("Failed to retrieve api key={} for TID={}",
Utils::SanitizeToken(SessionToken), TID));
} }
Expired = false; Expired = false;
return false; return false;
} }
bool AuthClient::IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo, bool AuthClient::IsValidApiKey(const std::string &SessionToken,
std::uint64_t TID, bool &Expired, bool &Contacted, bool & Suspended) { SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
bool &Expired, bool &Contacted, bool &Suspended) {
auto User = ApiKeyCache_.get(SessionToken); auto User = ApiKeyCache_.get(SessionToken);
if (!User.isNull()) { if (!User.isNull()) {
if (User->ExpiresOn < Utils::Now()) { if (User->ExpiresOn < Utils::Now()) {

View File

@@ -4,9 +4,9 @@
#pragma once #pragma once
#include "framework/SubSystemServer.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "Poco/ExpireLRUCache.h" #include "Poco/ExpireLRUCache.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "framework/SubSystemServer.h"
#include "framework/utils.h" #include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
@@ -14,10 +14,8 @@ namespace OpenWifi {
class AuthClient : public SubSystemServer { class AuthClient : public SubSystemServer {
public: public:
explicit AuthClient() noexcept: explicit AuthClient() noexcept
SubSystemServer("Authentication", "AUTH-CLNT", "authentication") : SubSystemServer("Authentication", "AUTH-CLNT", "authentication") {}
{
}
static auto instance() { static auto instance() {
static auto instance_ = new AuthClient; static auto instance_ = new AuthClient;
@@ -29,9 +27,7 @@ namespace OpenWifi {
std::uint64_t ExpiresOn; std::uint64_t ExpiresOn;
}; };
inline int Start() override { inline int Start() override { return 0; }
return 0;
}
inline void Stop() override { inline void Stop() override {
poco_information(Logger(), "Stopping..."); poco_information(Logger(), "Stopping...");
@@ -50,30 +46,27 @@ namespace OpenWifi {
} }
bool RetrieveTokenInformation(const std::string &SessionToken, bool RetrieveTokenInformation(const std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
std::uint64_t TID,
bool &Expired, bool &Contacted, bool Sub = false); bool &Expired, bool &Contacted, bool Sub = false);
bool RetrieveApiKeyInformation(const std::string &SessionToken, bool RetrieveApiKeyInformation(const std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
std::uint64_t TID,
bool &Expired, bool &Contacted, bool &Suspended); bool &Expired, bool &Contacted, bool &Suspended);
bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool IsAuthorized(const std::string &SessionToken,
std::uint64_t TID, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
bool &Expired, bool &Contacted, bool Sub = false); bool &Expired, bool &Contacted, bool Sub = false);
bool IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool IsValidApiKey(const std::string &SessionToken,
std::uint64_t TID, SecurityObjects::UserInfoAndPolicy &UInfo, std::uint64_t TID,
bool &Expired, bool &Contacted, bool &Suspended); bool &Expired, bool &Contacted, bool &Suspended);
private: private:
Poco::ExpireLRUCache<std::string, OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{
Poco::ExpireLRUCache<std::string,OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{512,1200000 }; 512, 1200000};
Poco::ExpireLRUCache<std::string, ApiKeyCacheEntry> ApiKeyCache_{512, 1200000}; Poco::ExpireLRUCache<std::string, ApiKeyCacheEntry> ApiKeyCache_{512, 1200000};
}; };
inline auto AuthClient() { return AuthClient::instance(); } inline auto AuthClient() { return AuthClient::instance(); }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -152,4 +152,4 @@ namespace OpenWifi::CIDR {
[[nodiscard]] inline bool ValidateIpRanges(const Types::StringVec &Ranges) { [[nodiscard]] inline bool ValidateIpRanges(const Types::StringVec &Ranges) {
return std::all_of(cbegin(Ranges), cend(Ranges), ValidateRange); return std::all_of(cbegin(Ranges), cend(Ranges), ValidateRange);
} }
} } // namespace OpenWifi::CIDR

View File

@@ -2,8 +2,8 @@
// Created by stephane bourque on 2021-09-14. // Created by stephane bourque on 2021-09-14.
// //
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include <regex> #include <regex>
#include "ConfigurationValidator.h" #include "ConfigurationValidator.h"
@@ -17,14 +17,15 @@
#include "fmt/format.h" #include "fmt/format.h"
#include <valijson/adapters/poco_json_adapter.hpp> #include <valijson/adapters/poco_json_adapter.hpp>
#include <valijson/utils/poco_json_utils.hpp> #include <valijson/constraints/constraint.hpp>
#include <valijson/schema.hpp> #include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp> #include <valijson/schema_parser.hpp>
#include <valijson/utils/poco_json_utils.hpp>
#include <valijson/validator.hpp> #include <valijson/validator.hpp>
#include <valijson/constraints/constraint.hpp>
static const std::string GitUCentralJSONSchemaFile{ static const std::string GitUCentralJSONSchemaFile{
"https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/ucentral.schema.json"}; "https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/"
"ucentral.schema.json"};
static std::string DefaultUCentralSchema = R"foo( static std::string DefaultUCentralSchema = R"foo(
@@ -36,6 +37,10 @@ static std::string DefaultUCentralSchema = R"foo(
"uuid": { "uuid": {
"type": "integer" "type": "integer"
}, },
"public_ip_lookup": {
"type": "string",
"format": "uc-fqdn"
},
"unit": { "unit": {
"$ref": "#/$defs/unit" "$ref": "#/$defs/unit"
}, },
@@ -633,26 +638,6 @@ static std::string DefaultUCentralSchema = R"foo(
"type": "string", "type": "string",
"format": "uc-timeout", "format": "uc-timeout",
"default": "6h" "default": "6h"
},
"relay-server": {
"type": "string",
"format": "ipv4",
"example": "192.168.2.1"
},
"circuit-id-format": {
"type": "string",
"example": [
"\\{Interface\\}:\\{VLAN-Id\\}:\\{SSID\\}:\\{Model\\}:\\{Name\\}:\\{AP-MAC\\}:\\{Location\\}",
"\\{AP-MAC\\};\\{SSID\\};\\{Crypto\\}",
"\\{Name\\} \\{ESSID\\}"
]
},
"remote-id-format": {
"type": "string",
"example": [
"\\{Client-MAC-hex\\} \\{SSID\\}",
"\\{AP-MAC-hex\\} \\{SSID\\}"
]
} }
} }
}, },
@@ -1231,6 +1216,32 @@ static std::string DefaultUCentralSchema = R"foo(
"secret" "secret"
] ]
}, },
"secondary": {
"type": "object",
"properties": {
"host": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"examples": [
1812
]
},
"secret": {
"type": "string",
"examples": [
"secret"
]
}
}
},
"request-attribute": { "request-attribute": {
"type": "array", "type": "array",
"items": { "items": {
@@ -1308,6 +1319,25 @@ static std::string DefaultUCentralSchema = R"foo(
"value": "Example Operator" "value": "Example Operator"
} }
] ]
},
{
"type": "object",
"properties": {
"id": {
"type": "integer",
"maximum": 255,
"minimum": 1
},
"hex-value": {
"type": "string"
}
},
"examples": [
{
"id": 32,
"value": "0a0b0c0d"
}
]
} }
] ]
} }
@@ -1657,6 +1687,236 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.captive.click": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "click-to-continue"
}
}
},
"service.captive.radius": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "radius"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
}
}
},
"service.captive.credentials": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "credentials"
},
"credentials": {
"type": "array",
"items": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"service.captive.uam": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "uam"
},
"uam-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 3990
},
"uam-secret": {
"type": "string"
},
"uam-server": {
"type": "string"
},
"nasid": {
"type": "string"
},
"nasmac": {
"type": "string"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
},
"ssid": {
"type": "string"
},
"mac-format": {
"type": "string",
"enum": [
"aabbccddeeff",
"aa-bb-cc-dd-ee-ff",
"aa:bb:cc:dd:ee:ff",
"AABBCCDDEEFF",
"AA:BB:CC:DD:EE:FF",
"AA-BB-CC-DD-EE-FF"
]
},
"final-redirect-url": {
"type": "string",
"enum": [
"default",
"uam"
]
},
"mac-auth": {
"type": "boolean",
"default": "default"
},
"radius-gw-proxy": {
"type": "boolean",
"default": false
}
}
},
"service.captive": {
"allOf": [
{
"oneOf": [
{
"$ref": "#/$defs/service.captive.click"
},
{
"$ref": "#/$defs/service.captive.radius"
},
{
"$ref": "#/$defs/service.captive.credentials"
},
{
"$ref": "#/$defs/service.captive.uam"
}
]
},
{
"type": "object",
"properties": {
"walled-garden-fqdn": {
"type": "array",
"items": {
"type": "string"
}
},
"walled-garden-ipaddr": {
"type": "array",
"items": {
"type": "string",
"format": "uc-ip"
}
},
"web-root": {
"type": "string",
"format": "uc-base64"
},
"idle-timeout": {
"type": "integer",
"default": 600
},
"session-timeout": {
"type": "integer"
}
}
}
]
},
"interface.ssid": { "interface.ssid": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1709,6 +1969,10 @@ static std::string DefaultUCentralSchema = R"foo(
"isolate-clients": { "isolate-clients": {
"type": "boolean" "type": "boolean"
}, },
"strict-forwarding": {
"type": "boolean",
"default": false
},
"power-save": { "power-save": {
"type": "boolean" "type": "boolean"
}, },
@@ -1777,8 +2041,15 @@ static std::string DefaultUCentralSchema = R"foo(
"$ref": "#/$defs/interface.ssid.rate-limit" "$ref": "#/$defs/interface.ssid.rate-limit"
}, },
"roaming": { "roaming": {
"anyOf": [
{
"$ref": "#/$defs/interface.ssid.roaming" "$ref": "#/$defs/interface.ssid.roaming"
}, },
{
"type": "boolean"
}
]
},
"radius": { "radius": {
"$ref": "#/$defs/interface.ssid.radius" "$ref": "#/$defs/interface.ssid.radius"
}, },
@@ -1794,6 +2065,9 @@ static std::string DefaultUCentralSchema = R"foo(
"access-control-list": { "access-control-list": {
"$ref": "#/$defs/interface.ssid.acl" "$ref": "#/$defs/interface.ssid.acl"
}, },
"captive": {
"$ref": "#/$defs/service.captive"
},
"hostapd-bss-raw": { "hostapd-bss-raw": {
"type": "array", "type": "array",
"items": { "items": {
@@ -2083,6 +2357,10 @@ static std::string DefaultUCentralSchema = R"foo(
"examples": [ "examples": [
"01234567890123456789012345678901" "01234567890123456789012345678901"
] ]
},
"mutual-tls": {
"type": "boolean",
"default": true
} }
} }
}, },
@@ -2692,236 +2970,6 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.captive.click": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "click-to-continue"
}
}
},
"service.captive.radius": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "radius"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
}
}
},
"service.captive.credentials": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "credentials"
},
"credentials": {
"type": "array",
"items": {
"type": "object",
"properties": {
"username": {
"type": "string"
},
"password": {
"type": "string"
}
}
}
}
}
},
"service.captive.uam": {
"type": "object",
"properties": {
"auth-mode": {
"type": "string",
"const": "uam"
},
"uam-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 3990
},
"uam-secret": {
"type": "string"
},
"uam-server": {
"type": "string"
},
"nasid": {
"type": "string"
},
"nasmac": {
"type": "string"
},
"auth-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"auth-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"auth-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-server": {
"type": "string",
"format": "uc-host",
"examples": [
"192.168.1.10"
]
},
"acct-port": {
"type": "integer",
"maximum": 65535,
"minimum": 1024,
"default": 1812
},
"acct-secret": {
"type": "string",
"examples": [
"secret"
]
},
"acct-interval": {
"type": "integer",
"default": 600
},
"ssid": {
"type": "string"
},
"mac-format": {
"type": "string",
"enum": [
"aabbccddeeff",
"aa-bb-cc-dd-ee-ff",
"aa:bb:cc:dd:ee:ff",
"AABBCCDDEEFF",
"AA:BB:CC:DD:EE:FF",
"AA-BB-CC-DD-EE-FF"
]
},
"final-redirect-url": {
"type": "string",
"enum": [
"default",
"uam"
]
},
"mac-auth": {
"type": "boolean",
"default": "default"
},
"radius-gw-proxy": {
"type": "boolean",
"default": false
}
}
},
"service.captive": {
"allOf": [
{
"oneOf": [
{
"$ref": "#/$defs/service.captive.click"
},
{
"$ref": "#/$defs/service.captive.radius"
},
{
"$ref": "#/$defs/service.captive.credentials"
},
{
"$ref": "#/$defs/service.captive.uam"
}
]
},
{
"type": "object",
"properties": {
"walled-garden-fqdn": {
"type": "array",
"items": {
"type": "string"
}
},
"walled-garden-ipaddr": {
"type": "array",
"items": {
"type": "string",
"format": "uc-ip"
}
},
"web-root": {
"type": "string",
"format": "uc-base64"
},
"idle-timeout": {
"type": "integer",
"default": 600
},
"session-timeout": {
"type": "integer"
}
}
}
]
},
"service.gps": { "service.gps": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2940,6 +2988,32 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"service.dhcp-relay": {
"type": "object",
"properties": {
"select-ports": {
"type": "array",
"items": {
"type": "string"
}
},
"vlans": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vlan": {
"type": "number"
},
"relay-server": {
"type": "string",
"format": "uc-ip"
}
}
}
}
}
},
"service": { "service": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -2999,6 +3073,9 @@ static std::string DefaultUCentralSchema = R"foo(
}, },
"gps": { "gps": {
"$ref": "#/$defs/service.gps" "$ref": "#/$defs/service.gps"
},
"dhcp-relay": {
"$ref": "#/$defs/service.dhcp-relay"
} }
} }
}, },
@@ -3091,6 +3168,20 @@ static std::string DefaultUCentralSchema = R"foo(
} }
} }
}, },
"metrics.wifi-scan": {
"type": "object",
"properties": {
"interval": {
"type": "integer"
},
"verbose": {
"type": "boolean"
},
"information-elements": {
"type": "boolean"
}
}
},
"metrics.telemetry": { "metrics.telemetry": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -3100,7 +3191,27 @@ static std::string DefaultUCentralSchema = R"foo(
"types": { "types": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string",
"enum": [
"ssh",
"health",
"health.dns",
"health.dhcp",
"health.radius",
"health.memory",
"client",
"client.join",
"client.leave",
"client.key-mismatch",
"wifi",
"wifi.start",
"wifi.stop",
"wired",
"wired.carrier-up",
"wired.carrier-down",
"unit",
"unit.boot-up"
]
} }
} }
} }
@@ -3111,7 +3222,27 @@ static std::string DefaultUCentralSchema = R"foo(
"types": { "types": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string",
"enum": [
"ssh",
"health",
"health.dns",
"health.dhcp",
"health.radius",
"health.memory",
"client",
"client.join",
"client.leave",
"client.key-mismatch",
"wifi",
"wifi.start",
"wifi.stop",
"wired",
"wired.carrier-up",
"wired.carrier-down",
"unit",
"unit.boot-up"
]
} }
} }
} }
@@ -3131,6 +3262,9 @@ static std::string DefaultUCentralSchema = R"foo(
"dhcp-snooping": { "dhcp-snooping": {
"$ref": "#/$defs/metrics.dhcp-snooping" "$ref": "#/$defs/metrics.dhcp-snooping"
}, },
"wifi-scan": {
"$ref": "#/$defs/metrics.wifi-scan"
},
"telemetry": { "telemetry": {
"$ref": "#/$defs/metrics.telemetry" "$ref": "#/$defs/metrics.telemetry"
}, },
@@ -3184,7 +3318,6 @@ static std::string DefaultUCentralSchema = R"foo(
)foo"; )foo";
static inline bool IsIPv4(const std::string &value) { static inline bool IsIPv4(const std::string &value) {
Poco::Net::IPAddress A; Poco::Net::IPAddress A;
return ((Poco::Net::IPAddress::tryParse(value, A) && A.family() == Poco::Net::IPAddress::IPv4)); return ((Poco::Net::IPAddress::tryParse(value, A) && A.family() == Poco::Net::IPAddress::IPv4));
@@ -3242,57 +3375,68 @@ bool ExternalValijsonFormatChecker(const std::string &format, const std::string
if (format == "uc-cidr4") { if (format == "uc-cidr4") {
if (IsCIDRv4(value)) if (IsCIDRv4(value))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid CIDR IPv4 block",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid CIDR IPv4 block", value));
} else if (format == "uc-cidr6") { } else if (format == "uc-cidr6") {
if (IsCIDRv6(value)) if (IsCIDRv6(value))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid CIDR IPv6 block",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid CIDR IPv6 block", value));
} else if (format == "uc-cidr") { } else if (format == "uc-cidr") {
if (IsCIDR(value)) if (IsCIDR(value))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid CIDR block",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid CIDR block", value));
} else if (format == "uc-mac") { } else if (format == "uc-mac") {
if (std::regex_match(value, mac_regex)) if (std::regex_match(value, mac_regex))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid MAC address",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid MAC address", value));
} else if (format == "uc-timeout") { } else if (format == "uc-timeout") {
if (std::regex_match(value, uc_timeout_regex)) if (std::regex_match(value, uc_timeout_regex))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid timeout value",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid timeout value", value));
} else if (format == "uc-host") { } else if (format == "uc-host") {
if (IsIP(value)) if (IsIP(value))
return true; return true;
if (std::regex_match(value, host_regex)) if (std::regex_match(value, host_regex))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid hostname",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid hostname", value));
} else if (format == "fqdn" || format == "uc-fqdn") { } else if (format == "fqdn" || format == "uc-fqdn") {
if (std::regex_match(value, host_regex)) if (std::regex_match(value, host_regex))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid FQDN",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid FQDN", value));
} else if (format == "uc-base64") { } else if (format == "uc-base64") {
std::string s{value}; std::string s{value};
Poco::trimInPlace(s); Poco::trimInPlace(s);
if ((s.size() % 4 == 0) && std::regex_match(s, b64_regex)) if ((s.size() % 4 == 0) && std::regex_match(s, b64_regex))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid base 64 value",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid base 64 value", value));
} else if (format == "uri") { } else if (format == "uri") {
try { try {
Poco::URI uri(value); Poco::URI uri(value);
return true; return true;
} catch (...) { } catch (...) {
} }
if(results) results->pushError(context,fmt::format("{} is not a valid URL",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid URL", value));
} else if (format == "uc-portrange") { } else if (format == "uc-portrange") {
try { try {
if (IsPortRangeIsValid(value)) if (IsPortRangeIsValid(value))
return true; return true;
} catch (...) { } catch (...) {
} }
if(results) results->pushError(context,fmt::format("{} is not a valid post range",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid post range", value));
} else if (format == "ip") { } else if (format == "ip") {
if (IsIP(value)) if (IsIP(value))
return true; return true;
if(results) results->pushError(context,fmt::format("{} is not a valid IP address",value)); if (results)
results->pushError(context, fmt::format("{} is not a valid IP address", value));
} }
return true; return true;
} }
@@ -3304,9 +3448,7 @@ namespace OpenWifi {
return 0; return 0;
} }
void ConfigurationValidator::Stop() { void ConfigurationValidator::Stop() {}
}
bool ConfigurationValidator::SetSchema(const std::string &SchemaStr) { bool ConfigurationValidator::SetSchema(const std::string &SchemaStr) {
try { try {
@@ -3350,21 +3492,22 @@ namespace OpenWifi {
schema_file << input.rdbuf(); schema_file << input.rdbuf();
input.close(); input.close();
if (SetSchema(schema_file.str())) { if (SetSchema(schema_file.str())) {
poco_information(Logger(), poco_information(
"Using uCentral data model validation schema from local file."); Logger(), "Using uCentral data model validation schema from local file.");
return; return;
} }
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} catch (...) { } catch (...) {
} }
SetSchema(DefaultUCentralSchema); SetSchema(DefaultUCentralSchema);
poco_information(Logger(),"Using uCentral data model validation schema from built-in default."); poco_information(Logger(),
"Using uCentral data model validation schema from built-in default.");
} }
bool ConfigurationValidator::Validate(const std::string &C, std::vector<std::string> &Errors, bool Strict) { bool ConfigurationValidator::Validate(const std::string &C, std::vector<std::string> &Errors,
bool Strict) {
if (Working_) { if (Working_) {
try { try {
Poco::JSON::Parser P; Poco::JSON::Parser P;
@@ -3382,7 +3525,8 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (const std::exception &E) { } catch (const std::exception &E) {
Logger().warning(fmt::format("Error wile validating a configuration (1): {}", E.what())); Logger().warning(
fmt::format("Error wile validating a configuration (1): {}", E.what()));
} catch (...) { } catch (...) {
Logger().warning("Error wile validating a configuration (2)"); Logger().warning("Error wile validating a configuration (2)");
} }
@@ -3398,4 +3542,4 @@ namespace OpenWifi {
Init(); Init();
} }
} } // namespace OpenWifi

View File

@@ -7,17 +7,16 @@
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include <valijson/adapters/poco_json_adapter.hpp> #include <valijson/adapters/poco_json_adapter.hpp>
#include <valijson/utils/poco_json_utils.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validator.hpp>
#include <valijson/constraints/constraint.hpp> #include <valijson/constraints/constraint.hpp>
#include <valijson/constraints/constraint_visitor.hpp> #include <valijson/constraints/constraint_visitor.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/utils/poco_json_utils.hpp>
#include <valijson/validator.hpp>
namespace OpenWifi { namespace OpenWifi {
class ConfigurationValidator : public SubSystemServer { class ConfigurationValidator : public SubSystemServer {
public: public:
static auto instance() { static auto instance() {
static auto instance_ = new ConfigurationValidator; static auto instance_ = new ConfigurationValidator;
return instance_; return instance_;
@@ -38,12 +37,13 @@ namespace OpenWifi {
Poco::JSON::Object::Ptr SchemaDocPtr_; Poco::JSON::Object::Ptr SchemaDocPtr_;
bool SetSchema(const std::string &SchemaStr); bool SetSchema(const std::string &SchemaStr);
ConfigurationValidator(): ConfigurationValidator()
SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") { : SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {}
}
}; };
inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); } inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error, bool strict) { return ConfigurationValidator::instance()->Validate(C, Error, strict); } inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error,
bool strict) {
return ConfigurationValidator::instance()->Validate(C, Error, strict);
} }
} // namespace OpenWifi

View File

@@ -4,9 +4,9 @@
#pragma once #pragma once
#include <vector>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
namespace OpenWifi { namespace OpenWifi {
@@ -264,8 +264,6 @@ namespace OpenWifi {
{.code = "EH", .name = "Western Sahara"}, {.code = "EH", .name = "Western Sahara"},
{.code = "YE", .name = "Yemen"}, {.code = "YE", .name = "Yemen"},
{.code = "ZM", .name = "Zambia"}, {.code = "ZM", .name = "Zambia"},
{ .code= "ZW", .name= "Zimbabwe" } {.code = "ZW", .name = "Zimbabwe"}};
};
}
} // namespace OpenWifi

View File

@@ -4,29 +4,30 @@
#include "framework/EventBusManager.h" #include "framework/EventBusManager.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/utils.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
EventBusManager::EventBusManager(Poco::Logger &L) : EventBusManager::EventBusManager(Poco::Logger &L) : Logger_(L) {}
Logger_(L) {
}
void EventBusManager::run() { void EventBusManager::run() {
Running_ = true; Running_ = true;
Utils::SetThreadName("fmwk:EventMgr"); Utils::SetThreadName("fmwk:EventMgr");
auto Msg = MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN); auto Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroServicePrivateEndPoint(),Msg, false); KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
false);
while (Running_) { while (Running_) {
Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer()); Poco::Thread::trySleep((unsigned long)MicroServiceDaemonBusTimer());
if (!Running_) if (!Running_)
break; break;
Msg = MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE); Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroServicePrivateEndPoint(),Msg, false); KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(),
Msg, false);
} }
Msg = MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE); Msg = std::make_shared<std::string>(MicroServiceMakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE));
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroServicePrivateEndPoint(),Msg, false); KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroServicePrivateEndPoint(), Msg,
false);
}; };
void EventBusManager::Start() { void EventBusManager::Start() {

View File

@@ -4,8 +4,8 @@
#pragma once #pragma once
#include "Poco/Runnable.h"
#include "Poco/Logger.h" #include "Poco/Logger.h"
#include "Poco/Runnable.h"
#include "Poco/Thread.h" #include "Poco/Thread.h"
namespace OpenWifi { namespace OpenWifi {
@@ -25,4 +25,3 @@ namespace OpenWifi {
}; };
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -4,50 +4,54 @@
#include "KafkaManager.h" #include "KafkaManager.h"
#include "framework/MicroServiceFuncs.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
void KafkaLoggerFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int level, const std::string & facility, const std::string &message) { void KafkaLoggerFun([[maybe_unused]] cppkafka::KafkaHandleBase &handle, int level,
const std::string &facility, const std::string &message) {
switch ((cppkafka::LogLevel)level) { switch ((cppkafka::LogLevel)level) {
case cppkafka::LogLevel::LogNotice: { case cppkafka::LogLevel::LogNotice: {
poco_notice(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_notice(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
case cppkafka::LogLevel::LogDebug: { case cppkafka::LogLevel::LogDebug: {
poco_debug(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_debug(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
case cppkafka::LogLevel::LogInfo: { case cppkafka::LogLevel::LogInfo: {
poco_information(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_information(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
case cppkafka::LogLevel::LogWarning: { case cppkafka::LogLevel::LogWarning: {
poco_warning(KafkaManager()->Logger(), fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_warning(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
case cppkafka::LogLevel::LogAlert: case cppkafka::LogLevel::LogAlert:
case cppkafka::LogLevel::LogCrit: { case cppkafka::LogLevel::LogCrit: {
poco_critical(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_critical(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
case cppkafka::LogLevel::LogErr: case cppkafka::LogLevel::LogErr:
case cppkafka::LogLevel::LogEmerg: case cppkafka::LogLevel::LogEmerg:
default: { default: {
poco_error(KafkaManager()->Logger(),fmt::format("kafka-log: facility: {} message: {}",facility, message)); poco_error(KafkaManager()->Logger(),
} fmt::format("kafka-log: facility: {} message: {}", facility, message));
break; } break;
} }
} }
inline void KafkaErrorFun([[maybe_unused]] cppkafka::KafkaHandleBase & handle, int error, const std::string &reason) { inline void KafkaErrorFun([[maybe_unused]] cppkafka::KafkaHandleBase &handle, int error,
poco_error(KafkaManager()->Logger(),fmt::format("kafka-error: {}, reason: {}", error, reason)); const std::string &reason) {
poco_error(KafkaManager()->Logger(),
fmt::format("kafka-error: {}, reason: {}", error, reason));
} }
inline void AddKafkaSecurity(cppkafka::Configuration &Config) { inline void AddKafkaSecurity(cppkafka::Configuration &Config) {
auto CA = MicroServiceConfigGetString("openwifi.kafka.ssl.ca.location", ""); auto CA = MicroServiceConfigGetString("openwifi.kafka.ssl.ca.location", "");
auto Certificate = MicroServiceConfigGetString("openwifi.kafka.ssl.certificate.location",""); auto Certificate =
MicroServiceConfigGetString("openwifi.kafka.ssl.certificate.location", "");
auto Key = MicroServiceConfigGetString("openwifi.kafka.ssl.key.location", ""); auto Key = MicroServiceConfigGetString("openwifi.kafka.ssl.key.location", "");
auto Password = MicroServiceConfigGetString("openwifi.kafka.ssl.key.password", ""); auto Password = MicroServiceConfigGetString("openwifi.kafka.ssl.key.password", "");
@@ -61,29 +65,29 @@ namespace OpenWifi {
Config.set("ssl.key.password", Password); Config.set("ssl.key.password", Password);
} }
void KafkaManager::initialize(Poco::Util::Application &self) { void KafkaManager::initialize(Poco::Util::Application &self) {
SubSystemServer::initialize(self); SubSystemServer::initialize(self);
KafkaEnabled_ = MicroServiceConfigGetBool("openwifi.kafka.enable", false); KafkaEnabled_ = MicroServiceConfigGetBool("openwifi.kafka.enable", false);
} }
inline void KafkaProducer::run() { inline void KafkaProducer::run() {
Poco::Logger &Logger_ = Poco::Logger::create("KAFKA-PRODUCER", KafkaManager()->Logger().getChannel()); Poco::Logger &Logger_ =
Poco::Logger::create("KAFKA-PRODUCER", KafkaManager()->Logger().getChannel());
poco_information(Logger_, "Starting..."); poco_information(Logger_, "Starting...");
Utils::SetThreadName("Kafka:Prod"); Utils::SetThreadName("Kafka:Prod");
cppkafka::Configuration Config({ cppkafka::Configuration Config(
{ "client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "") }, {{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
{ "metadata.broker.list", MicroServiceConfigGetString("openwifi.kafka.brokerlist", "") } {"metadata.broker.list",
}); MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}});
AddKafkaSecurity(Config); AddKafkaSecurity(Config);
Config.set_log_callback(KafkaLoggerFun); Config.set_log_callback(KafkaLoggerFun);
Config.set_error_callback(KafkaErrorFun); Config.set_error_callback(KafkaErrorFun);
KafkaManager()->SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" + KafkaManager()->SystemInfoWrapper_ =
std::to_string(MicroServiceID()) + R"lit({ "system" : { "id" : )lit" + std::to_string(MicroServiceID()) +
R"lit( , "host" : ")lit" + MicroServicePrivateEndPoint() + R"lit( , "host" : ")lit" + MicroServicePrivateEndPoint() +
R"lit(" } , "payload" : )lit"; R"lit(" } , "payload" : )lit";
@@ -95,11 +99,13 @@ namespace OpenWifi {
try { try {
auto Msg = dynamic_cast<KafkaMessage *>(Note.get()); auto Msg = dynamic_cast<KafkaMessage *>(Note.get());
if (Msg != nullptr) { if (Msg != nullptr) {
Producer.produce( Producer.produce(cppkafka::MessageBuilder(Msg->Topic())
cppkafka::MessageBuilder(Msg->Topic()).key(Msg->Key()).payload(Msg->Payload())); .key(Msg->Key())
.payload(Msg->Payload()));
} }
} catch (const cppkafka::HandleException &E) { } catch (const cppkafka::HandleException &E) {
poco_warning(Logger_,fmt::format("Caught a Kafka exception (producer): {}", E.what())); poco_warning(Logger_,
fmt::format("Caught a Kafka exception (producer): {}", E.what()));
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
} catch (...) { } catch (...) {
@@ -113,27 +119,25 @@ namespace OpenWifi {
inline void KafkaConsumer::run() { inline void KafkaConsumer::run() {
Utils::SetThreadName("Kafka:Cons"); Utils::SetThreadName("Kafka:Cons");
Poco::Logger &Logger_ = Poco::Logger::create("KAFKA-CONSUMER", KafkaManager()->Logger().getChannel()); Poco::Logger &Logger_ =
Poco::Logger::create("KAFKA-CONSUMER", KafkaManager()->Logger().getChannel());
poco_information(Logger_, "Starting..."); poco_information(Logger_, "Starting...");
cppkafka::Configuration Config({ cppkafka::Configuration Config(
{ "client.id", MicroServiceConfigGetString("openwifi.kafka.client.id","") }, {{"client.id", MicroServiceConfigGetString("openwifi.kafka.client.id", "")},
{"metadata.broker.list", MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")}, {"metadata.broker.list", MicroServiceConfigGetString("openwifi.kafka.brokerlist", "")},
{"group.id", MicroServiceConfigGetString("openwifi.kafka.group.id", "")}, {"group.id", MicroServiceConfigGetString("openwifi.kafka.group.id", "")},
{"enable.auto.commit", MicroServiceConfigGetBool("openwifi.kafka.auto.commit", false)}, {"enable.auto.commit", MicroServiceConfigGetBool("openwifi.kafka.auto.commit", false)},
{"auto.offset.reset", "latest"}, {"auto.offset.reset", "latest"},
{ "enable.partition.eof", false } {"enable.partition.eof", false}});
});
AddKafkaSecurity(Config); AddKafkaSecurity(Config);
Config.set_log_callback(KafkaLoggerFun); Config.set_log_callback(KafkaLoggerFun);
Config.set_error_callback(KafkaErrorFun); Config.set_error_callback(KafkaErrorFun);
cppkafka::TopicConfiguration topic_config = { cppkafka::TopicConfiguration topic_config = {{"auto.offset.reset", "smallest"}};
{ "auto.offset.reset", "smallest" }
};
// Now configure it to be the default topic config // Now configure it to be the default topic config
Config.set_default_topic_configuration(topic_config); Config.set_default_topic_configuration(topic_config);
@@ -162,24 +166,27 @@ namespace OpenWifi {
Running_ = true; Running_ = true;
while (Running_) { while (Running_) {
try { try {
std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(100)); std::vector<cppkafka::Message> MsgVec =
Consumer.poll_batch(BatchSize, std::chrono::milliseconds(100));
for (auto const &Msg : MsgVec) { for (auto const &Msg : MsgVec) {
if (!Msg) if (!Msg)
continue; continue;
if (Msg.get_error()) { if (Msg.get_error()) {
if (!Msg.is_eof()) { if (!Msg.is_eof()) {
poco_error(Logger_,fmt::format("Error: {}", Msg.get_error().to_string())); poco_error(Logger_,
fmt::format("Error: {}", Msg.get_error().to_string()));
} }
if (!AutoCommit) if (!AutoCommit)
Consumer.async_commit(Msg); Consumer.async_commit(Msg);
continue; continue;
} }
KafkaManager()->Dispatch(Msg.get_topic(), Msg.get_key(),Msg.get_payload() ); KafkaManager()->Dispatch(Msg.get_topic().c_str(), Msg.get_key(), std::make_shared<std::string>(Msg.get_payload()));
if (!AutoCommit) if (!AutoCommit)
Consumer.async_commit(Msg); Consumer.async_commit(Msg);
} }
} catch (const cppkafka::HandleException &E) { } catch (const cppkafka::HandleException &E) {
poco_warning(Logger_,fmt::format("Caught a Kafka exception (consumer): {}", E.what())); poco_warning(Logger_,
fmt::format("Caught a Kafka exception (consumer): {}", E.what()));
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
} catch (...) { } catch (...) {
@@ -205,7 +212,8 @@ namespace OpenWifi {
} }
} }
void KafkaProducer::Produce(const std::string &Topic, const std::string &Key, const std::string &Payload) { void KafkaProducer::Produce(const char *Topic, const std::string &Key,
const std::shared_ptr<std::string> Payload) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Queue_.enqueueNotification(new KafkaMessage(Topic, Key, Payload)); Queue_.enqueueNotification(new KafkaMessage(Topic, Key, Payload));
} }
@@ -240,7 +248,8 @@ namespace OpenWifi {
} }
} }
auto KafkaDispatcher::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) { auto KafkaDispatcher::RegisterTopicWatcher(const std::string &Topic,
Types::TopicNotifyFunction &F) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto It = Notifiers_.find(Topic); auto It = Notifiers_.find(Topic);
if (It == Notifiers_.end()) { if (It == Notifiers_.end()) {
@@ -266,7 +275,8 @@ namespace OpenWifi {
} }
} }
void KafkaDispatcher::Dispatch(const std::string &Topic, const std::string &Key, const std::string &Payload) { void KafkaDispatcher::Dispatch(const char *Topic, const std::string &Key,
const std::shared_ptr<std::string> Payload) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto It = Notifiers_.find(Topic); auto It = Notifiers_.find(Topic);
if (It != Notifiers_.end()) { if (It != Notifiers_.end()) {
@@ -275,7 +285,8 @@ namespace OpenWifi {
} }
void KafkaDispatcher::run() { void KafkaDispatcher::run() {
Poco::Logger &Logger_ = Poco::Logger::create("KAFKA-DISPATCHER", KafkaManager()->Logger().getChannel()); Poco::Logger &Logger_ =
Poco::Logger::create("KAFKA-DISPATCHER", KafkaManager()->Logger().getChannel());
poco_information(Logger_, "Starting..."); poco_information(Logger_, "Starting...");
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification()); Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
Utils::SetThreadName("kafka:dispatch"); Utils::SetThreadName("kafka:dispatch");
@@ -301,7 +312,6 @@ namespace OpenWifi {
T.push_back(TopicName); T.push_back(TopicName);
} }
int KafkaManager::Start() { int KafkaManager::Start() {
if (!KafkaEnabled_) if (!KafkaEnabled_)
return 0; return 0;
@@ -322,21 +332,25 @@ namespace OpenWifi {
} }
} }
void KafkaManager::PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage ) { void KafkaManager::PostMessage(const char *topic, const std::string &key,
const std::shared_ptr<std::string> PayLoad, bool WrapMessage) {
if (KafkaEnabled_) { if (KafkaEnabled_) {
ProducerThr_.Produce(topic, key, WrapMessage ? WrapSystemId(PayLoad) : PayLoad); ProducerThr_.Produce(topic, key, WrapMessage ? WrapSystemId(PayLoad) : PayLoad);
} }
} }
void KafkaManager::Dispatch(const std::string &Topic, const std::string & Key, const std::string &Payload) { void KafkaManager::Dispatch(const char *Topic, const std::string &Key,
const std::shared_ptr<std::string> Payload) {
Dispatcher_.Dispatch(Topic, Key, Payload); Dispatcher_.Dispatch(Topic, Key, Payload);
} }
[[nodiscard]] std::string KafkaManager::WrapSystemId(const std::string & PayLoad) { [[nodiscard]] const std::shared_ptr<std::string> KafkaManager::WrapSystemId(const std::shared_ptr<std::string> PayLoad) {
return SystemInfoWrapper_ + PayLoad + "}"; *PayLoad = SystemInfoWrapper_ + *PayLoad + "}";
return PayLoad;
} }
uint64_t KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) { uint64_t KafkaManager::RegisterTopicWatcher(const std::string &Topic,
Types::TopicNotifyFunction &F) {
if (KafkaEnabled_) { if (KafkaEnabled_) {
return Dispatcher_.RegisterTopicWatcher(Topic, F); return Dispatcher_.RegisterTopicWatcher(Topic, F);
} else { } else {
@@ -350,16 +364,16 @@ namespace OpenWifi {
} }
} }
void KafkaManager::Topics(std::vector<std::string> &T) { void KafkaManager::Topics(std::vector<std::string> &T) { Dispatcher_.Topics(T); }
Dispatcher_.Topics(T);
}
void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList &partitions) { void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList &partitions) {
poco_information(Logger(),fmt::format("Partition assigned: {}...", partitions.front().get_partition())); poco_information(
Logger(), fmt::format("Partition assigned: {}...", partitions.front().get_partition()));
} }
void KafkaManager::PartitionRevocation(const cppkafka::TopicPartitionList &partitions) { void KafkaManager::PartitionRevocation(const cppkafka::TopicPartitionList &partitions) {
poco_information(Logger(),fmt::format("Partition revocation: {}...",partitions.front().get_partition())); poco_information(Logger(), fmt::format("Partition revocation: {}...",
partitions.front().get_partition()));
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -7,10 +7,10 @@
#include "Poco/Notification.h" #include "Poco/Notification.h"
#include "Poco/NotificationQueue.h" #include "Poco/NotificationQueue.h"
#include "framework/SubSystemServer.h"
#include "framework/OpenWifiTypes.h"
#include "framework/utils.h"
#include "framework/KafkaTopics.h" #include "framework/KafkaTopics.h"
#include "framework/OpenWifiTypes.h"
#include "framework/SubSystemServer.h"
#include "framework/utils.h"
#include "cppkafka/cppkafka.h" #include "cppkafka/cppkafka.h"
@@ -18,18 +18,17 @@ namespace OpenWifi {
class KafkaMessage : public Poco::Notification { class KafkaMessage : public Poco::Notification {
public: public:
KafkaMessage( const std::string &Topic, const std::string &Key, const std::string & Payload) : KafkaMessage(const char * Topic, const std::string &Key, const std::shared_ptr<std::string> Payload)
Topic_(Topic), Key_(Key), Payload_(Payload) { : Topic_(Topic), Key_(Key), Payload_(std::move(Payload)) {}
}
inline const std::string & Topic() { return Topic_; } inline const char * Topic() { return Topic_; }
inline const std::string &Key() { return Key_; } inline const std::string &Key() { return Key_; }
inline const std::string & Payload() { return Payload_; } inline const std::string &Payload() { return *Payload_; }
private: private:
std::string Topic_; const char *Topic_;
std::string Key_; std::string Key_;
std::string Payload_; std::shared_ptr<std::string> Payload_;
}; };
class KafkaProducer : public Poco::Runnable { class KafkaProducer : public Poco::Runnable {
@@ -37,7 +36,7 @@ namespace OpenWifi {
void run() override; void run() override;
void Start(); void Start();
void Stop(); void Stop();
void Produce(const std::string &Topic, const std::string &Key, const std::string &Payload); void Produce(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload);
private: private:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
@@ -64,7 +63,7 @@ namespace OpenWifi {
void Stop(); void Stop();
auto RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F); auto RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void UnregisterTopicWatcher(const std::string &Topic, int Id); void UnregisterTopicWatcher(const std::string &Topic, int Id);
void Dispatch(const std::string &Topic, const std::string &Key, const std::string &Payload); void Dispatch(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload);
void run() override; void run() override;
void Topics(std::vector<std::string> &T); void Topics(std::vector<std::string> &T);
@@ -79,7 +78,6 @@ namespace OpenWifi {
class KafkaManager : public SubSystemServer { class KafkaManager : public SubSystemServer {
public: public:
friend class KafkaConsumer; friend class KafkaConsumer;
friend class KafkaProducer; friend class KafkaProducer;
@@ -93,9 +91,10 @@ namespace OpenWifi {
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage = true ); void PostMessage(const char *topic, const std::string &key,
void Dispatch(const std::string &Topic, const std::string & Key, const std::string &Payload); const std::shared_ptr<std::string> PayLoad, bool WrapMessage = true);
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad); void Dispatch(const char *Topic, const std::string &Key, const std::shared_ptr<std::string> Payload);
[[nodiscard]] const std::shared_ptr<std::string> WrapSystemId(const std::shared_ptr<std::string> PayLoad);
[[nodiscard]] inline bool Enabled() const { return KafkaEnabled_; } [[nodiscard]] inline bool Enabled() const { return KafkaEnabled_; }
uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F); uint64_t RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F);
void UnregisterTopicWatcher(const std::string &Topic, uint64_t Id); void UnregisterTopicWatcher(const std::string &Topic, uint64_t Id);
@@ -111,12 +110,9 @@ namespace OpenWifi {
void PartitionAssignment(const cppkafka::TopicPartitionList &partitions); void PartitionAssignment(const cppkafka::TopicPartitionList &partitions);
void PartitionRevocation(const cppkafka::TopicPartitionList &partitions); void PartitionRevocation(const cppkafka::TopicPartitionList &partitions);
KafkaManager() noexcept: KafkaManager() noexcept : SubSystemServer("KafkaManager", "KAFKA-SVR", "openwifi.kafka") {}
SubSystemServer("KafkaManager", "KAFKA-SVR", "openwifi.kafka") {
}
}; };
inline auto KafkaManager() { return KafkaManager::instance(); } inline auto KafkaManager() { return KafkaManager::instance(); }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -10,33 +10,32 @@
#include <string> #include <string>
namespace OpenWifi::KafkaTopics { namespace OpenWifi::KafkaTopics {
static const std::string HEALTHCHECK{"healthcheck"}; inline const char * HEALTHCHECK = "healthcheck";
static const std::string STATE{"state"}; inline const char * STATE = "state";
static const std::string CONNECTION{"connection"}; inline const char * CONNECTION = "connection";
static const std::string WIFISCAN{"wifiscan"}; inline const char * WIFISCAN = "wifiscan";
static const std::string ALERTS{"alerts"}; inline const char * ALERTS = "alerts";
static const std::string COMMAND{"command"}; inline const char * COMMAND = "command";
static const std::string SERVICE_EVENTS{"service_events"}; inline const char * SERVICE_EVENTS = "service_events";
static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"}; inline const char * DEVICE_EVENT_QUEUE = "device_event_queue";
static const std::string DEVICE_TELEMETRY{"device_telemetry"}; inline const char * DEVICE_TELEMETRY = "device_telemetry";
static const std::string PROVISIONING_CHANGE{"provisioning_change"}; inline const char * PROVISIONING_CHANGE = "provisioning_change";
namespace ServiceEvents { namespace ServiceEvents {
static const std::string EVENT_JOIN{"join"}; inline const char * EVENT_JOIN = "join";
static const std::string EVENT_LEAVE{"leave"}; inline const char * EVENT_LEAVE = "leave";
static const std::string EVENT_KEEP_ALIVE{"keep-alive"}; inline const char * EVENT_KEEP_ALIVE = "keep-alive";
static const std::string EVENT_REMOVE_TOKEN{"remove-token"}; inline const char * EVENT_REMOVE_TOKEN = "remove-token";
namespace Fields { namespace Fields {
static const std::string EVENT{"event"}; inline const char * EVENT = "event";
static const std::string ID{"id"}; inline const char * ID = "id";
static const std::string TYPE{"type"}; inline const char * TYPE = "type";
static const std::string PUBLIC{"publicEndPoint"}; inline const char * PUBLIC = "publicEndPoint";
static const std::string PRIVATE{"privateEndPoint"}; inline const char * PRIVATE = "privateEndPoint";
static const std::string KEY{"key"}; inline const char * KEY = "key";
static const std::string VRSN{"version"}; inline const char * VRSN = "version";
static const std::string TOKEN{"token"}; inline const char * TOKEN = "token";
} } // namespace Fields
} } // namespace ServiceEvents
} } // namespace OpenWifi::KafkaTopics

View File

@@ -2,40 +2,39 @@
// Created by stephane bourque on 2022-10-26. // Created by stephane bourque on 2022-10-26.
// //
#include "Poco/FileChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/PatternFormatter.h"
#include "Poco/FormattingChannel.h"
#include "Poco/AsyncChannel.h" #include "Poco/AsyncChannel.h"
#include "Poco/NullChannel.h" #include "Poco/ConsoleChannel.h"
#include "Poco/SplitterChannel.h" #include "Poco/FileChannel.h"
#include "Poco/Net/HTTPStreamFactory.h" #include "Poco/FormattingChannel.h"
#include "Poco/Net/HTTPSStreamFactory.h" #include "Poco/JSON/JSONException.h"
#include "Poco/Net/FTPSStreamFactory.h" #include "Poco/Net/FTPSStreamFactory.h"
#include "Poco/Net/FTPStreamFactory.h" #include "Poco/Net/FTPStreamFactory.h"
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/SSLManager.h" #include "Poco/Net/SSLManager.h"
#include "Poco/JSON/JSONException.h" #include "Poco/NullChannel.h"
#include "Poco/PatternFormatter.h"
#include "Poco/SplitterChannel.h"
#include "framework/ALBserver.h"
#include "framework/AuthClient.h"
#include "framework/KafkaManager.h"
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "framework/MicroServiceErrorHandler.h" #include "framework/MicroServiceErrorHandler.h"
#include "framework/UI_WebSocketClientServer.h"
#include "framework/MicroServiceNames.h" #include "framework/MicroServiceNames.h"
#include "framework/AuthClient.h"
#include "framework/ALBserver.h"
#include "framework/KafkaManager.h"
#include "framework/RESTAPI_GenericServerAccounting.h"
#include "framework/RESTAPI_ExtServer.h" #include "framework/RESTAPI_ExtServer.h"
#include "framework/RESTAPI_GenericServerAccounting.h"
#include "framework/RESTAPI_IntServer.h" #include "framework/RESTAPI_IntServer.h"
#include "framework/utils.h" #include "framework/UI_WebSocketClientServer.h"
#include "framework/WebSocketLogger.h" #include "framework/WebSocketLogger.h"
#include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
void MicroService::Exit(int Reason) { void MicroService::Exit(int Reason) { std::exit(Reason); }
std::exit(Reason);
}
void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key, const std::string & Payload) { void MicroService::BusMessageReceived([[maybe_unused]] const std::string &Key,
const std::string &Payload) {
std::lock_guard G(InfraMutex_); std::lock_guard G(InfraMutex_);
try { try {
Poco::JSON::Parser P; Poco::JSON::Parser P;
@@ -54,21 +53,45 @@ namespace OpenWifi {
Object->has(KafkaTopics::ServiceEvents::Fields::PRIVATE) && Object->has(KafkaTopics::ServiceEvents::Fields::PRIVATE) &&
Object->has(KafkaTopics::ServiceEvents::Fields::VRSN) && Object->has(KafkaTopics::ServiceEvents::Fields::VRSN) &&
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) { Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
auto PrivateEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(); auto PrivateEndPoint =
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE && Services_.find(PrivateEndPoint) != Services_.end()) { Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString();
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE &&
Services_.find(PrivateEndPoint) != Services_.end()) {
Services_[PrivateEndPoint].LastUpdate = Utils::Now(); Services_[PrivateEndPoint].LastUpdate = Utils::Now();
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) { } else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
Services_.erase(PrivateEndPoint); Services_.erase(PrivateEndPoint);
poco_debug(logger(),fmt::format("Service {} ID={} leaving system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID)); poco_debug(
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN || Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) { logger(),
poco_debug(logger(),fmt::format("Service {} ID={} joining system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID)); fmt::format(
"Service {} ID={} leaving system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN ||
Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
poco_debug(
logger(),
fmt::format(
"Service {} ID={} joining system.",
Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
ID));
Services_[PrivateEndPoint] = Types::MicroServiceMeta{ Services_[PrivateEndPoint] = Types::MicroServiceMeta{
.Id = ID, .Id = ID,
.Type = Poco::toLower(Object->get(KafkaTopics::ServiceEvents::Fields::TYPE).toString()), .Type = Poco::toLower(
.PrivateEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(), Object->get(KafkaTopics::ServiceEvents::Fields::TYPE)
.PublicEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PUBLIC).toString(), .toString()),
.AccessKey = Object->get(KafkaTopics::ServiceEvents::Fields::KEY).toString(), .PrivateEndPoint =
.Version = Object->get(KafkaTopics::ServiceEvents::Fields::VRSN).toString(), Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE)
.toString(),
.PublicEndPoint =
Object->get(KafkaTopics::ServiceEvents::Fields::PUBLIC)
.toString(),
.AccessKey =
Object->get(KafkaTopics::ServiceEvents::Fields::KEY)
.toString(),
.Version = Object->get(KafkaTopics::ServiceEvents::Fields::VRSN)
.toString(),
.LastUpdate = Utils::Now()}; .LastUpdate = Utils::Now()};
std::string SvcList; std::string SvcList;
@@ -78,21 +101,30 @@ namespace OpenWifi {
else else
SvcList += ", " + Svc.second.Type; SvcList += ", " + Svc.second.Type;
} }
poco_information(logger(),fmt::format("Current list of microservices: {}", SvcList)); poco_information(
logger(),
fmt::format("Current list of microservices: {}", SvcList));
} }
} else { } else {
poco_error(logger(),fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",Event)); poco_error(
logger(),
fmt::format("KAFKA-MSG: invalid event '{}', missing a field.",
Event));
} }
} else if (Event == KafkaTopics::ServiceEvents::EVENT_REMOVE_TOKEN) { } else if (Event == KafkaTopics::ServiceEvents::EVENT_REMOVE_TOKEN) {
if (Object->has(KafkaTopics::ServiceEvents::Fields::TOKEN)) { if (Object->has(KafkaTopics::ServiceEvents::Fields::TOKEN)) {
#ifndef TIP_SECURITY_SERVICE #ifndef TIP_SECURITY_SERVICE
AuthClient()->RemovedCachedToken(Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString()); AuthClient()->RemovedCachedToken(
Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
#endif #endif
} else { } else {
poco_error(logger(),fmt::format("KAFKA-MSG: invalid event '{}', missing token",Event)); poco_error(
logger(),
fmt::format("KAFKA-MSG: invalid event '{}', missing token", Event));
} }
} else { } else {
poco_error(logger(),fmt::format("Unknown Event: {} Source: {}", Event, ID)); poco_error(logger(),
fmt::format("Unknown Event: {} Source: {}", Event, ID));
} }
} }
} else { } else {
@@ -137,14 +169,16 @@ namespace OpenWifi {
void MicroService::LoadConfigurationFile() { void MicroService::LoadConfigurationFile() {
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, "."); std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR, ".");
ConfigFileName_ = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_; ConfigFileName_ =
ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
Poco::Path ConfigFile(ConfigFileName_); Poco::Path ConfigFile(ConfigFileName_);
if(!ConfigFile.isFile()) if (!ConfigFile.isFile()) {
{ std::cerr << DAEMON_APP_NAME << ": Configuration " << ConfigFile.toString()
std::cerr << DAEMON_APP_NAME << ": Configuration " << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR +
<< ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR " env variable the path of the " + DAEMON_PROPERTIES_FILENAME +
+ " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl; " file."
<< std::endl;
std::exit(Poco::Util::Application::EXIT_CONFIG); std::exit(Poco::Util::Application::EXIT_CONFIG);
} }
@@ -163,7 +197,8 @@ namespace OpenWifi {
std::string KeyFile = ConfigPath("openwifi.service.key", ""); std::string KeyFile = ConfigPath("openwifi.service.key", "");
if (!KeyFile.empty()) { if (!KeyFile.empty()) {
std::string KeyFilePassword = ConfigPath("openwifi.service.key.password", ""); std::string KeyFilePassword = ConfigPath("openwifi.service.key.password", "");
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword)); AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(
new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
Cipher_ = CipherFactory_.createCipher(*AppKey_); Cipher_ = CipherFactory_.createCipher(*AppKey_);
Signer_.setRSAKey(AppKey_); Signer_.setRSAKey(AppKey_);
Signer_.addAllAlgorithms(); Signer_.addAllAlgorithms();
@@ -188,11 +223,13 @@ namespace OpenWifi {
initialized = true; initialized = true;
LoadConfigurationFile(); LoadConfigurationFile();
auto LoggingDestination = MicroService::instance().ConfigGetString("logging.type", "file"); auto LoggingDestination =
auto LoggingFormat = MicroService::instance().ConfigGetString("logging.format", MicroService::instance().ConfigGetString("logging.type", "file");
"%Y-%m-%d %H:%M:%S.%i %s: [%p][thr:%I] %t"); auto LoggingFormat = MicroService::instance().ConfigGetString(
"logging.format", "%Y-%m-%d %H:%M:%S.%i %s: [%p][thr:%I] %t");
auto UseAsyncLogs_ = MicroService::instance().ConfigGetBool("logging.asynch", true); auto UseAsyncLogs_ = MicroService::instance().ConfigGetBool("logging.asynch", true);
auto DisableWebSocketLogging = MicroService::instance().ConfigGetBool("logging.websocket",false); auto DisableWebSocketLogging =
MicroService::instance().ConfigGetBool("logging.websocket", false);
if (LoggingDestination == "null") { if (LoggingDestination == "null") {
Poco::AutoPtr<Poco::NullChannel> DevNull(new Poco::NullChannel); Poco::AutoPtr<Poco::NullChannel> DevNull(new Poco::NullChannel);
@@ -206,10 +243,12 @@ namespace OpenWifi {
} else if (LoggingDestination == "syslog") { } else if (LoggingDestination == "syslog") {
SetSyslogLogs(UseAsyncLogs_, DisableWebSocketLogging, LoggingFormat); SetSyslogLogs(UseAsyncLogs_, DisableWebSocketLogging, LoggingFormat);
} else { } else {
SetFileLogs(UseAsyncLogs_, DisableWebSocketLogging, LoggingFormat, DAEMON_ROOT_ENV_VAR); SetFileLogs(UseAsyncLogs_, DisableWebSocketLogging, LoggingFormat,
DAEMON_ROOT_ENV_VAR);
} }
auto Level = Poco::Logger::parseLevel(MicroService::instance().ConfigGetString("logging.level", "debug")); auto Level = Poco::Logger::parseLevel(
MicroService::instance().ConfigGetString("logging.level", "debug"));
Poco::Logger::root().setLevel(Level); Poco::Logger::root().setLevel(Level);
if (!DisableWebSocketLogging) { if (!DisableWebSocketLogging) {
static const UI_WebSocketClientServer::NotificationTypeIdVec Notifications = { static const UI_WebSocketClientServer::NotificationTypeIdVec Notifications = {
@@ -219,12 +258,14 @@ namespace OpenWifi {
} }
} }
void MicroService::SetConsoleLogs(bool UseAsync, bool DisableWebSocketLogging, const std::string & FormatterPattern) { void MicroService::SetConsoleLogs(bool UseAsync, bool DisableWebSocketLogging,
const std::string &FormatterPattern) {
Poco::AutoPtr<Poco::ConsoleChannel> Console(new Poco::ConsoleChannel); Poco::AutoPtr<Poco::ConsoleChannel> Console(new Poco::ConsoleChannel);
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter); Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
Formatter->setProperty("pattern", FormatterPattern); Formatter->setProperty("pattern", FormatterPattern);
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(new Poco::FormattingChannel(Formatter, Console)); Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, Console));
if (DisableWebSocketLogging) { if (DisableWebSocketLogging) {
if (UseAsync) { if (UseAsync) {
@@ -245,15 +286,18 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter); Poco::Logger::root().setChannel(Splitter);
} }
} }
Poco::Logger::root().information(fmt::format("Enabled console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging)); Poco::Logger::root().information(fmt::format("Enabled console logs: asynch={} websocket={}",
UseAsync, DisableWebSocketLogging));
} }
void MicroService::SetColorConsoleLogs(bool UseAsync, bool DisableWebSocketLogging, const std::string & FormatterPattern) { void MicroService::SetColorConsoleLogs(bool UseAsync, bool DisableWebSocketLogging,
const std::string &FormatterPattern) {
Poco::AutoPtr<Poco::ColorConsoleChannel> Console(new Poco::ColorConsoleChannel); Poco::AutoPtr<Poco::ColorConsoleChannel> Console(new Poco::ColorConsoleChannel);
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter); Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
Formatter->setProperty("pattern", FormatterPattern); Formatter->setProperty("pattern", FormatterPattern);
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(new Poco::FormattingChannel(Formatter, Console)); Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, Console));
if (DisableWebSocketLogging) { if (DisableWebSocketLogging) {
if (UseAsync) { if (UseAsync) {
@@ -274,20 +318,28 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter); Poco::Logger::root().setChannel(Splitter);
} }
} }
Poco::Logger::root().information(fmt::format("Enabled color console logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging)); Poco::Logger::root().information(
fmt::format("Enabled color console logs: asynch={} websocket={}", UseAsync,
DisableWebSocketLogging));
} }
void MicroService::SetSQLLogs([[maybe_unused]] bool UseAsync,[[maybe_unused]] bool DisableWebSocketLogging,[[maybe_unused]] const std::string & FormatterPattern) { void MicroService::SetSQLLogs([[maybe_unused]] bool UseAsync,
//"CREATE TABLE T_POCO_LOG (Source VARCHAR, Name VARCHAR, ProcessId INTEGER, Thread VARCHAR, ThreadId INTEGER, Priority INTEGER, Text VARCHAR, DateTime DATE)" [[maybe_unused]] bool DisableWebSocketLogging,
[[maybe_unused]] const std::string &FormatterPattern) {
//"CREATE TABLE T_POCO_LOG (Source VARCHAR, Name VARCHAR, ProcessId INTEGER, Thread VARCHAR,
//ThreadId INTEGER, Priority INTEGER, Text VARCHAR, DateTime DATE)"
} }
void MicroService::SetSyslogLogs([[maybe_unused]] bool UseAsync,[[maybe_unused]] bool DisableWebSocketLogging,[[maybe_unused]] const std::string & FormatterPattern) { void MicroService::SetSyslogLogs([[maybe_unused]] bool UseAsync,
[[maybe_unused]] bool DisableWebSocketLogging,
[[maybe_unused]] const std::string &FormatterPattern) {}
} void MicroService::SetFileLogs(bool UseAsync, bool DisableWebSocketLogging,
const std::string &FormatterPattern,
void MicroService::SetFileLogs(bool UseAsync, bool DisableWebSocketLogging, const std::string & FormatterPattern, const std::string & root_env_var) { const std::string &root_env_var) {
std::string DefaultLogPath = fmt::format("${}/logs", root_env_var); std::string DefaultLogPath = fmt::format("${}/logs", root_env_var);
auto LoggingLocationDir = MicroService::instance().ConfigPath("logging.path", DefaultLogPath); auto LoggingLocationDir =
MicroService::instance().ConfigPath("logging.path", DefaultLogPath);
Poco::File LD(LoggingLocationDir); Poco::File LD(LoggingLocationDir);
try { try {
if (!LD.exists()) { if (!LD.exists()) {
@@ -306,7 +358,8 @@ namespace OpenWifi {
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter); Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
Formatter->setProperty("pattern", FormatterPattern); Formatter->setProperty("pattern", FormatterPattern);
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(new Poco::FormattingChannel(Formatter, FileChannel)); Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, FileChannel));
if (DisableWebSocketLogging) { if (DisableWebSocketLogging) {
if (UseAsync) { if (UseAsync) {
@@ -327,7 +380,8 @@ namespace OpenWifi {
Poco::Logger::root().setChannel(Splitter); Poco::Logger::root().setChannel(Splitter);
} }
} }
Poco::Logger::root().information(fmt::format("Enabled file logs: asynch={} websocket={}",UseAsync,DisableWebSocketLogging)); Poco::Logger::root().information(fmt::format("Enabled file logs: asynch={} websocket={}",
UseAsync, DisableWebSocketLogging));
} }
void DaemonPostInitialization(Poco::Util::Application &self); void DaemonPostInitialization(Poco::Util::Application &self);
@@ -371,7 +425,9 @@ namespace OpenWifi {
ServerApplication::initialize(self); ServerApplication::initialize(self);
DaemonPostInitialization(self); DaemonPostInitialization(self);
Types::TopicNotifyFunction F = [this](const std::string &Key,const std::string &Payload) { this->BusMessageReceived(Key, Payload); }; Types::TopicNotifyFunction F = [this](const std::string &Key, const std::string &Payload) {
this->BusMessageReceived(Key, Payload);
};
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F); KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
} }
@@ -392,58 +448,64 @@ namespace OpenWifi {
Poco::Util::Option("help", "", "display help information on command line arguments") Poco::Util::Option("help", "", "display help information on command line arguments")
.required(false) .required(false)
.repeatable(false) .repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleHelp))); .callback(
Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleHelp)));
options.addOption( options.addOption(Poco::Util::Option("file", "", "specify the configuration file")
Poco::Util::Option("file", "", "specify the configuration file")
.required(false) .required(false)
.repeatable(false) .repeatable(false)
.argument("file") .argument("file")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleConfig))); .callback(Poco::Util::OptionCallback<MicroService>(
this, &MicroService::handleConfig)));
options.addOption( options.addOption(Poco::Util::Option("debug", "", "to run in debug, set to true")
Poco::Util::Option("debug", "", "to run in debug, set to true")
.required(false) .required(false)
.repeatable(false) .repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleDebug))); .callback(Poco::Util::OptionCallback<MicroService>(
this, &MicroService::handleDebug)));
options.addOption( options.addOption(
Poco::Util::Option("logs", "", "specify the log directory and file (i.e. dir/file.log)") Poco::Util::Option("logs", "", "specify the log directory and file (i.e. dir/file.log)")
.required(false) .required(false)
.repeatable(false) .repeatable(false)
.argument("dir") .argument("dir")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleLogs))); .callback(
Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleLogs)));
options.addOption( options.addOption(Poco::Util::Option("version", "", "get the version and quit.")
Poco::Util::Option("version", "", "get the version and quit.")
.required(false) .required(false)
.repeatable(false) .repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleVersion))); .callback(Poco::Util::OptionCallback<MicroService>(
this, &MicroService::handleVersion)));
} }
void MicroService::handleHelp([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &value) { void MicroService::handleHelp([[maybe_unused]] const std::string &name,
[[maybe_unused]] const std::string &value) {
HelpRequested_ = true; HelpRequested_ = true;
displayHelp(); displayHelp();
stopOptionsProcessing(); stopOptionsProcessing();
} }
void MicroService::handleVersion([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &value) { void MicroService::handleVersion([[maybe_unused]] const std::string &name,
[[maybe_unused]] const std::string &value) {
HelpRequested_ = true; HelpRequested_ = true;
std::cout << Version() << std::endl; std::cout << Version() << std::endl;
stopOptionsProcessing(); stopOptionsProcessing();
} }
void MicroService::handleDebug([[maybe_unused]] const std::string &name, const std::string &value) { void MicroService::handleDebug([[maybe_unused]] const std::string &name,
const std::string &value) {
if (value == "true") if (value == "true")
DebugMode_ = true; DebugMode_ = true;
} }
void MicroService::handleLogs([[maybe_unused]] const std::string &name, const std::string &value) { void MicroService::handleLogs([[maybe_unused]] const std::string &name,
const std::string &value) {
LogDir_ = value; LogDir_ = value;
} }
void MicroService::handleConfig([[maybe_unused]] const std::string &name, const std::string &value) { void MicroService::handleConfig([[maybe_unused]] const std::string &name,
const std::string &value) {
ConfigFileName_ = value; ConfigFileName_ = value;
} }
@@ -466,7 +528,8 @@ namespace OpenWifi {
for (auto i : SubSystems_) { for (auto i : SubSystems_) {
i->Start(); i->Start();
} }
EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create("EventBusManager",Poco::Logger::root().getChannel(),Poco::Logger::root().getLevel())); EventBusManager_ = std::make_unique<EventBusManager>(Poco::Logger::create(
"EventBusManager", Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
EventBusManager_->Start(); EventBusManager_->Start();
} }
@@ -510,7 +573,8 @@ namespace OpenWifi {
return ss.str(); return ss.str();
} }
bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem,
const std::string &Level) {
try { try {
auto P = Poco::Logger::parseLevel(Level); auto P = Poco::Logger::parseLevel(Level);
auto Sub = Poco::toLower(SubSystem); auto Sub = Poco::toLower(SubSystem);
@@ -561,7 +625,8 @@ namespace OpenWifi {
} }
const Types::StringVec &MicroService::GetLogLevelNames() { const Types::StringVec &MicroService::GetLogLevelNames() {
static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" }; static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning",
"notice", "information", "debug", "trace"};
return LevelNames; return LevelNames;
} }
@@ -569,17 +634,13 @@ namespace OpenWifi {
return (uint64_t)config().getInt64(Key, Default); return (uint64_t)config().getInt64(Key, Default);
} }
uint64_t MicroService::ConfigGetInt(const std::string &Key) { uint64_t MicroService::ConfigGetInt(const std::string &Key) { return config().getInt(Key); }
return config().getInt(Key);
}
uint64_t MicroService::ConfigGetBool(const std::string &Key, bool Default) { uint64_t MicroService::ConfigGetBool(const std::string &Key, bool Default) {
return config().getBool(Key, Default); return config().getBool(Key, Default);
} }
uint64_t MicroService::ConfigGetBool(const std::string &Key) { uint64_t MicroService::ConfigGetBool(const std::string &Key) { return config().getBool(Key); }
return config().getBool(Key);
}
std::string MicroService::ConfigGetString(const std::string &Key, const std::string &Default) { std::string MicroService::ConfigGetString(const std::string &Key, const std::string &Default) {
return config().getString(Key, Default); return config().getString(Key, Default);
@@ -603,14 +664,16 @@ namespace OpenWifi {
if (NoBuiltInCrypto_) { if (NoBuiltInCrypto_) {
return S; return S;
} }
return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);; return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);
;
} }
std::string MicroService::Decrypt(const std::string &S) { std::string MicroService::Decrypt(const std::string &S) {
if (NoBuiltInCrypto_) { if (NoBuiltInCrypto_) {
return S; return S;
} }
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);; return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);
;
} }
std::string MicroService::MakeSystemEventMessage(const std::string &Type) const { std::string MicroService::MakeSystemEventMessage(const std::string &Type) const {
@@ -640,11 +703,11 @@ namespace OpenWifi {
void MicroService::SavePID() { void MicroService::SavePID() {
try { try {
std::ofstream O; std::ofstream O;
O.open(MicroService::instance().DataDir() + "/pidfile",std::ios::binary | std::ios::trunc); O.open(MicroService::instance().DataDir() + "/pidfile",
std::ios::binary | std::ios::trunc);
O << Poco::Process::id(); O << Poco::Process::id();
O.close(); O.close();
} catch (...) } catch (...) {
{
std::cout << "Could not save system ID" << std::endl; std::cout << "Could not save system ID" << std::endl;
} }
} }
@@ -687,7 +750,6 @@ namespace OpenWifi {
std::time_t now = std::chrono::system_clock::to_time_t(t); std::time_t now = std::chrono::system_clock::to_time_t(t);
of << Activity << " at " << std::ctime(&now); of << Activity << " at " << std::ctime(&now);
} catch (...) { } catch (...) {
} }
} }
} }
@@ -707,8 +769,7 @@ namespace OpenWifi {
if (F.exists()) if (F.exists())
F.remove(); F.remove();
} catch (...) { } catch (...) {
} }
} }
} } // namespace OpenWifi

View File

@@ -9,12 +9,11 @@
#pragma once #pragma once
#include <array> #include <array>
#include <iostream>
#include <vector>
#include <fstream>
#include <random>
#include <ctime> #include <ctime>
#include <fstream>
#include <iostream>
#include <random>
#include <vector>
// This must be defined for poco_debug and poco_trace macros to function. // This must be defined for poco_debug and poco_trace macros to function.
@@ -24,37 +23,37 @@
namespace OpenWifi { namespace OpenWifi {
inline uint64_t Now() { return std::time(nullptr); }; inline uint64_t Now() { return std::time(nullptr); };
} } // namespace OpenWifi
#include "Poco/Util/Application.h" #include "Poco/AutoPtr.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/Cipher.h" #include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/Environment.h"
#include "Poco/JSON/Object.h"
#include "Poco/JWT/Signer.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Process.h" #include "Poco/Process.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/HelpFormatter.h" #include "Poco/Util/HelpFormatter.h"
#include "Poco/JSON/Object.h" #include "Poco/Util/Option.h"
#include "Poco/AutoPtr.h" #include "Poco/Util/OptionSet.h"
#include "Poco/Util/PropertyFileConfiguration.h" #include "Poco/Util/PropertyFileConfiguration.h"
#include "Poco/JWT/Signer.h" #include "Poco/Util/ServerApplication.h"
#include "Poco/Environment.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "framework/EventBusManager.h"
#include "framework/SubSystemServer.h"
#include "framework/ow_constants.h" #include "framework/ow_constants.h"
#include "framework/utils.h" #include "framework/utils.h"
#include "framework/SubSystemServer.h"
#include "framework/EventBusManager.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h" #include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "cppkafka/cppkafka.h" #include "cppkafka/cppkafka.h"
#include "fmt/core.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
#include "ow_version.h" #include "ow_version.h"
#include "fmt/core.h"
#define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl; #define _OWDEBUG_ std::cout << __FILE__ << ":" << __LINE__ << std::endl;
// #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__)); // #define _OWDEBUG_ Logger().debug(Poco::format("%s: %lu",__FILE__,__LINE__));
@@ -63,19 +62,12 @@ namespace OpenWifi {
class MicroService : public Poco::Util::ServerApplication { class MicroService : public Poco::Util::ServerApplication {
public: public:
explicit MicroService( std::string PropFile, explicit MicroService(std::string PropFile, std::string RootEnv, std::string ConfigVar,
std::string RootEnv, std::string AppName, uint64_t BusTimer, SubSystemVec Subsystems)
std::string ConfigVar, : DAEMON_PROPERTIES_FILENAME(std::move(PropFile)),
std::string AppName, DAEMON_ROOT_ENV_VAR(std::move(RootEnv)), DAEMON_CONFIG_ENV_VAR(std::move(ConfigVar)),
uint64_t BusTimer, DAEMON_APP_NAME(std::move(AppName)), DAEMON_BUS_TIMER(BusTimer),
SubSystemVec Subsystems) : SubSystems_(std::move(Subsystems)), Logger_(Poco::Logger::get("FRAMEWORK")) {
DAEMON_PROPERTIES_FILENAME(std::move(PropFile)),
DAEMON_ROOT_ENV_VAR(std::move(RootEnv)),
DAEMON_CONFIG_ENV_VAR(std::move(ConfigVar)),
DAEMON_APP_NAME(std::move(AppName)),
DAEMON_BUS_TIMER(BusTimer),
SubSystems_(std::move(Subsystems)),
Logger_(Poco::Logger::get("FRAMEWORK")) {
instance_ = this; instance_ = this;
RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count()); RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count());
// Logger_ = Poco::Logger::root().get("BASE-SVC"); // Logger_ = Poco::Logger::root().get("BASE-SVC");
@@ -100,9 +92,13 @@ namespace OpenWifi {
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; }; inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
[[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; } [[nodiscard]] const std::string &AppName() { return DAEMON_APP_NAME; }
static inline uint64_t GetPID() { return Poco::Process::id(); }; static inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; [[nodiscard]] inline const std::string GetPublicAPIEndPoint() {
return MyPublicEndPoint_ + "/api/v1";
};
[[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; }; [[nodiscard]] inline const std::string &GetUIURI() const { return UIURI_; };
[[nodiscard]] inline uint64_t Random(uint64_t ceiling) { return (RandomEngine_() % ceiling); } [[nodiscard]] inline uint64_t Random(uint64_t ceiling) {
return (RandomEngine_() % ceiling);
}
[[nodiscard]] inline uint64_t Random(uint64_t min, uint64_t max) { [[nodiscard]] inline uint64_t Random(uint64_t min, uint64_t max) {
return ((RandomEngine_() % (max - min)) + min); return ((RandomEngine_() % (max - min)) + min);
} }
@@ -158,11 +154,17 @@ namespace OpenWifi {
[[nodiscard]] std::string Sign(Poco::JWT::Token &T, const std::string &Algo); [[nodiscard]] std::string Sign(Poco::JWT::Token &T, const std::string &Algo);
void AddActivity(const std::string &Activity); void AddActivity(const std::string &Activity);
static void SetConsoleLogs(bool UseAsync, bool AllowWebSocket, const std::string & FormatterPattern); static void SetConsoleLogs(bool UseAsync, bool AllowWebSocket,
static void SetColorConsoleLogs(bool UseAsync, bool AllowWebSocket, const std::string & FormatterPattern); const std::string &FormatterPattern);
static void SetSQLLogs(bool UseAsync, bool AllowWebSocket, const std::string & FormatterPattern); static void SetColorConsoleLogs(bool UseAsync, bool AllowWebSocket,
static void SetSyslogLogs(bool UseAsync, bool AllowWebSocket, const std::string & FormatterPattern); const std::string &FormatterPattern);
static void SetFileLogs(bool UseAsync, bool AllowWebSocket, const std::string & FormatterPattern, const std::string & root_env_var); static void SetSQLLogs(bool UseAsync, bool AllowWebSocket,
const std::string &FormatterPattern);
static void SetSyslogLogs(bool UseAsync, bool AllowWebSocket,
const std::string &FormatterPattern);
static void SetFileLogs(bool UseAsync, bool AllowWebSocket,
const std::string &FormatterPattern,
const std::string &root_env_var);
inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; } inline bool AllowExternalMicroServices() const { return AllowExternalMicroServices_; }
private: private:
@@ -182,7 +184,8 @@ namespace OpenWifi {
std::string MyPrivateEndPoint_; std::string MyPrivateEndPoint_;
std::string MyPublicEndPoint_; std::string MyPublicEndPoint_;
std::string UIURI_; std::string UIURI_;
std::string Version_{ OW_VERSION::VERSION + "("+ OW_VERSION::BUILD + ")" + " - " + OW_VERSION::HASH }; std::string Version_{OW_VERSION::VERSION + "(" + OW_VERSION::BUILD + ")" + " - " +
OW_VERSION::HASH};
std::recursive_mutex InfraMutex_; std::recursive_mutex InfraMutex_;
std::default_random_engine RandomEngine_; std::default_random_engine RandomEngine_;
Poco::Util::PropertyFileConfiguration *PropConfigurationFile_ = nullptr; Poco::Util::PropertyFileConfiguration *PropConfigurationFile_ = nullptr;
@@ -203,4 +206,4 @@ namespace OpenWifi {
inline MicroService *MicroService::instance_ = nullptr; inline MicroService *MicroService::instance_ = nullptr;
} } // namespace OpenWifi

View File

@@ -4,21 +4,20 @@
#pragma once #pragma once
#include "fmt/format.h"
#include "Poco/Util/Application.h"
#include "Poco/ErrorHandler.h" #include "Poco/ErrorHandler.h"
#include "Poco/JSON/JSONException.h"
#include "Poco/JSON/Template.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/Net/SSLException.h" #include "Poco/Net/SSLException.h"
#include "Poco/JSON/Template.h"
#include "Poco/JSON/JSONException.h"
#include "Poco/Thread.h" #include "Poco/Thread.h"
#include "Poco/Util/Application.h"
#include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
class MicroServiceErrorHandler : public Poco::ErrorHandler { class MicroServiceErrorHandler : public Poco::ErrorHandler {
public: public:
explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) { explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) {}
}
inline void exception(const Poco::Exception &Base) override { inline void exception(const Poco::Exception &Base) override {
try { try {
@@ -34,146 +33,134 @@ namespace OpenWifi {
Base.rethrow(); Base.rethrow();
} catch (const Poco::Net::InvalidCertificateException &E) { } catch (const Poco::Net::InvalidCertificateException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidCertificateException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::InvalidCertificateException thr_name={} "
E.displayText(), "thr_id={} code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::InvalidSocketException &E) { } catch (const Poco::Net::InvalidSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidSocketException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::InvalidSocketException thr_name={} thr_id={} "
E.displayText(), "code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::WebSocketException &E) { } catch (const Poco::Net::WebSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::WebSocketException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::Net::WebSocketException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::Net::ConnectionResetException &E) { } catch (const Poco::Net::ConnectionResetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::ConnectionResetException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::ConnectionResetException thr_name={} thr_id={} "
E.displayText(), "code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::CertificateValidationException &E) { } catch (const Poco::Net::CertificateValidationException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::CertificateValidationException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::CertificateValidationException thr_name={} "
E.displayText(), "thr_id={} code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) { } catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLConnectionUnexpectedlyClosedException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::SSLConnectionUnexpectedlyClosedException "
E.displayText(), "thr_name={} thr_id={} code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::SSLContextException &E) { } catch (const Poco::Net::SSLContextException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLContextException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::Net::SSLContextException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::Net::SSLException &E) { } catch (const Poco::Net::SSLException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::Net::SSLException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::Net::InvalidAddressException &E) { } catch (const Poco::Net::InvalidAddressException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidAddressException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::Net::InvalidAddressException thr_name={} thr_id={} "
E.displayText(), "code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::Net::NetException &E) { } catch (const Poco::Net::NetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::NetException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::Net::NetException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::IOException &E) { } catch (const Poco::IOException &E) {
poco_error(App_.logger(), fmt::format("Poco::IOException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(
t_name, t_id, E.code(), App_.logger(),
E.displayText(), fmt::format(
E.message(), "Poco::IOException thr_name={} thr_id={} code={} text={} msg={} what={}",
E.what())); t_name, t_id, E.code(), E.displayText(), E.message(), E.what()));
} catch (const Poco::TimeoutException &E) { } catch (const Poco::TimeoutException &E) {
poco_error(App_.logger(), fmt::format("Poco::TimeoutException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::TimeoutException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::NoThreadAvailableException &E) { } catch (const Poco::NoThreadAvailableException &E) {
poco_error(App_.logger(), fmt::format("Poco::NoThreadAvailableException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::NoThreadAvailableException thr_name={} thr_id={} "
E.displayText(), "code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::OutOfMemoryException &E) { } catch (const Poco::OutOfMemoryException &E) {
poco_error(App_.logger(), fmt::format("Poco::OutOfMemoryException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::OutOfMemoryException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::BadCastException &E) { } catch (const Poco::BadCastException &E) {
poco_error(App_.logger(), fmt::format("Poco::BadCastException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::BadCastException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::DataException &E) { } catch (const Poco::DataException &E) {
poco_error(App_.logger(), fmt::format("Poco::DataException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(
t_name, t_id, E.code(), App_.logger(),
E.displayText(), fmt::format(
E.message(), "Poco::DataException thr_name={} thr_id={} code={} text={} msg={} what={}",
E.what())); t_name, t_id, E.code(), E.displayText(), E.message(), E.what()));
} catch (const Poco::PoolOverflowException &E) { } catch (const Poco::PoolOverflowException &E) {
poco_error(App_.logger(), fmt::format("Poco::PoolOverflowException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::PoolOverflowException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::SystemException &E) { } catch (const Poco::SystemException &E) {
poco_error(App_.logger(), fmt::format("Poco::SystemException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::SystemException thr_name={} thr_id={} "
t_name, t_id, E.code(), "code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::RuntimeException &E) { } catch (const Poco::RuntimeException &E) {
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::JSON::JSONTemplateException &E) { } catch (const Poco::JSON::JSONTemplateException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONTemplateException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(),
t_name, t_id, E.code(), fmt::format("Poco::JSON::JSONTemplateException thr_name={} thr_id={} "
E.displayText(), "code={} text={} msg={} what={}",
E.message(), t_name, t_id, E.code(), E.displayText(), E.message(),
E.what())); E.what()));
} catch (const Poco::JSON::JSONException &E) { } catch (const Poco::JSON::JSONException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::JSON::JSONException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::ApplicationException &E) { } catch (const Poco::ApplicationException &E) {
poco_error(App_.logger(), fmt::format("Poco::ApplicationException thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(App_.logger(), fmt::format("Poco::ApplicationException thr_name={} "
t_name, t_id, E.code(), "thr_id={} code={} text={} msg={} what={}",
E.displayText(), t_name, t_id, E.code(), E.displayText(),
E.message(), E.message(), E.what()));
E.what()));
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_error(App_.logger(), fmt::format("Poco::Exception thr_name={} thr_id={} code={} text={} msg={} what={}", poco_error(
t_name, t_id, E.code(), App_.logger(),
E.displayText(), fmt::format(
E.message(), "Poco::Exception thr_name={} thr_id={} code={} text={} msg={} what={}",
E.what())); t_name, t_id, E.code(), E.displayText(), E.message(), E.what()));
} catch (...) { } catch (...) {
poco_error(App_.logger(), fmt::format("Poco:Generic thr_name={}", t_name, t_id)); poco_error(App_.logger(), fmt::format("Poco:Generic thr_name={}", t_name, t_id));
} }
@@ -187,9 +174,8 @@ namespace OpenWifi {
t_name = "startup_code"; t_name = "startup_code";
t_id = 0; t_id = 0;
} }
poco_warning(App_.logger(), fmt::format("std::exception in {}: {} thr_id={}", poco_warning(App_.logger(),
t_name,E.what(), fmt::format("std::exception in {}: {} thr_id={}", t_name, E.what(), t_id));
t_id));
} }
inline void exception() override { inline void exception() override {
@@ -200,13 +186,14 @@ namespace OpenWifi {
t_name = "startup_code"; t_name = "startup_code";
t_id = 0; t_id = 0;
} }
poco_warning(App_.logger(), fmt::format("generic exception in {} thr_id={}", poco_warning(App_.logger(),
t_name, t_id)); fmt::format("generic exception in {} thr_id={}", t_name, t_id));
} }
private: private:
Poco::Util::Application &App_; Poco::Util::Application &App_;
std::string t_name; std::string t_name;
int t_id = 0; int t_id = 0;
}; };
} } // namespace OpenWifi

View File

@@ -4,8 +4,8 @@
#pragma once #pragma once
#include <string>
#include <map> #include <map>
#include <string>
#include "Poco/BasicEvent.h" #include "Poco/BasicEvent.h"
#include "Poco/ExpireLRUCache.h" #include "Poco/ExpireLRUCache.h"
@@ -13,27 +13,26 @@
namespace OpenWifi { namespace OpenWifi {
class ConfigurationEntry { class ConfigurationEntry {
public: public:
template <typename T> explicit ConfigurationEntry(T def) : template <typename T> explicit ConfigurationEntry(T def) : Default_(def), Current_(def) {}
Default_(def),
Current_(def){
}
template <typename T> explicit ConfigurationEntry(T def, T cur, const std::string &Hint="") : template <typename T>
Default_(def), explicit ConfigurationEntry(T def, T cur, const std::string &Hint = "")
Current_(cur), : Default_(def), Current_(cur), Hint_(Hint) {}
Hint_(Hint){
}
inline ConfigurationEntry() = default; inline ConfigurationEntry() = default;
inline ~ConfigurationEntry() = default; inline ~ConfigurationEntry() = default;
template <typename T> explicit operator T() const { return std::get<T>(Current_); } template <typename T> explicit operator T() const { return std::get<T>(Current_); }
inline ConfigurationEntry & operator=(const char *v) { Current_ = std::string(v); return *this;} inline ConfigurationEntry &operator=(const char *v) {
template <typename T> ConfigurationEntry & operator=(T v) { Current_ = (T) v; return *this;} Current_ = std::string(v);
return *this;
void reset() {
Current_ = Default_;
} }
template <typename T> ConfigurationEntry &operator=(T v) {
Current_ = (T)v;
return *this;
}
void reset() { Current_ = Default_; }
private: private:
std::variant<bool, uint64_t, std::string> Default_, Current_; std::variant<bool, uint64_t, std::string> Default_, Current_;
@@ -45,14 +44,9 @@ namespace OpenWifi {
template <typename T> class FIFO { template <typename T> class FIFO {
public: public:
explicit FIFO(uint32_t Size) : explicit FIFO(uint32_t Size) : Size_(Size) { Buffer_ = new T[Size_]; }
Size_(Size) {
Buffer_ = new T [Size_];
}
~FIFO() { ~FIFO() { delete[] Buffer_; }
delete [] Buffer_;
}
mutable Poco::BasicEvent<bool> Writable_; mutable Poco::BasicEvent<bool> Writable_;
mutable Poco::BasicEvent<bool> Readable_; mutable Poco::BasicEvent<bool> Readable_;
@@ -108,25 +102,17 @@ namespace OpenWifi {
T *Buffer_ = nullptr; T *Buffer_ = nullptr;
}; };
template <class Record, typename KeyType = std::string, int Size=256, int Expiry=60000> class RecordCache { template <class Record, typename KeyType = std::string, int Size = 256, int Expiry = 60000>
class RecordCache {
public: public:
explicit RecordCache( KeyType Record::* Q) : explicit RecordCache(KeyType Record::*Q) : MemberOffset(Q){};
MemberOffset(Q){ inline auto update(const Record &R) { return Cache_.update(R.*MemberOffset, R); }
}; inline auto get(const KeyType &K) { return Cache_.get(K); }
inline auto update(const Record &R) { inline auto remove(const KeyType &K) { return Cache_.remove(K); }
return Cache_.update(R.*MemberOffset, R); inline auto remove(const Record &R) { return Cache_.remove(R.*MemberOffset); }
}
inline auto get(const KeyType &K) {
return Cache_.get(K);
}
inline auto remove(const KeyType &K) {
return Cache_.remove(K);
}
inline auto remove(const Record &R) {
return Cache_.remove(R.*MemberOffset);
}
private: private:
KeyType Record::*MemberOffset; KeyType Record::*MemberOffset;
Poco::ExpireLRUCache<KeyType, Record> Cache_{Size, Expiry}; Poco::ExpireLRUCache<KeyType, Record> Cache_{Size, Expiry};
}; };
} } // namespace OpenWifi

View File

@@ -2,8 +2,8 @@
// Created by stephane bourque on 2022-10-25. // Created by stephane bourque on 2022-10-25.
// //
#include "framework/MicroService.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
const std::string &MicroServiceDataDirectory() { return MicroService::instance().DataDir(); } const std::string &MicroServiceDataDirectory() { return MicroService::instance().DataDir(); }
@@ -18,7 +18,8 @@ namespace OpenWifi {
std::string MicroServicePublicEndPoint() { return MicroService::instance().PublicEndPoint(); } std::string MicroServicePublicEndPoint() { return MicroService::instance().PublicEndPoint(); }
std::string MicroServiceConfigGetString(const std::string &Key, const std::string &DefaultValue) { std::string MicroServiceConfigGetString(const std::string &Key,
const std::string &DefaultValue) {
return MicroService::instance().ConfigGetString(Key, DefaultValue); return MicroService::instance().ConfigGetString(Key, DefaultValue);
} }
@@ -46,15 +47,17 @@ namespace OpenWifi {
void MicroServiceReload(const std::string &Type) { MicroService::instance().Reload(Type); } void MicroServiceReload(const std::string &Type) { MicroService::instance().Reload(Type); }
const Types::StringVec MicroServiceGetLogLevelNames() { Types::StringVec MicroServiceGetLogLevelNames() {
return MicroService::instance().GetLogLevelNames(); return MicroService::instance().GetLogLevelNames();
} }
const Types::StringVec MicroServiceGetSubSystems() { Types::StringVec MicroServiceGetSubSystems() {
return MicroService::instance().GetSubSystems(); return MicroService::instance().GetSubSystems();
} }
Types::StringPairVec MicroServiceGetLogLevels() { return MicroService::instance().GetLogLevels(); } Types::StringPairVec MicroServiceGetLogLevels() {
return MicroService::instance().GetLogLevels();
}
bool MicroServiceSetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { bool MicroServiceSetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) {
return MicroService::instance().SetSubsystemLogLevel(SubSystem, Level); return MicroService::instance().SetSubsystemLogLevel(SubSystem, Level);
@@ -76,7 +79,7 @@ namespace OpenWifi {
std::string MicroServiceGetUIURI() { return MicroService::instance().GetUIURI(); } std::string MicroServiceGetUIURI() { return MicroService::instance().GetUIURI(); }
const SubSystemVec MicroServiceGetFullSubSystems() { SubSystemVec MicroServiceGetFullSubSystems() {
return MicroService::instance().GetFullSubSystems(); return MicroService::instance().GetFullSubSystems();
} }
@@ -84,20 +87,17 @@ namespace OpenWifi {
std::uint64_t MicroServiceDaemonBusTimer() { return MicroService::instance().DaemonBusTimer(); } std::uint64_t MicroServiceDaemonBusTimer() { return MicroService::instance().DaemonBusTimer(); }
std::string MicroServiceMakeSystemEventMessage(const std::string &Type) { std::string MicroServiceMakeSystemEventMessage(const char *Type) {
return MicroService::instance().MakeSystemEventMessage(Type); return MicroService::instance().MakeSystemEventMessage(Type);
} }
Poco::ThreadPool &MicroServiceTimerPool() { return MicroService::instance().TimerPool(); } Poco::ThreadPool &MicroServiceTimerPool() { return MicroService::instance().TimerPool(); }
std::string MicroServiceConfigPath(const std::string &Key, std::string MicroServiceConfigPath(const std::string &Key, const std::string &DefaultValue) {
const std::string &DefaultValue) {
return MicroService::instance().ConfigPath(Key, DefaultValue); return MicroService::instance().ConfigPath(Key, DefaultValue);
} }
std::string MicroServiceWWWAssetsDir() { std::string MicroServiceWWWAssetsDir() { return MicroService::instance().WWWAssetsDir(); }
return MicroService::instance().WWWAssetsDir();
}
std::uint64_t MicroServiceRandom(std::uint64_t Start, std::uint64_t End) { std::uint64_t MicroServiceRandom(std::uint64_t Start, std::uint64_t End) {
return MicroService::instance().Random(Start, End); return MicroService::instance().Random(Start, End);
@@ -123,4 +123,4 @@ namespace OpenWifi {
return MicroService::instance().AllowExternalMicroServices(); return MicroService::instance().AllowExternalMicroServices();
} }
} } // namespace OpenWifi

View File

@@ -8,11 +8,10 @@
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/ThreadPool.h"
#include "Poco/JWT/Token.h" #include "Poco/JWT/Token.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/ThreadPool.h"
namespace OpenWifi { namespace OpenWifi {
class SubSystemServer; class SubSystemServer;
@@ -21,7 +20,8 @@ namespace OpenWifi {
Types::MicroServiceMetaVec MicroServiceGetServices(const std::string &Type); Types::MicroServiceMetaVec MicroServiceGetServices(const std::string &Type);
Types::MicroServiceMetaVec MicroServiceGetServices(); Types::MicroServiceMetaVec MicroServiceGetServices();
std::string MicroServicePublicEndPoint(); std::string MicroServicePublicEndPoint();
std::string MicroServiceConfigGetString(const std::string &Key, const std::string &DefaultValue); std::string MicroServiceConfigGetString(const std::string &Key,
const std::string &DefaultValue);
bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue); bool MicroServiceConfigGetBool(const std::string &Key, bool DefaultValue);
std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue); std::uint64_t MicroServiceConfigGetInt(const std::string &Key, std::uint64_t DefaultValue);
std::string MicroServicePrivateEndPoint(); std::string MicroServicePrivateEndPoint();
@@ -31,8 +31,8 @@ namespace OpenWifi {
void MicroServiceLoadConfigurationFile(); void MicroServiceLoadConfigurationFile();
void MicroServiceReload(); void MicroServiceReload();
void MicroServiceReload(const std::string &Type); void MicroServiceReload(const std::string &Type);
const Types::StringVec MicroServiceGetLogLevelNames(); Types::StringVec MicroServiceGetLogLevelNames();
const Types::StringVec MicroServiceGetSubSystems(); Types::StringVec MicroServiceGetSubSystems();
Types::StringPairVec MicroServiceGetLogLevels(); Types::StringPairVec MicroServiceGetLogLevels();
bool MicroServiceSetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level); bool MicroServiceSetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level);
void MicroServiceGetExtraConfiguration(Poco::JSON::Object &Answer); void MicroServiceGetExtraConfiguration(Poco::JSON::Object &Answer);
@@ -40,13 +40,12 @@ namespace OpenWifi {
std::uint64_t MicroServiceUptimeTotalSeconds(); std::uint64_t MicroServiceUptimeTotalSeconds();
std::uint64_t MicroServiceStartTimeEpochTime(); std::uint64_t MicroServiceStartTimeEpochTime();
std::string MicroServiceGetUIURI(); std::string MicroServiceGetUIURI();
const SubSystemVec MicroServiceGetFullSubSystems(); SubSystemVec MicroServiceGetFullSubSystems();
std::string MicroServiceCreateUUID(); std::string MicroServiceCreateUUID();
std::uint64_t MicroServiceDaemonBusTimer(); std::uint64_t MicroServiceDaemonBusTimer();
std::string MicroServiceMakeSystemEventMessage( const std::string & Type ); std::string MicroServiceMakeSystemEventMessage(const char *Type);
Poco::ThreadPool &MicroServiceTimerPool(); Poco::ThreadPool &MicroServiceTimerPool();
std::string MicroServiceConfigPath(const std::string &Key, std::string MicroServiceConfigPath(const std::string &Key, const std::string &DefaultValue);
const std::string &DefaultValue);
std::string MicroServiceWWWAssetsDir(); std::string MicroServiceWWWAssetsDir();
std::uint64_t MicroServiceRandom(std::uint64_t Start, std::uint64_t End); std::uint64_t MicroServiceRandom(std::uint64_t Start, std::uint64_t End);
std::uint64_t MicroServiceRandom(std::uint64_t Range); std::uint64_t MicroServiceRandom(std::uint64_t Range);
@@ -54,4 +53,4 @@ namespace OpenWifi {
std::string MicroServiceGetPublicAPIEndPoint(); std::string MicroServiceGetPublicAPIEndPoint();
void MicroServiceDeleteOverrideConfiguration(); void MicroServiceDeleteOverrideConfiguration();
bool AllowExternalMicroServices(); bool AllowExternalMicroServices();
} } // namespace OpenWifi

View File

@@ -19,4 +19,4 @@ namespace OpenWifi {
static const std::string uSERVICE_ANALYTICS{"owanalytics"}; static const std::string uSERVICE_ANALYTICS{"owanalytics"};
static const std::string uSERVICE_OWRRM{"owrrm"}; static const std::string uSERVICE_OWRRM{"owrrm"};
} } // namespace OpenWifi

View File

@@ -4,18 +4,19 @@
#include "OpenAPIRequests.h" #include "OpenAPIRequests.h"
#include "Poco/JSON/Parser.h"
#include "Poco/Logger.h" #include "Poco/Logger.h"
#include "Poco/URI.h"
#include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPSClientSession.h" #include "Poco/Net/HTTPSClientSession.h"
#include "Poco/JSON/Parser.h" #include "Poco/URI.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
Poco::Net::HTTPServerResponse::HTTPStatus OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken) { Poco::Net::HTTPServerResponse::HTTPStatus
OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string &BearerToken) {
try { try {
auto Services = MicroServiceGetServices(Type_); auto Services = MicroServiceGetServices(Type_);
@@ -29,11 +30,11 @@ namespace OpenWifi {
URI.addQueryParameter(qp.first, qp.second); URI.addQueryParameter(qp.first, qp.second);
std::string Path(URI.getPathAndQuery()); std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Path,
Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPMessage::HTTP_1_1);
poco_debug(Poco::Logger::get("REST-CALLER-GET"), fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_ ) ); poco_debug(Poco::Logger::get("REST-CALLER-GET"),
fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_));
if (BearerToken.empty()) { if (BearerToken.empty()) {
Request.add("X-API-KEY", Svc.AccessKey); Request.add("X-API-KEY", Svc.AccessKey);
@@ -71,15 +72,14 @@ namespace OpenWifi {
return Response.getStatus(); return Response.getStatus();
} }
} }
} } catch (const Poco::Exception &E) {
catch (const Poco::Exception &E)
{
Poco::Logger::get("REST-CALLER-GET").log(E); Poco::Logger::get("REST-CALLER-GET").log(E);
} }
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT; return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
} }
Poco::Net::HTTPServerResponse::HTTPStatus OpenAPIRequestPut::Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken) { Poco::Net::HTTPServerResponse::HTTPStatus
OpenAPIRequestPut::Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string &BearerToken) {
try { try {
auto Services = MicroServiceGetServices(Type_); auto Services = MicroServiceGetServices(Type_);
for (auto const &Svc : Services) { for (auto const &Svc : Services) {
@@ -91,12 +91,12 @@ namespace OpenWifi {
for (const auto &qp : QueryData_) for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second); URI.addQueryParameter(qp.first, qp.second);
poco_debug(Poco::Logger::get("REST-CALLER-PUT"), fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_ ) ); poco_debug(Poco::Logger::get("REST-CALLER-PUT"),
fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_));
std::string Path(URI.getPathAndQuery()); std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_PUT, Path,
Path,
Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPMessage::HTTP_1_1);
std::ostringstream obody; std::ostringstream obody;
Poco::JSON::Stringifier::stringify(Body_, obody); Poco::JSON::Stringifier::stringify(Body_, obody);
@@ -148,34 +148,33 @@ namespace OpenWifi {
return Response.getStatus(); return Response.getStatus();
} }
} }
} } catch (const Poco::Exception &E) {
catch (const Poco::Exception &E)
{
Poco::Logger::get("REST-CALLER-PUT").log(E); Poco::Logger::get("REST-CALLER-PUT").log(E);
} }
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT; return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
} }
Poco::Net::HTTPServerResponse::HTTPStatus OpenAPIRequestPost::Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken) { Poco::Net::HTTPServerResponse::HTTPStatus
OpenAPIRequestPost::Do(Poco::JSON::Object::Ptr &ResponseObject,
const std::string &BearerToken) {
try { try {
auto Services = MicroServiceGetServices(Type_); auto Services = MicroServiceGetServices(Type_);
for (auto const &Svc : Services) { for (auto const &Svc : Services) {
Poco::URI URI(Svc.PrivateEndPoint); Poco::URI URI(Svc.PrivateEndPoint);
auto Secure = (URI.getScheme() == "https"); auto Secure = (URI.getScheme() == "https");
URI.setPath(EndPoint_); URI.setPath(EndPoint_);
for (const auto &qp : QueryData_) for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second); URI.addQueryParameter(qp.first, qp.second);
poco_debug(Poco::Logger::get("REST-CALLER-POST"),fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_ ) ); poco_debug(Poco::Logger::get("REST-CALLER-POST"),
fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_));
std::string Path(URI.getPathAndQuery()); std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path,
Path,
Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPMessage::HTTP_1_1);
std::ostringstream obody; std::ostringstream obody;
Poco::JSON::Stringifier::stringify(Body_, obody); Poco::JSON::Stringifier::stringify(Body_, obody);
@@ -225,15 +224,14 @@ namespace OpenWifi {
return Response.getStatus(); return Response.getStatus();
} }
} }
} } catch (const Poco::Exception &E) {
catch (const Poco::Exception &E)
{
Poco::Logger::get("REST-CALLER-POST").log(E); Poco::Logger::get("REST-CALLER-POST").log(E);
} }
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT; return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
} }
Poco::Net::HTTPServerResponse::HTTPStatus OpenAPIRequestDelete::Do(const std::string & BearerToken) { Poco::Net::HTTPServerResponse::HTTPStatus
OpenAPIRequestDelete::Do(const std::string &BearerToken) {
try { try {
auto Services = MicroServiceGetServices(Type_); auto Services = MicroServiceGetServices(Type_);
@@ -246,12 +244,12 @@ namespace OpenWifi {
for (const auto &qp : QueryData_) for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second); URI.addQueryParameter(qp.first, qp.second);
poco_debug(Poco::Logger::get("REST-CALLER-DELETE"),fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_ ) ); poco_debug(Poco::Logger::get("REST-CALLER-DELETE"),
fmt::format(" {}", LoggingStr_.empty() ? URI.toString() : LoggingStr_));
std::string Path(URI.getPathAndQuery()); std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_DELETE, Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_DELETE, Path,
Path,
Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPMessage::HTTP_1_1);
if (BearerToken.empty()) { if (BearerToken.empty()) {
Request.add("X-API-KEY", Svc.AccessKey); Request.add("X-API-KEY", Svc.AccessKey);
@@ -277,13 +275,10 @@ namespace OpenWifi {
return Response.getStatus(); return Response.getStatus();
} }
} }
} } catch (const Poco::Exception &E) {
catch (const Poco::Exception &E)
{
Poco::Logger::get("REST-CALLER-DELETE").log(E); Poco::Logger::get("REST-CALLER-DELETE").log(E);
} }
return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT; return Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT;
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -15,17 +15,14 @@ namespace OpenWifi {
class OpenAPIRequestGet { class OpenAPIRequestGet {
public: public:
explicit OpenAPIRequestGet( const std::string & Type, explicit OpenAPIRequestGet(const std::string &Type, const std::string &EndPoint,
const std::string & EndPoint, const Types::StringPairVec &QueryData, uint64_t msTimeout,
const Types::StringPairVec & QueryData, const std::string &LoggingStr = "")
uint64_t msTimeout, : Type_(Type), EndPoint_(EndPoint), QueryData_(QueryData), msTimeout_(msTimeout),
const std::string &LoggingStr=""):
Type_(Type),
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout),
LoggingStr_(LoggingStr){}; LoggingStr_(LoggingStr){};
Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken = ""); Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject,
const std::string &BearerToken = "");
private: private:
std::string Type_; std::string Type_;
std::string EndPoint_; std::string EndPoint_;
@@ -36,20 +33,15 @@ namespace OpenWifi {
class OpenAPIRequestPut { class OpenAPIRequestPut {
public: public:
explicit OpenAPIRequestPut( const std::string & Type, explicit OpenAPIRequestPut(const std::string &Type, const std::string &EndPoint,
const std::string & EndPoint,
const Types::StringPairVec &QueryData, const Types::StringPairVec &QueryData,
const Poco::JSON::Object & Body, const Poco::JSON::Object &Body, uint64_t msTimeout,
uint64_t msTimeout, const std::string &LoggingStr = "")
const std::string &LoggingStr=""): : Type_(Type), EndPoint_(EndPoint), QueryData_(QueryData), msTimeout_(msTimeout),
Type_(Type), Body_(Body), LoggingStr_(LoggingStr){};
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout),
Body_(Body),
LoggingStr_(LoggingStr){};
Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken = ""); Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject,
const std::string &BearerToken = "");
private: private:
std::string Type_; std::string Type_;
@@ -62,19 +54,15 @@ namespace OpenWifi {
class OpenAPIRequestPost { class OpenAPIRequestPost {
public: public:
explicit OpenAPIRequestPost( const std::string & Type, explicit OpenAPIRequestPost(const std::string &Type, const std::string &EndPoint,
const std::string & EndPoint,
const Types::StringPairVec &QueryData, const Types::StringPairVec &QueryData,
const Poco::JSON::Object & Body, const Poco::JSON::Object &Body, uint64_t msTimeout,
uint64_t msTimeout, const std::string &LoggingStr = "")
const std::string &LoggingStr=""): : Type_(Type), EndPoint_(EndPoint), QueryData_(QueryData), msTimeout_(msTimeout),
Type_(Type), Body_(Body), LoggingStr_(LoggingStr){};
EndPoint_(EndPoint), Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject,
QueryData_(QueryData), const std::string &BearerToken = "");
msTimeout_(msTimeout),
Body_(Body),
LoggingStr_(LoggingStr){};
Poco::Net::HTTPServerResponse::HTTPStatus Do(Poco::JSON::Object::Ptr &ResponseObject, const std::string & BearerToken = "");
private: private:
std::string Type_; std::string Type_;
std::string EndPoint_; std::string EndPoint_;
@@ -86,15 +74,10 @@ namespace OpenWifi {
class OpenAPIRequestDelete { class OpenAPIRequestDelete {
public: public:
explicit OpenAPIRequestDelete( const std::string & Type, explicit OpenAPIRequestDelete(const std::string &Type, const std::string &EndPoint,
const std::string & EndPoint, const Types::StringPairVec &QueryData, uint64_t msTimeout,
const Types::StringPairVec & QueryData, const std::string &LoggingStr = "")
uint64_t msTimeout, : Type_(Type), EndPoint_(EndPoint), QueryData_(QueryData), msTimeout_(msTimeout),
const std::string &LoggingStr=""):
Type_(Type),
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout),
LoggingStr_(LoggingStr){}; LoggingStr_(LoggingStr){};
Poco::Net::HTTPServerResponse::HTTPStatus Do(const std::string &BearerToken = ""); Poco::Net::HTTPServerResponse::HTTPStatus Do(const std::string &BearerToken = "");

View File

@@ -4,14 +4,14 @@
#pragma once #pragma once
#include <functional>
#include <list>
#include <map> #include <map>
#include <queue>
#include <set>
#include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <functional>
#include <string>
#include <queue>
#include <list>
#include <set>
namespace OpenWifi::Types { namespace OpenWifi::Types {
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
@@ -41,11 +41,12 @@ namespace OpenWifi::Types {
typedef std::map<std::string, MicroServiceMeta> MicroServiceMetaMap; typedef std::map<std::string, MicroServiceMeta> MicroServiceMetaMap;
typedef std::vector<MicroServiceMeta> MicroServiceMetaVec; typedef std::vector<MicroServiceMeta> MicroServiceMetaVec;
} } // namespace OpenWifi::Types
namespace OpenWifi { namespace OpenWifi {
inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S, uint64_t Increment=1) { inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S,
uint64_t Increment = 1) {
auto it = M.find(S); auto it = M.find(S);
if (it == M.end()) if (it == M.end())
M[S] = Increment; M[S] = Increment;
@@ -53,14 +54,14 @@ namespace OpenWifi {
it->second += Increment; it->second += Increment;
} }
inline void UpdateCountedMap(OpenWifi::Types::Counted3DMapSII &M, const std::string &S, uint32_t Index, uint64_t Increment=1) { inline void UpdateCountedMap(OpenWifi::Types::Counted3DMapSII &M, const std::string &S,
uint32_t Index, uint64_t Increment = 1) {
auto it = M.find(S); auto it = M.find(S);
if (it == M.end()) { if (it == M.end()) {
std::map<uint32_t, uint64_t> E; std::map<uint32_t, uint64_t> E;
E[Index] = Increment; E[Index] = Increment;
M[S] = E; M[S] = E;
} } else {
else {
std::map<uint32_t, uint64_t> &IndexMap = it->second; std::map<uint32_t, uint64_t> &IndexMap = it->second;
auto it_index = IndexMap.find(Index); auto it_index = IndexMap.find(Index);
if (it_index == IndexMap.end()) { if (it_index == IndexMap.end()) {
@@ -70,4 +71,4 @@ namespace OpenWifi {
} }
} }
} }
} } // namespace OpenWifi

View File

@@ -6,22 +6,23 @@
namespace OpenWifi { namespace OpenWifi {
Poco::Net::HTTPRequestHandler *ExtRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &Request) { Poco::Net::HTTPRequestHandler *
ExtRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &Request) {
try { try {
Poco::URI uri(Request.getURI()); Poco::URI uri(Request.getURI());
auto TID = NextTransactionId_++; auto TID = NextTransactionId_++;
Utils::SetThreadName(fmt::format("x-rest:{}", TID).c_str()); Utils::SetThreadName(fmt::format("x-rest:{}", TID).c_str());
return RESTAPI_ExtServer()->CallServer(uri.getPath(), TID); return RESTAPI_ExtServer()->CallServer(uri.getPath(), TID);
} catch (...) { } catch (...) {
} }
return nullptr; return nullptr;
} }
Poco::Net::HTTPRequestHandler *RESTAPI_ExtServer::CallServer(const std::string &Path, uint64_t Id) { Poco::Net::HTTPRequestHandler *RESTAPI_ExtServer::CallServer(const std::string &Path,
uint64_t Id) {
RESTAPIHandler::BindingMap Bindings; RESTAPIHandler::BindingMap Bindings;
Utils::SetThreadName(fmt::format("x-rest:{}", Id).c_str()); Utils::SetThreadName(fmt::format("x-rest:{}", Id).c_str());
return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id); return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id);
} }
} } // namespace OpenWifi

View File

@@ -6,18 +6,21 @@
#include "Poco/Net/HTTPServer.h" #include "Poco/Net/HTTPServer.h"
#include "framework/SubSystemServer.h"
#include "framework/RESTAPI_Handler.h" #include "framework/RESTAPI_Handler.h"
#include "framework/SubSystemServer.h"
namespace OpenWifi { namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings, Poco::Net::HTTPRequestHandler *
RESTAPI_ExtRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger &L, RESTAPI_GenericServerAccounting &S, uint64_t Id); Poco::Logger &L, RESTAPI_GenericServerAccounting &S, uint64_t Id);
class ExtRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { class ExtRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public: public:
ExtRequestHandlerFactory() = default; ExtRequestHandlerFactory() = default;
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override; Poco::Net::HTTPRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override;
private: private:
static inline std::atomic_uint64_t NextTransactionId_ = 1; static inline std::atomic_uint64_t NextTransactionId_ = 1;
}; };
@@ -36,10 +39,15 @@ namespace OpenWifi {
for (const auto &Svr : ConfigServersList_) { for (const auto &Svr : ConfigServersList_) {
if (MicroServiceNoAPISecurity()) { if (MicroServiceNoAPISecurity()) {
poco_information(Logger(),fmt::format("Starting: {}:{}. Security has been disabled for APIs.", Svr.Address(), Svr.Port())); poco_information(
Logger(),
fmt::format("Starting: {}:{}. Security has been disabled for APIs.",
Svr.Address(), Svr.Port()));
} else { } else {
poco_information(Logger(),fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", Svr.Address(), Svr.Port(), poco_information(Logger(),
Svr.KeyFile(),Svr.CertFile())); fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}",
Svr.Address(), Svr.Port(), Svr.KeyFile(),
Svr.CertFile()));
Svr.LogCert(Logger()); Svr.LogCert(Logger());
if (!Svr.RootCA().empty()) if (!Svr.RootCA().empty())
Svr.LogCas(Logger()); Svr.LogCas(Logger());
@@ -52,10 +60,12 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::HTTPServer> NewServer; std::unique_ptr<Poco::Net::HTTPServer> NewServer;
if (MicroServiceNoAPISecurity()) { if (MicroServiceNoAPISecurity()) {
auto Sock{Svr.CreateSocket(Logger())}; auto Sock{Svr.CreateSocket(Logger())};
NewServer = std::make_unique<Poco::Net::HTTPServer>(new ExtRequestHandlerFactory, Pool_, Sock, Params); NewServer = std::make_unique<Poco::Net::HTTPServer>(
new ExtRequestHandlerFactory, Pool_, Sock, Params);
} else { } else {
auto Sock{Svr.CreateSecureSocket(Logger())}; auto Sock{Svr.CreateSecureSocket(Logger())};
NewServer = std::make_unique<Poco::Net::HTTPServer>(new ExtRequestHandlerFactory, Pool_, Sock, Params); NewServer = std::make_unique<Poco::Net::HTTPServer>(
new ExtRequestHandlerFactory, Pool_, Sock, Params);
}; };
NewServer->start(); NewServer->start();
RESTServers_.push_back(std::move(NewServer)); RESTServers_.push_back(std::move(NewServer));
@@ -88,12 +98,10 @@ namespace OpenWifi {
Poco::ThreadPool Pool_{"x-rest", 8, 128}; Poco::ThreadPool Pool_{"x-rest", 8, 128};
RESTAPI_GenericServerAccounting Server_; RESTAPI_GenericServerAccounting Server_;
RESTAPI_ExtServer() noexcept: RESTAPI_ExtServer() noexcept
SubSystemServer("RESTAPI_ExtServer", "REST-XSRV", "openwifi.restapi") : SubSystemServer("RESTAPI_ExtServer", "REST-XSRV", "openwifi.restapi") {}
{
}
}; };
inline auto RESTAPI_ExtServer() { return RESTAPI_ExtServer::instance(); }; inline auto RESTAPI_ExtServer() { return RESTAPI_ExtServer::instance(); };
} } // namespace OpenWifi

View File

@@ -4,25 +4,19 @@
#pragma once #pragma once
#include <string>
#include <array> #include <array>
#include <string>
#include "Poco/StringTokenizer.h"
#include "Poco/String.h"
#include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPRequest.h"
#include "Poco/String.h"
#include "Poco/StringTokenizer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_GenericServerAccounting { class RESTAPI_GenericServerAccounting {
public: public:
enum { LOG_GET = 0, LOG_DELETE, LOG_PUT, LOG_POST };
enum {
LOG_GET=0,
LOG_DELETE,
LOG_PUT,
LOG_POST
};
void inline SetFlags(bool External, const std::string &Methods) { void inline SetFlags(bool External, const std::string &Methods) {
Poco::StringTokenizer Tokens(Methods, ","); Poco::StringTokenizer Tokens(Methods, ",");
@@ -40,14 +34,18 @@ namespace OpenWifi {
} }
inline void InitLogging() { inline void InitLogging() {
std::string Public = MicroServiceConfigGetString("apilogging.public.methods","PUT,POST,DELETE"); std::string Public =
MicroServiceConfigGetString("apilogging.public.methods", "PUT,POST,DELETE");
SetFlags(true, Public); SetFlags(true, Public);
std::string Private = MicroServiceConfigGetString("apilogging.private.methods","PUT,POST,DELETE"); std::string Private =
MicroServiceConfigGetString("apilogging.private.methods", "PUT,POST,DELETE");
SetFlags(false, Private); SetFlags(false, Private);
std::string PublicBadTokens = MicroServiceConfigGetString("apilogging.public.badtokens.methods",""); std::string PublicBadTokens =
MicroServiceConfigGetString("apilogging.public.badtokens.methods", "");
LogBadTokens_[0] = (Poco::icompare(PublicBadTokens, "true") == 0); LogBadTokens_[0] = (Poco::icompare(PublicBadTokens, "true") == 0);
std::string PrivateBadTokens = MicroServiceConfigGetString("apilogging.private.badtokens.methods",""); std::string PrivateBadTokens =
MicroServiceConfigGetString("apilogging.private.badtokens.methods", "");
LogBadTokens_[1] = (Poco::icompare(PrivateBadTokens, "true") == 0); LogBadTokens_[1] = (Poco::icompare(PrivateBadTokens, "true") == 0);
} }
@@ -72,4 +70,4 @@ namespace OpenWifi {
std::array<bool, 8> LogFlags_{false}; std::array<bool, 8> LogFlags_{false};
std::array<bool, 2> LogBadTokens_{false}; std::array<bool, 2> LogBadTokens_{false};
}; };
} } // namespace OpenWifi

View File

@@ -4,5 +4,4 @@
#include "RESTAPI_Handler.h" #include "RESTAPI_Handler.h"
namespace OpenWifi { namespace OpenWifi {} // namespace OpenWifi
} // namespace OpenWifi

View File

@@ -4,27 +4,27 @@
#pragma once #pragma once
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include "Poco/Net/HTTPRequestHandler.h" #include "Poco/DeflatingStream.h"
#include "Poco/Logger.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/Logger.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPResponse.h" #include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPServerResponse.h"
#include "Poco/DeflatingStream.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Net/OAuth20Credentials.h" #include "Poco/Net/OAuth20Credentials.h"
#include "Poco/TemporaryFile.h"
#include "framework/ow_constants.h" #include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "framework/AuthClient.h"
#include "framework/RESTAPI_GenericServerAccounting.h" #include "framework/RESTAPI_GenericServerAccounting.h"
#include "framework/RESTAPI_RateLimiter.h" #include "framework/RESTAPI_RateLimiter.h"
#include "framework/utils.h"
#include "framework/RESTAPI_utils.h" #include "framework/RESTAPI_utils.h"
#include "framework/AuthClient.h" #include "framework/ow_constants.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h" #include "framework/utils.h"
#if defined(TIP_SECURITY_SERVICE) #if defined(TIP_SECURITY_SERVICE)
#include "AuthService.h" #include "AuthService.h"
@@ -40,7 +40,8 @@ namespace OpenWifi {
uint64_t StartDate = 0, EndDate = 0, Offset = 0, Limit = 0, LogType = 0; uint64_t StartDate = 0, EndDate = 0, Offset = 0, Limit = 0, LogType = 0;
std::string SerialNumber, Filter; std::string SerialNumber, Filter;
std::vector<std::string> Select; std::vector<std::string> Select;
bool Lifetime=false, LastOnly=false, Newest=false, CountOnly=false, AdditionalInfo=false; bool Lifetime = false, LastOnly = false, Newest = false, CountOnly = false,
AdditionalInfo = false;
}; };
typedef std::map<std::string, std::string> BindingMap; typedef std::map<std::string, std::string> BindingMap;
@@ -49,30 +50,19 @@ namespace OpenWifi {
int64_t MaxCalls = 10; int64_t MaxCalls = 10;
}; };
RESTAPIHandler( BindingMap map, RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods,
Poco::Logger &l, RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
std::vector<std::string> Methods, bool Internal, bool AlwaysAuthorize = true, bool RateLimited = false,
RESTAPI_GenericServerAccounting & Server,
uint64_t TransactionId,
bool Internal,
bool AlwaysAuthorize=true,
bool RateLimited=false,
const RateLimit &Profile = RateLimit{.Interval = 1000, .MaxCalls = 100}, const RateLimit &Profile = RateLimit{.Interval = 1000, .MaxCalls = 100},
bool SubscriberOnly = false) bool SubscriberOnly = false)
: Bindings_(std::move(map)), : Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)),
Logger_(l), Internal_(Internal), RateLimited_(RateLimited), SubOnlyService_(SubscriberOnly),
Methods_(std::move(Methods)), AlwaysAuthorize_(AlwaysAuthorize), Server_(Server), MyRates_(Profile),
Internal_(Internal), TransactionId_(TransactionId) {}
RateLimited_(RateLimited),
SubOnlyService_(SubscriberOnly),
AlwaysAuthorize_(AlwaysAuthorize),
Server_(Server),
MyRates_(Profile),
TransactionId_(TransactionId)
{
}
inline bool RoleIsAuthorized([[maybe_unused]] const std::string & Path, [[maybe_unused]] const std::string & Method, [[maybe_unused]] std::string & Reason) { inline bool RoleIsAuthorized([[maybe_unused]] const std::string &Path,
[[maybe_unused]] const std::string &Method,
[[maybe_unused]] std::string &Reason) {
return true; return true;
} }
@@ -87,11 +77,13 @@ namespace OpenWifi {
if (Request->getContentLength() > 0) { if (Request->getContentLength() > 0) {
if (Request->getContentType().find("application/json") != std::string::npos) { if (Request->getContentType().find("application/json") != std::string::npos) {
ParsedBody_ = IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>(); ParsedBody_ = IncomingParser_.parse(Request->stream())
.extract<Poco::JSON::Object::Ptr>();
} }
} }
if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) { if (RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(
RequestIn, MyRates_.Interval, MyRates_.MaxCalls)) {
return UnAuthorized(RESTAPI::Errors::RATE_LIMIT_EXCEEDED); return UnAuthorized(RESTAPI::Errors::RATE_LIMIT_EXCEEDED);
} }
@@ -130,9 +122,13 @@ namespace OpenWifi {
} }
[[nodiscard]] inline bool NeedAdditionalInfo() const { return QB_.AdditionalInfo; } [[nodiscard]] inline bool NeedAdditionalInfo() const { return QB_.AdditionalInfo; }
[[nodiscard]] inline const std::vector<std::string> & SelectedRecords() const { return QB_.Select; } [[nodiscard]] inline const std::vector<std::string> &SelectedRecords() const {
return QB_.Select;
}
inline static bool ParseBindings(const std::string & Request, const std::list<std::string> & EndPoints, BindingMap &bindings) { inline static bool ParseBindings(const std::string &Request,
const std::list<std::string> &EndPoints,
BindingMap &bindings) {
bindings.clear(); bindings.clear();
auto PathItems = Poco::StringTokenizer(Request, "/"); auto PathItems = Poco::StringTokenizer(Request, "/");
@@ -180,29 +176,39 @@ namespace OpenWifi {
return false; return false;
} }
[[nodiscard]] inline uint64_t GetParameter(const std::string &Name, const uint64_t Default) { [[nodiscard]] inline uint64_t GetParameter(const std::string &Name,
auto Hint = std::find_if(Parameters_.begin(),Parameters_.end(),[&](const std::pair<std::string,std::string> &S){ return S.first==Name; }); const uint64_t Default) {
auto Hint = std::find_if(
Parameters_.begin(), Parameters_.end(),
[&](const std::pair<std::string, std::string> &S) { return S.first == Name; });
if (Hint == Parameters_.end() || !is_number(Hint->second)) if (Hint == Parameters_.end() || !is_number(Hint->second))
return Default; return Default;
return std::stoull(Hint->second); return std::stoull(Hint->second);
} }
[[nodiscard]] inline bool GetBoolParameter(const std::string &Name, bool Default = false) { [[nodiscard]] inline bool GetBoolParameter(const std::string &Name, bool Default = false) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[&](const std::pair<std::string,std::string> &S){ return S.first==Name; }); auto Hint = std::find_if(
begin(Parameters_), end(Parameters_),
[&](const std::pair<std::string, std::string> &S) { return S.first == Name; });
if (Hint == end(Parameters_) || !is_bool(Hint->second)) if (Hint == end(Parameters_) || !is_bool(Hint->second))
return Default; return Default;
return Hint->second == "true"; return Hint->second == "true";
} }
[[nodiscard]] inline std::string GetParameter(const std::string &Name, const std::string &Default="") { [[nodiscard]] inline std::string GetParameter(const std::string &Name,
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[&](const std::pair<std::string,std::string> &S){ return S.first==Name; }); const std::string &Default = "") {
auto Hint = std::find_if(
begin(Parameters_), end(Parameters_),
[&](const std::pair<std::string, std::string> &S) { return S.first == Name; });
if (Hint == end(Parameters_)) if (Hint == end(Parameters_))
return Default; return Default;
return Hint->second; return Hint->second;
} }
[[nodiscard]] inline bool HasParameter(const std::string &Name, std::string &Value) { [[nodiscard]] inline bool HasParameter(const std::string &Name, std::string &Value) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[&](const std::pair<std::string,std::string> &S){ return S.first==Name; }); auto Hint = std::find_if(
begin(Parameters_), end(Parameters_),
[&](const std::pair<std::string, std::string> &S) { return S.first == Name; });
if (Hint == end(Parameters_)) if (Hint == end(Parameters_))
return false; return false;
Value = Hint->second; Value = Hint->second;
@@ -210,14 +216,17 @@ namespace OpenWifi {
} }
[[nodiscard]] inline bool HasParameter(const std::string &Name, uint64_t &Value) { [[nodiscard]] inline bool HasParameter(const std::string &Name, uint64_t &Value) {
auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[&](const std::pair<std::string,std::string> &S){ return S.first==Name; }); auto Hint = std::find_if(
begin(Parameters_), end(Parameters_),
[&](const std::pair<std::string, std::string> &S) { return S.first == Name; });
if (Hint == end(Parameters_)) if (Hint == end(Parameters_))
return false; return false;
Value = std::stoull(Hint->second); Value = std::stoull(Hint->second);
return true; return true;
} }
[[nodiscard]] inline const std::string & GetBinding(const std::string &Name, const std::string &Default="") { [[nodiscard]] inline const std::string &GetBinding(const std::string &Name,
const std::string &Default = "") {
auto E = Bindings_.find(Poco::toLower(Name)); auto E = Bindings_.find(Poco::toLower(Name));
if (E == Bindings_.end()) if (E == Bindings_.end())
return Default; return Default;
@@ -236,7 +245,8 @@ namespace OpenWifi {
return Return; return Return;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, Types::UUIDvec_t & Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, Types::UUIDvec_t &Value) {
if (O->has(Field) && O->isArray(Field)) { if (O->has(Field) && O->isArray(Field)) {
auto Arr = O->getArray(Field); auto Arr = O->getArray(Field);
for (const auto &i : *Arr) for (const auto &i : *Arr)
@@ -246,7 +256,8 @@ namespace OpenWifi {
return false; return false;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, std::string &Value) {
if (O->has(Field)) { if (O->has(Field)) {
Value = O->get(Field).toString(); Value = O->get(Field).toString();
return true; return true;
@@ -254,7 +265,8 @@ namespace OpenWifi {
return false; return false;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, uint64_t &Value) {
if (O->has(Field)) { if (O->has(Field)) {
Value = O->get(Field); Value = O->get(Field);
return true; return true;
@@ -262,7 +274,8 @@ namespace OpenWifi {
return false; return false;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, bool &Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, bool &Value) {
if (O->has(Field)) { if (O->has(Field)) {
Value = O->get(Field).toString() == "true"; Value = O->get(Field).toString() == "true";
return true; return true;
@@ -270,7 +283,8 @@ namespace OpenWifi {
return false; return false;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, double &Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, double &Value) {
if (O->has(Field)) { if (O->has(Field)) {
Value = (double)O->get(Field); Value = (double)O->get(Field);
return true; return true;
@@ -278,7 +292,8 @@ namespace OpenWifi {
return false; return false;
} }
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, Poco::Data::BLOB &Value) { static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O,
const std::string &Field, Poco::Data::BLOB &Value) {
if (O->has(Field)) { if (O->has(Field)) {
std::string Content = O->get(Field).toString(); std::string Content = O->get(Field).toString();
auto DecodedBlob = Utils::base64decode(Content); auto DecodedBlob = Utils::base64decode(Content);
@@ -288,8 +303,9 @@ namespace OpenWifi {
return false; return false;
} }
template <typename T>
template <typename T> bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, const T &value, T & assignee) { bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field,
const T &value, T &assignee) {
if (O->has(Field)) { if (O->has(Field)) {
assignee = value; assignee = value;
return true; return true;
@@ -342,13 +358,15 @@ namespace OpenWifi {
Response->send(); Response->send();
} }
inline void PrepareResponse(Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK, inline void PrepareResponse(
Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK,
bool CloseConnection = false) { bool CloseConnection = false) {
Response->setStatus(Status); Response->setStatus(Status);
SetCommonHeaders(CloseConnection); SetCommonHeaders(CloseConnection);
} }
inline void BadRequest(const OpenWifi::RESTAPI::Errors::msg &E, const std::string & Extra="") { inline void BadRequest(const OpenWifi::RESTAPI::Errors::msg &E,
const std::string &Extra = "") {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode", 400); ErrorObject.set("ErrorCode", 400);
@@ -356,7 +374,8 @@ namespace OpenWifi {
if (Extra.empty()) if (Extra.empty())
ErrorObject.set("ErrorDescription", fmt::format("{}: {}", E.err_num, E.err_txt)); ErrorObject.set("ErrorDescription", fmt::format("{}: {}", E.err_num, E.err_txt));
else else
ErrorObject.set("ErrorDescription",fmt::format("{}: {} ({})",E.err_num,E.err_txt, Extra)) ; ErrorObject.set("ErrorDescription",
fmt::format("{}: {} ({})", E.err_num, E.err_txt, Extra));
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
@@ -391,11 +410,10 @@ namespace OpenWifi {
ErrorObject.set("ErrorDescription", fmt::format("{}: {}", E.err_num, E.err_txt)); ErrorObject.set("ErrorDescription", fmt::format("{}: {}", E.err_num, E.err_txt));
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
poco_debug(Logger_,fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}", poco_debug(Logger_,
Requester(), fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}", Requester(),
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->getMethod(), Request->getMethod(), Request->getURI()));
Request->getURI()));
} }
inline void OK() { inline void OK() {
@@ -456,7 +474,8 @@ namespace OpenWifi {
Response->sendFile(File.path(), MT.ContentType); Response->sendFile(File.path(), MT.ContentType);
} }
inline void SendFile(Poco::TemporaryFile &TempAvatar, [[maybe_unused]] const std::string &Type, const std::string & Name) { inline void SendFile(Poco::TemporaryFile &TempAvatar,
[[maybe_unused]] const std::string &Type, const std::string &Name) {
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK); Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
SetCommonHeaders(); SetCommonHeaders();
auto MT = Utils::FindMediaType(Name); auto MT = Utils::FindMediaType(Name);
@@ -464,6 +483,7 @@ namespace OpenWifi {
Response->set("Content-Transfer-Encoding", "binary"); Response->set("Content-Transfer-Encoding", "binary");
Response->set("Accept-Ranges", "bytes"); Response->set("Accept-Ranges", "bytes");
} }
Response->set("Access-Control-Expose-Headers", "Content-Disposition");
Response->set("Content-Disposition", "attachment; filename=" + Name); Response->set("Content-Disposition", "attachment; filename=" + Name);
Response->set("Accept-Ranges", "bytes"); Response->set("Accept-Ranges", "bytes");
Response->set("Cache-Control", "no-store"); Response->set("Cache-Control", "no-store");
@@ -472,7 +492,8 @@ namespace OpenWifi {
Response->sendFile(TempAvatar.path(), MT.ContentType); Response->sendFile(TempAvatar.path(), MT.ContentType);
} }
inline void SendFileContent(const std::string &Content, const std::string &Type, const std::string & Name) { inline void SendFileContent(const std::string &Content, [[maybe_unused]] const std::string &Type,
const std::string &Name) {
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK); Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
SetCommonHeaders(); SetCommonHeaders();
auto MT = Utils::FindMediaType(Name); auto MT = Utils::FindMediaType(Name);
@@ -480,18 +501,18 @@ namespace OpenWifi {
Response->set("Content-Transfer-Encoding", "binary"); Response->set("Content-Transfer-Encoding", "binary");
Response->set("Accept-Ranges", "bytes"); Response->set("Accept-Ranges", "bytes");
} }
Response->set("Access-Control-Expose-Headers", "Content-Disposition");
Response->set("Content-Disposition", "attachment; filename=" + Name); Response->set("Content-Disposition", "attachment; filename=" + Name);
Response->set("Accept-Ranges", "bytes"); Response->set("Accept-Ranges", "bytes");
Response->set("Cache-Control", "no-store"); Response->set("Cache-Control", "no-store");
Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT");
Response->setContentLength(Content.size()); Response->setContentLength(Content.size());
Response->setContentType(Type ); Response->setContentType(MT.ContentType);
auto &OutputStream = Response->send(); auto &OutputStream = Response->send();
OutputStream << Content; OutputStream << Content;
} }
inline void SendHTMLFileBack(Poco::File & File, inline void SendHTMLFileBack(Poco::File &File, const Types::StringPairVec &FormVars) {
const Types::StringPairVec & FormVars) {
Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK); Response->setStatus(Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK);
SetCommonHeaders(); SetCommonHeaders();
Response->set("Pragma", "private"); Response->set("Pragma", "private");
@@ -505,7 +526,8 @@ namespace OpenWifi {
ostr << FormContent; ostr << FormContent;
} }
inline void ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status, bool CloseConnection=false) { inline void ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status,
bool CloseConnection = false) {
PrepareResponse(Status, CloseConnection); PrepareResponse(Status, CloseConnection);
if (Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) { if (Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) {
Response->setContentLength(0); Response->setContentLength(0);
@@ -519,7 +541,8 @@ namespace OpenWifi {
if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) { if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) {
ProcessOptions(); ProcessOptions();
return false; return false;
} else if (std::find(Methods_.begin(), Methods_.end(), Request->getMethod()) == Methods_.end()) { } else if (std::find(Methods_.begin(), Methods_.end(), Request->getMethod()) ==
Methods_.end()) {
BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod); BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod);
return false; return false;
} }
@@ -539,7 +562,8 @@ namespace OpenWifi {
AcceptedEncoding->second.find("compress") != std::string::npos) { AcceptedEncoding->second.find("compress") != std::string::npos) {
Response->set("Content-Encoding", "gzip"); Response->set("Content-Encoding", "gzip");
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::DeflatingOutputStream deflater(Answer, Poco::DeflatingStreamBuf::STREAM_GZIP); Poco::DeflatingOutputStream deflater(Answer,
Poco::DeflatingStreamBuf::STREAM_GZIP);
Poco::JSON::Stringifier::stringify(Object, deflater); Poco::JSON::Stringifier::stringify(Object, deflater);
deflater.close(); deflater.close();
return; return;
@@ -560,7 +584,8 @@ namespace OpenWifi {
AcceptedEncoding->second.find("compress") != std::string::npos) { AcceptedEncoding->second.find("compress") != std::string::npos) {
Response->set("Content-Encoding", "gzip"); Response->set("Content-Encoding", "gzip");
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::DeflatingOutputStream deflater(Answer, Poco::DeflatingStreamBuf::STREAM_GZIP); Poco::DeflatingOutputStream deflater(Answer,
Poco::DeflatingStreamBuf::STREAM_GZIP);
deflater << json_doc; deflater << json_doc;
deflater.close(); deflater.close();
return; return;
@@ -605,19 +630,23 @@ namespace OpenWifi {
return true; return true;
} }
[[nodiscard]] inline uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0){ [[nodiscard]] inline uint64_t Get(const char *Parameter, const Poco::JSON::Object::Ptr &Obj,
uint64_t Default = 0) {
if (Obj->has(Parameter)) if (Obj->has(Parameter))
return Obj->get(Parameter); return Obj->get(Parameter);
return Default; return Default;
} }
[[nodiscard]] inline std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default=""){ [[nodiscard]] inline std::string GetS(const char *Parameter,
const Poco::JSON::Object::Ptr &Obj,
const std::string &Default = "") {
if (Obj->has(Parameter)) if (Obj->has(Parameter))
return Obj->get(Parameter).toString(); return Obj->get(Parameter).toString();
return Default; return Default;
} }
[[nodiscard]] inline bool GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default=false){ [[nodiscard]] inline bool GetB(const char *Parameter, const Poco::JSON::Object::Ptr &Obj,
bool Default = false) {
if (Obj->has(Parameter)) if (Obj->has(Parameter))
return Obj->get(Parameter).toString() == "true"; return Obj->get(Parameter).toString() == "true";
return Default; return Default;
@@ -657,6 +686,7 @@ namespace OpenWifi {
SecurityObjects::UserInfoAndPolicy UserInfo_; SecurityObjects::UserInfoAndPolicy UserInfo_;
QueryBlock QB_; QueryBlock QB_;
const std::string &Requester() const { return REST_Requester_; } const std::string &Requester() const { return REST_Requester_; }
protected: protected:
BindingMap Bindings_; BindingMap Bindings_;
Poco::URI::QueryParameters Parameters_; Poco::URI::QueryParameters Parameters_;
@@ -677,29 +707,33 @@ namespace OpenWifi {
}; };
#ifdef TIP_SECURITY_SERVICE #ifdef TIP_SECURITY_SERVICE
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest &Request,
SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired , bool Sub ); std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy &UInfo,
std::uint64_t TID, bool &Expired, bool Sub);
#endif #endif
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , [[maybe_unused]] bool & Contacted , bool Sub ) { inline bool RESTAPIHandler::IsAuthorized(bool &Expired, [[maybe_unused]] bool &Contacted,
bool Sub) {
if (Internal_ && Request->has("X-INTERNAL-NAME")) { if (Internal_ && Request->has("X-INTERNAL-NAME")) {
auto Allowed = MicroServiceIsValidAPIKEY(*Request); auto Allowed = MicroServiceIsValidAPIKEY(*Request);
Contacted = true; Contacted = true;
if (!Allowed) { if (!Allowed) {
if (Server_.LogBadTokens(false)) { if (Server_.LogBadTokens(false)) {
poco_debug(Logger_,fmt::format("I-REQ-DENIED({}): TID={} Method={} Path={}", poco_debug(Logger_,
fmt::format("I-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
TransactionId_, TransactionId_, Request->getMethod(),
Request->getMethod(), Request->getURI())); Request->getURI()));
} }
} else { } else {
auto Id = Request->get("X-INTERNAL-NAME", "unknown"); auto Id = Request->get("X-INTERNAL-NAME", "unknown");
REST_Requester_ = Id; REST_Requester_ = Id;
if (Server_.LogIt(Request->getMethod(), true)) { if (Server_.LogIt(Request->getMethod(), true)) {
poco_debug(Logger_,fmt::format("I-REQ-ALLOWED({}): TID={} User='{}' Method={} Path={}", poco_debug(Logger_,
fmt::format("I-REQ-ALLOWED({}): TID={} User='{}' Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
TransactionId_, TransactionId_, Id, Request->getMethod(),
Id, Request->getURI()));
Request->getMethod(), Request->getURI()));
} }
} }
return Allowed; return Allowed;
@@ -708,27 +742,29 @@ namespace OpenWifi {
bool suspended = false; bool suspended = false;
#ifdef TIP_SECURITY_SERVICE #ifdef TIP_SECURITY_SERVICE
std::uint64_t expiresOn; std::uint64_t expiresOn;
if (AuthService()->IsValidApiKey(SessionToken_, UserInfo_.webtoken, UserInfo_.userinfo, Expired, expiresOn, suspended)) { if (AuthService()->IsValidApiKey(SessionToken_, UserInfo_.webtoken, UserInfo_.userinfo,
Expired, expiresOn, suspended)) {
#else #else
if (AuthClient()->IsValidApiKey( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted, suspended)) { if (AuthClient()->IsValidApiKey(SessionToken_, UserInfo_, TransactionId_, Expired,
Contacted, suspended)) {
#endif #endif
REST_Requester_ = UserInfo_.userinfo.email; REST_Requester_ = UserInfo_.userinfo.email;
if (Server_.LogIt(Request->getMethod(), true)) { if (Server_.LogIt(Request->getMethod(), true)) {
poco_debug(Logger_,fmt::format("X-REQ-ALLOWED({}): APIKEY-ACCESS TID={} User='{}@{}' Method={} Path={}", poco_debug(Logger_,
UserInfo_.userinfo.email, fmt::format("X-REQ-ALLOWED({}): APIKEY-ACCESS TID={} User='{}@{}' "
TransactionId_, "Method={} Path={}",
UserInfo_.userinfo.email, TransactionId_,
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->clientAddress().toString(), Request->clientAddress().toString(),
Request->getMethod(), Request->getMethod(), Request->getURI()));
Request->getURI()));
} }
return true; return true;
} else { } else {
if (Server_.LogBadTokens(true)) { if (Server_.LogBadTokens(true)) {
poco_debug(Logger_,fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}", poco_debug(Logger_,
fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
TransactionId_, TransactionId_, Request->getMethod(),
Request->getMethod(),
Request->getURI())); Request->getURI()));
} }
} }
@@ -745,27 +781,29 @@ namespace OpenWifi {
} }
} }
#ifdef TIP_SECURITY_SERVICE #ifdef TIP_SECURITY_SERVICE
if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, TransactionId_, Expired, Sub)) { if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, TransactionId_, Expired,
Sub)) {
#else #else
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted, Sub)) { if (AuthClient()->IsAuthorized(SessionToken_, UserInfo_, TransactionId_, Expired,
Contacted, Sub)) {
#endif #endif
REST_Requester_ = UserInfo_.userinfo.email; REST_Requester_ = UserInfo_.userinfo.email;
if (Server_.LogIt(Request->getMethod(), true)) { if (Server_.LogIt(Request->getMethod(), true)) {
poco_debug(Logger_,fmt::format("X-REQ-ALLOWED({}): TID={} User='{}@{}' Method={} Path={}", poco_debug(
UserInfo_.userinfo.email, Logger_,
TransactionId_, fmt::format("X-REQ-ALLOWED({}): TID={} User='{}@{}' Method={} Path={}",
UserInfo_.userinfo.email, TransactionId_,
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
Request->clientAddress().toString(), Request->clientAddress().toString(), Request->getMethod(),
Request->getMethod(),
Request->getURI())); Request->getURI()));
} }
return true; return true;
} else { } else {
if (Server_.LogBadTokens(true)) { if (Server_.LogBadTokens(true)) {
poco_debug(Logger_,fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}", poco_debug(Logger_,
fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Utils::FormatIPv6(Request->clientAddress().toString()),
TransactionId_, TransactionId_, Request->getMethod(),
Request->getMethod(),
Request->getURI())); Request->getURI()));
} }
} }
@@ -775,8 +813,11 @@ namespace OpenWifi {
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler { class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
public: public:
RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServerAccounting & Server, uint64_t TransactionId, bool Internal) RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
: RESTAPIHandler(bindings, L, std::vector<std::string>{}, Server, TransactionId, Internal) {} RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, std::vector<std::string>{}, Server, TransactionId,
Internal) {}
inline void DoGet() override{}; inline void DoGet() override{};
inline void DoPost() override{}; inline void DoPost() override{};
inline void DoPut() override{}; inline void DoPut() override{};
@@ -784,35 +825,37 @@ namespace OpenWifi {
}; };
template <class T> template <class T>
constexpr auto test_has_PathName_method(T*) constexpr auto test_has_PathName_method(T *) -> decltype(T::PathName(), std::true_type{}) {
-> decltype( T::PathName() , std::true_type{} )
{
return std::true_type{}; return std::true_type{};
} }
constexpr auto test_has_PathName_method(...) -> std::false_type constexpr auto test_has_PathName_method(...) -> std::false_type { return std::false_type{}; }
{
return std::false_type{};
}
template <typename T, typename... Args> template <typename T, typename... Args>
RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, RESTAPIHandler *RESTAPI_Router(const std::string &RequestedPath,
Poco::Logger & Logger, RESTAPI_GenericServerAccounting & Server, uint64_t TransactionId) { RESTAPIHandler::BindingMap &Bindings, Poco::Logger &Logger,
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId) {
static_assert(test_has_PathName_method((T *)nullptr),
"Class must have a static PathName() method.");
if (RESTAPIHandler::ParseBindings(RequestedPath, T::PathName(), Bindings)) { if (RESTAPIHandler::ParseBindings(RequestedPath, T::PathName(), Bindings)) {
return new T(Bindings, Logger, Server, TransactionId, false); return new T(Bindings, Logger, Server, TransactionId, false);
} }
if constexpr (sizeof...(Args) == 0) { if constexpr (sizeof...(Args) == 0) {
return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server, TransactionId, false); return new RESTAPI_UnknownRequestHandler(Bindings, Logger, Server, TransactionId,
false);
} else { } else {
return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger, Server, TransactionId); return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger, Server, TransactionId);
} }
} }
template <typename T, typename... Args> template <typename T, typename... Args>
RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, RESTAPIHandler *RESTAPI_Router_I(const std::string &RequestedPath,
Poco::Logger & Logger, RESTAPI_GenericServerAccounting & Server, uint64_t TransactionId) { RESTAPIHandler::BindingMap &Bindings, Poco::Logger &Logger,
static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId) {
static_assert(test_has_PathName_method((T *)nullptr),
"Class must have a static PathName() method.");
if (RESTAPIHandler::ParseBindings(RequestedPath, T::PathName(), Bindings)) { if (RESTAPIHandler::ParseBindings(RequestedPath, T::PathName(), Bindings)) {
return new T(Bindings, Logger, Server, TransactionId, true); return new T(Bindings, Logger, Server, TransactionId, true);
} }
@@ -820,7 +863,8 @@ namespace OpenWifi {
if constexpr (sizeof...(Args) == 0) { if constexpr (sizeof...(Args) == 0) {
return new RESTAPI_UnknownRequestHandler(Bindings, Logger, Server, TransactionId, true); return new RESTAPI_UnknownRequestHandler(Bindings, Logger, Server, TransactionId, true);
} else { } else {
return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger, Server, TransactionId); return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger, Server,
TransactionId);
} }
} }

View File

@@ -6,18 +6,21 @@
#include "Poco/Net/HTTPServer.h" #include "Poco/Net/HTTPServer.h"
#include "framework/SubSystemServer.h"
#include "framework/RESTAPI_Handler.h" #include "framework/RESTAPI_Handler.h"
#include "framework/SubSystemServer.h"
namespace OpenWifi { namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings, Poco::Net::HTTPRequestHandler *
RESTAPI_IntRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger &L, RESTAPI_GenericServerAccounting &S, uint64_t Id); Poco::Logger &L, RESTAPI_GenericServerAccounting &S, uint64_t Id);
class IntRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { class IntRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public: public:
inline IntRequestHandlerFactory() = default; inline IntRequestHandlerFactory() = default;
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override; Poco::Net::HTTPRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override;
private: private:
static inline std::atomic_uint64_t NextTransactionId_ = 1; static inline std::atomic_uint64_t NextTransactionId_ = 1;
}; };
@@ -36,10 +39,15 @@ namespace OpenWifi {
for (const auto &Svr : ConfigServersList_) { for (const auto &Svr : ConfigServersList_) {
if (MicroServiceNoAPISecurity()) { if (MicroServiceNoAPISecurity()) {
poco_information(Logger(),fmt::format("Starting: {}:{}. Security has been disabled for APIs.", Svr.Address(), Svr.Port())); poco_information(
Logger(),
fmt::format("Starting: {}:{}. Security has been disabled for APIs.",
Svr.Address(), Svr.Port()));
} else { } else {
poco_information(Logger(),fmt::format("Starting: {}:{}. Keyfile:{} CertFile: {}", Svr.Address(), Svr.Port(), poco_information(Logger(),
Svr.KeyFile(),Svr.CertFile())); fmt::format("Starting: {}:{}. Keyfile:{} CertFile: {}",
Svr.Address(), Svr.Port(), Svr.KeyFile(),
Svr.CertFile()));
Svr.LogCert(Logger()); Svr.LogCert(Logger());
if (!Svr.RootCA().empty()) if (!Svr.RootCA().empty())
Svr.LogCas(Logger()); Svr.LogCas(Logger());
@@ -52,10 +60,12 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::HTTPServer> NewServer; std::unique_ptr<Poco::Net::HTTPServer> NewServer;
if (MicroServiceNoAPISecurity()) { if (MicroServiceNoAPISecurity()) {
auto Sock{Svr.CreateSocket(Logger())}; auto Sock{Svr.CreateSocket(Logger())};
NewServer = std::make_unique<Poco::Net::HTTPServer>(new IntRequestHandlerFactory, Pool_, Sock, Params); NewServer = std::make_unique<Poco::Net::HTTPServer>(
new IntRequestHandlerFactory, Pool_, Sock, Params);
} else { } else {
auto Sock{Svr.CreateSecureSocket(Logger())}; auto Sock{Svr.CreateSecureSocket(Logger())};
NewServer = std::make_unique<Poco::Net::HTTPServer>(new IntRequestHandlerFactory, Pool_, Sock, Params); NewServer = std::make_unique<Poco::Net::HTTPServer>(
new IntRequestHandlerFactory, Pool_, Sock, Params);
}; };
NewServer->start(); NewServer->start();
RESTServers_.push_back(std::move(NewServer)); RESTServers_.push_back(std::move(NewServer));
@@ -86,19 +96,16 @@ namespace OpenWifi {
return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id); return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id);
} }
const Poco::ThreadPool &Pool() { return Pool_; } const Poco::ThreadPool &Pool() { return Pool_; }
private: private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_; std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_{"i-rest", 4, 64}; Poco::ThreadPool Pool_{"i-rest", 4, 64};
RESTAPI_GenericServerAccounting Server_; RESTAPI_GenericServerAccounting Server_;
RESTAPI_IntServer() noexcept: RESTAPI_IntServer() noexcept
SubSystemServer("RESTAPI_IntServer", "REST-ISRV", "openwifi.internal.restapi") : SubSystemServer("RESTAPI_IntServer", "REST-ISRV", "openwifi.internal.restapi") {}
{
}
}; };
inline auto RESTAPI_IntServer() { return RESTAPI_IntServer::instance(); }; inline auto RESTAPI_IntServer() { return RESTAPI_IntServer::instance(); };
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -4,29 +4,26 @@
#pragma once #pragma once
#include <string>
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/CountingStream.h" #include "Poco/CountingStream.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/NullStream.h" #include "Poco/NullStream.h"
#include "Poco/StreamCopier.h" #include "Poco/StreamCopier.h"
#include <string>
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_PartHandler : public Poco::Net::PartHandler { class RESTAPI_PartHandler : public Poco::Net::PartHandler {
public: public:
RESTAPI_PartHandler(): RESTAPI_PartHandler() : _length(0) {}
_length(0)
{
}
inline void handlePart(const Poco::Net::MessageHeader& header, std::istream& stream) override inline void handlePart(const Poco::Net::MessageHeader &header,
{ std::istream &stream) override {
_type = header.get("Content-Type", "(unspecified)"); _type = header.get("Content-Type", "(unspecified)");
if (header.has("Content-Disposition")) if (header.has("Content-Disposition")) {
{
std::string disp; std::string disp;
Poco::Net::NameValueCollection params; Poco::Net::NameValueCollection params;
Poco::Net::MessageHeader::splitParameters(header["Content-Disposition"], disp, params); Poco::Net::MessageHeader::splitParameters(header["Content-Disposition"], disp,
params);
_name = params.get("name", "(unnamed)"); _name = params.get("name", "(unnamed)");
_fileName = params.get("filename", "(unnamed)"); _fileName = params.get("filename", "(unnamed)");
} }
@@ -37,25 +34,13 @@ namespace OpenWifi {
_length = (int)istr.chars(); _length = (int)istr.chars();
} }
[[nodiscard]] inline int length() const [[nodiscard]] inline int length() const { return _length; }
{
return _length;
}
[[nodiscard]] inline const std::string& name() const [[nodiscard]] inline const std::string &name() const { return _name; }
{
return _name;
}
[[nodiscard]] inline const std::string& fileName() const [[nodiscard]] inline const std::string &fileName() const { return _fileName; }
{
return _fileName;
}
[[nodiscard]] inline const std::string& contentType() const [[nodiscard]] inline const std::string &contentType() const { return _type; }
{
return _type;
}
private: private:
int _length; int _length;
@@ -63,4 +48,4 @@ namespace OpenWifi {
std::string _name; std::string _name;
std::string _fileName; std::string _fileName;
}; };
} } // namespace OpenWifi

View File

@@ -6,9 +6,9 @@
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include "Poco/URI.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/ExpireLRUCache.h" #include "Poco/ExpireLRUCache.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/URI.h"
#include "fmt/format.h" #include "fmt/format.h"
@@ -16,7 +16,6 @@ namespace OpenWifi {
class RESTAPI_RateLimiter : public SubSystemServer { class RESTAPI_RateLimiter : public SubSystemServer {
public: public:
struct ClientCacheEntry { struct ClientCacheEntry {
int64_t Start = 0; int64_t Start = 0;
int Count = 0; int Count = 0;
@@ -30,11 +29,14 @@ namespace OpenWifi {
inline int Start() final { return 0; }; inline int Start() final { return 0; };
inline void Stop() final{}; inline void Stop() final{};
inline bool IsRateLimited(const Poco::Net::HTTPServerRequest &R, int64_t Period, int64_t MaxCalls) { inline bool IsRateLimited(const Poco::Net::HTTPServerRequest &R, int64_t Period,
int64_t MaxCalls) {
Poco::URI uri(R.getURI()); Poco::URI uri(R.getURI());
auto H = str_hash(uri.getPath() + R.clientAddress().host().toString()); auto H = str_hash(uri.getPath() + R.clientAddress().host().toString());
auto E = Cache_.get(H); auto E = Cache_.get(H);
auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
if (E.isNull()) { if (E.isNull()) {
Cache_.add(H, ClientCacheEntry{.Start = Now, .Count = 1}); Cache_.add(H, ClientCacheEntry{.Start = Now, .Count = 1});
return false; return false;
@@ -43,7 +45,8 @@ namespace OpenWifi {
E->Count++; E->Count++;
Cache_.update(H, E); Cache_.update(H, E);
if (E->Count > MaxCalls) { if (E->Count > MaxCalls) {
poco_warning(Logger(),fmt::format("RATE-LIMIT-EXCEEDED: from '{}'", R.clientAddress().toString())); poco_warning(Logger(), fmt::format("RATE-LIMIT-EXCEEDED: from '{}'",
R.clientAddress().toString()));
return true; return true;
} }
return false; return false;
@@ -54,22 +57,16 @@ namespace OpenWifi {
return false; return false;
} }
inline void Clear() { inline void Clear() { Cache_.clear(); }
Cache_.clear();
}
private: private:
Poco::ExpireLRUCache<uint64_t, ClientCacheEntry> Cache_{2048}; Poco::ExpireLRUCache<uint64_t, ClientCacheEntry> Cache_{2048};
std::hash<std::string> str_hash; std::hash<std::string> str_hash;
RESTAPI_RateLimiter() noexcept: RESTAPI_RateLimiter() noexcept
SubSystemServer("RateLimiter", "RATE-LIMITER", "rate.limiter") : SubSystemServer("RateLimiter", "RATE-LIMITER", "rate.limiter") {}
{
}
}; };
inline auto RESTAPI_RateLimiter() { return RESTAPI_RateLimiter::instance(); } inline auto RESTAPI_RateLimiter() { return RESTAPI_RateLimiter::instance(); }
} // namespace OpenWifi
}

View File

@@ -14,14 +14,14 @@ namespace OpenWifi {
class RESTAPI_system_command : public RESTAPIHandler { class RESTAPI_system_command : public RESTAPIHandler {
public: public:
RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServerAccounting & Server, uint64_t TransactionId, bool Internal) RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server, TransactionId, Internal) {}
TransactionId,
Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/system"}; } static auto PathName() { return std::list<std::string>{"/api/v1/system"}; }
inline void DoGet() { inline void DoGet() {
@@ -88,7 +88,8 @@ namespace OpenWifi {
auto Name = GetS(RESTAPI::Protocol::TAG, InnerObj); auto Name = GetS(RESTAPI::Protocol::TAG, InnerObj);
auto Value = GetS(RESTAPI::Protocol::VALUE, InnerObj); auto Value = GetS(RESTAPI::Protocol::VALUE, InnerObj);
MicroServiceSetSubsystemLogLevel(Name, Value); MicroServiceSetSubsystemLogLevel(Name, Value);
poco_information(Logger_, poco_information(
Logger_,
fmt::format("Setting log level for {} at {}", Name, Value)); fmt::format("Setting log level for {} at {}", Name, Value));
} }
} }
@@ -154,4 +155,4 @@ namespace OpenWifi {
void DoDelete() final{}; void DoDelete() final{};
}; };
} } // namespace OpenWifi

View File

@@ -4,32 +4,33 @@
#pragma once #pragma once
#include "framework/RESTAPI_Handler.h"
#include "Poco/Net/WebSocket.h" #include "Poco/Net/WebSocket.h"
#include "framework/RESTAPI_Handler.h"
#include "framework/UI_WebSocketClientServer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/UI_WebSocketClientServer.h"
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_webSocketServer : public RESTAPIHandler { class RESTAPI_webSocketServer : public RESTAPIHandler {
public: public:
inline RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId, bool Internal) inline RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server,
uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET, std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal, false) {} Server, TransactionId, Internal, false) {}
static auto PathName() { return std::list<std::string>{"/api/v1/ws"}; } static auto PathName() { return std::list<std::string>{"/api/v1/ws"}; }
void DoGet() final { void DoGet() final {
try try {
{ if (Request->find("Upgrade") != Request->end() &&
if(Request->find("Upgrade") != Request->end() && Poco::icompare((*Request)["Upgrade"], "websocket") == 0) { Poco::icompare((*Request)["Upgrade"], "websocket") == 0) {
try try {
{
Poco::Net::WebSocket WS(*Request, *Response); Poco::Net::WebSocket WS(*Request, *Response);
auto Id = MicroServiceCreateUUID(); auto Id = MicroServiceCreateUUID();
UI_WebSocketClientServer()->NewClient(WS,Id,UserInfo_.userinfo.email, TransactionId_); UI_WebSocketClientServer()->NewClient(WS, Id, UserInfo_.userinfo.email,
} TransactionId_);
catch (...) { } catch (...) {
std::cout << "Cannot create websocket client..." << std::endl; std::cout << "Cannot create websocket client..." << std::endl;
} }
} }
@@ -40,6 +41,7 @@ namespace OpenWifi {
void DoDelete() final{}; void DoDelete() final{};
void DoPost() final{}; void DoPost() final{};
void DoPut() final{}; void DoPut() final{};
private: private:
}; };
} } // namespace OpenWifi

View File

@@ -6,17 +6,25 @@
#include <string> #include <string>
#include "Poco/Data/LOB.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/Data/LOB.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "framework/utils.h" #include "framework/utils.h"
#include <RESTObjects/RESTAPI_SecurityObjects.h>
namespace OpenWifi::RESTAPI_utils { namespace OpenWifi::RESTAPI_utils {
inline void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr) { inline bool IsRootOrAdmin(const SecurityObjects::UserInfo &UI) {
return UI.userRole==SecurityObjects::ROOT ||
UI.userRole==SecurityObjects::ADMIN;
}
inline void EmbedDocument(const std::string &ObjName, Poco::JSON::Object &Obj,
const std::string &ObjStr) {
std::string D = ObjStr.empty() ? "{}" : ObjStr; std::string D = ObjStr.empty() ? "{}" : ObjStr;
Poco::JSON::Parser P; Poco::JSON::Parser P;
Poco::Dynamic::Var result = P.parse(D); Poco::Dynamic::Var result = P.parse(D);
@@ -68,12 +76,14 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, Value); Obj.set(Field, Value);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Poco::Data::BLOB &Value) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field,
const Poco::Data::BLOB &Value) {
auto Result = Utils::base64encode((const unsigned char *)Value.rawContent(), Value.size()); auto Result = Utils::base64encode((const unsigned char *)Value.rawContent(), Value.size());
Obj.set(Field, Result); Obj.set(Field, Result);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringPairVec & S) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field,
const Types::StringPairVec &S) {
Poco::JSON::Array Array; Poco::JSON::Array Array;
for (const auto &i : S) { for (const auto &i : S) {
Poco::JSON::Object O; Poco::JSON::Object O;
@@ -84,7 +94,8 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, Array); Obj.set(Field, Array);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringVec &V) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field,
const Types::StringVec &V) {
Poco::JSON::Array A; Poco::JSON::Array A;
for (const auto &i : V) for (const auto &i : V)
A.add(i); A.add(i);
@@ -98,7 +109,8 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, A); Obj.set(Field, A);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::CountedMap &M) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field,
const Types::CountedMap &M) {
Poco::JSON::Array A; Poco::JSON::Array A;
for (const auto &[Key, Value] : M) { for (const auto &[Key, Value] : M) {
Poco::JSON::Object O; Poco::JSON::Object O;
@@ -109,7 +121,8 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, A); Obj.set(Field, A);
} }
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::Counted3DMapSII &M) { inline void field_to_json(Poco::JSON::Object &Obj, const char *Field,
const Types::Counted3DMapSII &M) {
Poco::JSON::Array A; Poco::JSON::Array A;
for (const auto &[OrgName, MonthlyNumberMap] : M) { for (const auto &[OrgName, MonthlyNumberMap] : M) {
Poco::JSON::Object OrgObject; Poco::JSON::Object OrgObject;
@@ -127,14 +140,14 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, A); Obj.set(Field, A);
} }
template<typename T> void field_to_json(Poco::JSON::Object &Obj, template <typename T>
const char *Field, void field_to_json(Poco::JSON::Object &Obj, const char *Field, const T &V,
const T &V,
std::function<std::string(const T &)> F) { std::function<std::string(const T &)> F) {
Obj.set(Field, F(V)); Obj.set(Field, F(V));
} }
template<class T> void field_to_json(Poco::JSON::Object &Obj, const char *Field, const std::vector<T> &Value) { template <class T>
void field_to_json(Poco::JSON::Object &Obj, const char *Field, const std::vector<T> &Value) {
Poco::JSON::Array Arr; Poco::JSON::Array Arr;
for (const auto &i : Value) { for (const auto &i : Value) {
Poco::JSON::Object AO; Poco::JSON::Object AO;
@@ -144,7 +157,8 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field, Arr); Obj.set(Field, Arr);
} }
template<class T> void field_to_json(Poco::JSON::Object &Obj, const char *Field, const T &Value) { template <class T>
void field_to_json(Poco::JSON::Object &Obj, const char *Field, const T &Value) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
Value.to_json(Answer); Value.to_json(Answer);
Obj.set(Field, Answer); Obj.set(Field, Answer);
@@ -155,71 +169,84 @@ namespace OpenWifi::RESTAPI_utils {
/////////////////////////// ///////////////////////////
/////////////////////////// ///////////////////////////
template<typename T> bool field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T & V, template <typename T>
bool field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T &V,
std::function<T(const std::string &)> F) { std::function<T(const std::string &)> F) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
V = F(Obj->get(Field).toString()); V = F(Obj->get(Field).toString());
return true; return true;
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, std::string &S) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
std::string &S) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
S = Obj->get(Field).toString(); S = Obj->get(Field).toString();
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, double & Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
double &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (double)Obj->get(Field); Value = (double)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, float & Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
float &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (float)Obj->get(Field); Value = (float)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, bool &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
bool &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (Obj->get(Field).toString() == "true"); Value = (Obj->get(Field).toString() == "true");
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, int16_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
int16_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (int16_t)Obj->get(Field); Value = (int16_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, int32_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
int32_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (int32_t)Obj->get(Field); Value = (int32_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, int64_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
int64_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (int64_t)Obj->get(Field); Value = (int64_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint16_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
uint16_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (uint16_t)Obj->get(Field); Value = (uint16_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint32_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
uint32_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (uint32_t)Obj->get(Field); Value = (uint32_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint64_t &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
uint64_t &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) if (Obj->has(Field) && !Obj->isNull(Field))
Value = (uint64_t)Obj->get(Field); Value = (uint64_t)Obj->get(Field);
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Poco::Data::BLOB &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Poco::Data::BLOB &Value) {
if (Obj->has(Field) && !Obj->isNull(Field)) { if (Obj->has(Field) && !Obj->isNull(Field)) {
auto Result = Utils::base64decode(Obj->get(Field).toString()); auto Result = Utils::base64decode(Obj->get(Field).toString());
Value.assignRaw((const unsigned char *)&Result[0], Result.size()); Value.assignRaw((const unsigned char *)&Result[0], Result.size());
} }
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::StringPairVec &Vec) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Types::StringPairVec &Vec) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) { if (Obj->isArray(Field) && !Obj->isNull(Field)) {
auto O = Obj->getArray(Field); auto O = Obj->getArray(Field);
for (const auto &i : *O) { for (const auto &i : *O) {
@@ -235,7 +262,8 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::StringVec &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Types::StringVec &Value) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) { if (Obj->isArray(Field) && !Obj->isNull(Field)) {
Value.clear(); Value.clear();
Poco::JSON::Array::Ptr A = Obj->getArray(Field); Poco::JSON::Array::Ptr A = Obj->getArray(Field);
@@ -245,7 +273,8 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::TagList &Value) { inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
Types::TagList &Value) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) { if (Obj->isArray(Field) && !Obj->isNull(Field)) {
Value.clear(); Value.clear();
Poco::JSON::Array::Ptr A = Obj->getArray(Field); Poco::JSON::Array::Ptr A = Obj->getArray(Field);
@@ -255,7 +284,9 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
template<class T> void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, std::vector<T> &Value) { template <class T>
void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field,
std::vector<T> &Value) {
if (Obj->isArray(Field) && !Obj->isNull(Field)) { if (Obj->isArray(Field) && !Obj->isNull(Field)) {
Poco::JSON::Array::Ptr Arr = Obj->getArray(Field); Poco::JSON::Array::Ptr Arr = Obj->getArray(Field);
for (auto &i : *Arr) { for (auto &i : *Arr) {
@@ -267,7 +298,8 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
template<class T> void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T &Value) { template <class T>
void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, T &Value) {
if (Obj->isObject(Field) && !Obj->isNull(Field)) { if (Obj->isObject(Field) && !Obj->isNull(Field)) {
Poco::JSON::Object::Ptr A = Obj->getObject(Field); Poco::JSON::Object::Ptr A = Obj->getObject(Field);
Value.from_json(A); Value.from_json(A);
@@ -336,7 +368,8 @@ namespace OpenWifi::RESTAPI_utils {
for (auto const &j : i) { for (auto const &j : i) {
if constexpr (std::is_integral<T>::value) { if constexpr (std::is_integral<T>::value) {
InnerArr.add(j); InnerArr.add(j);
} if constexpr(std::is_same_v<T,std::string>) { }
if constexpr (std::is_same_v<T, std::string>) {
InnerArr.add(j); InnerArr.add(j);
} else { } else {
InnerArr.add(j); InnerArr.add(j);
@@ -373,7 +406,6 @@ namespace OpenWifi::RESTAPI_utils {
Result.push_back(i.toString()); Result.push_back(i.toString());
} }
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
@@ -390,7 +422,6 @@ namespace OpenWifi::RESTAPI_utils {
Result.push_back(i); Result.push_back(i);
} }
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
@@ -411,7 +442,6 @@ namespace OpenWifi::RESTAPI_utils {
} }
} }
} catch (...) { } catch (...) {
} }
return R; return R;
@@ -432,12 +462,12 @@ namespace OpenWifi::RESTAPI_utils {
Result.push_back(Obj); Result.push_back(Obj);
} }
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
template<class T> std::vector<std::vector<T>> to_array_of_array_of_object(const std::string & ObjectString) { template <class T>
std::vector<std::vector<T>> to_array_of_array_of_object(const std::string &ObjectString) {
std::vector<std::vector<T>> Result; std::vector<std::vector<T>> Result;
if (ObjectString.empty()) if (ObjectString.empty())
return Result; return Result;
@@ -457,7 +487,6 @@ namespace OpenWifi::RESTAPI_utils {
Result.push_back(InnerVector); Result.push_back(InnerVector);
} }
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
@@ -481,4 +510,4 @@ namespace OpenWifi::RESTAPI_utils {
Obj.from_json(RawObject); Obj.from_json(RawObject);
return true; return true;
} }
} } // namespace OpenWifi::RESTAPI_utils

View File

@@ -4,32 +4,25 @@
#pragma once #pragma once
#include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include "Poco/Data/SessionPool.h" #include "Poco/Data/SessionPool.h"
#include "Poco/Data/SQLite/Connector.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#ifndef SMALL_BUILD #ifndef SMALL_BUILD
#include "Poco/Data/PostgreSQL/Connector.h"
#include "Poco/Data/MySQL/Connector.h" #include "Poco/Data/MySQL/Connector.h"
#include "Poco/Data/PostgreSQL/Connector.h"
#endif #endif
#include "framework/SubSystemServer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/SubSystemServer.h"
namespace OpenWifi { namespace OpenWifi {
enum DBType { enum DBType { sqlite, pgsql, mysql };
sqlite,
pgsql,
mysql
};
class StorageClass : public SubSystemServer { class StorageClass : public SubSystemServer {
public: public:
StorageClass() noexcept: StorageClass() noexcept : SubSystemServer("StorageClass", "STORAGE-SVR", "storage") {}
SubSystemServer("StorageClass", "STORAGE-SVR", "storage")
{
}
int Start() override { int Start() override {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
@@ -47,11 +40,10 @@ namespace OpenWifi {
return 0; return 0;
} }
void Stop() override { void Stop() override { Pool_->shutdown(); }
Pool_->shutdown();
}
DBType Type() const { return dbType_; }; DBType Type() const { return dbType_; };
private: private:
inline int Setup_SQLite(); inline int Setup_SQLite();
inline int Setup_MySQL(); inline int Setup_MySQL();
@@ -66,20 +58,29 @@ namespace OpenWifi {
}; };
#ifdef SMALL_BUILD #ifdef SMALL_BUILD
int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } int Service::Setup_MySQL() {
int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } Daemon()->exit(Poco::Util::Application::EXIT_CONFIG);
return 0;
}
int Service::Setup_PostgreSQL() {
Daemon()->exit(Poco::Util::Application::EXIT_CONFIG);
return 0;
}
#else #else
inline int StorageClass::Setup_SQLite() { inline int StorageClass::Setup_SQLite() {
Logger().notice("SQLite StorageClass enabled."); Logger().notice("SQLite StorageClass enabled.");
dbType_ = sqlite; dbType_ = sqlite;
auto DBName = MicroServiceDataDirectory() + "/" + MicroServiceConfigGetString("storage.type.sqlite.db",""); auto DBName = MicroServiceDataDirectory() + "/" +
MicroServiceConfigGetString("storage.type.sqlite.db", "");
int NumSessions = (int)MicroServiceConfigGetInt("storage.type.sqlite.maxsessions", 64); int NumSessions = (int)MicroServiceConfigGetInt("storage.type.sqlite.maxsessions", 64);
int IdleTime = (int)MicroServiceConfigGetInt("storage.type.sqlite.idletime", 60); int IdleTime = (int)MicroServiceConfigGetInt("storage.type.sqlite.idletime", 60);
Poco::Data::SQLite::Connector::registerConnector(); Poco::Data::SQLite::Connector::registerConnector();
// Pool_ = std::make_unique<Poco::Data::SessionPool>(new Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 8, // Pool_ = std::make_unique<Poco::Data::SessionPool>(new
// (int)NumSessions, (int)IdleTime)); // Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 8,
// (int)NumSessions,
// (int)IdleTime));
Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_.name(), DBName, 8, Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_.name(), DBName, 8,
(int)NumSessions, (int)IdleTime); (int)NumSessions, (int)IdleTime);
return 0; return 0;
@@ -96,16 +97,13 @@ namespace OpenWifi {
auto Database = MicroServiceConfigGetString("storage.type.mysql.database", ""); auto Database = MicroServiceConfigGetString("storage.type.mysql.database", "");
auto Port = MicroServiceConfigGetString("storage.type.mysql.port", ""); auto Port = MicroServiceConfigGetString("storage.type.mysql.port", "");
std::string ConnectionStr = std::string ConnectionStr = "host=" + Host + ";user=" + Username + ";password=" + Password +
"host=" + Host + ";db=" + Database + ";port=" + Port +
";user=" + Username +
";password=" + Password +
";db=" + Database +
";port=" + Port +
";compress=true;auto-reconnect=true"; ";compress=true;auto-reconnect=true";
Poco::Data::MySQL::Connector::registerConnector(); Poco::Data::MySQL::Connector::registerConnector();
Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_.name(), ConnectionStr, 8, NumSessions, IdleTime); Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_.name(), ConnectionStr, 8,
NumSessions, IdleTime);
return 0; return 0;
} }
@@ -120,21 +118,19 @@ namespace OpenWifi {
auto Password = MicroServiceConfigGetString("storage.type.postgresql.password", ""); auto Password = MicroServiceConfigGetString("storage.type.postgresql.password", "");
auto Database = MicroServiceConfigGetString("storage.type.postgresql.database", ""); auto Database = MicroServiceConfigGetString("storage.type.postgresql.database", "");
auto Port = MicroServiceConfigGetString("storage.type.postgresql.port", ""); auto Port = MicroServiceConfigGetString("storage.type.postgresql.port", "");
auto ConnectionTimeout = MicroServiceConfigGetString("storage.type.postgresql.connectiontimeout", ""); auto ConnectionTimeout =
MicroServiceConfigGetString("storage.type.postgresql.connectiontimeout", "");
std::string ConnectionStr = std::string ConnectionStr = "host=" + Host + " user=" + Username + " password=" + Password +
"host=" + Host + " dbname=" + Database + " port=" + Port +
" user=" + Username +
" password=" + Password +
" dbname=" + Database +
" port=" + Port +
" connect_timeout=" + ConnectionTimeout; " connect_timeout=" + ConnectionTimeout;
Poco::Data::PostgreSQL::Connector::registerConnector(); Poco::Data::PostgreSQL::Connector::registerConnector();
Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_.name(), ConnectionStr, 8, NumSessions, IdleTime); Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_.name(), ConnectionStr, 8,
NumSessions, IdleTime);
return 0; return 0;
} }
#endif #endif
} } // namespace OpenWifi

View File

@@ -6,36 +6,29 @@
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h" #include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/Net/SSLManager.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
PropertiesFileServerEntry::PropertiesFileServerEntry(std::string Address, uint32_t port, std::string Key_file, PropertiesFileServerEntry::PropertiesFileServerEntry(
std::string Cert_file, std::string RootCa, std::string Issuer, std::string Address, uint32_t port, std::string Key_file, std::string Cert_file,
std::string ClientCas, std::string Cas, std::string RootCa, std::string Issuer, std::string ClientCas, std::string Cas,
std::string Key_file_password, std::string Name, std::string Key_file_password, std::string Name, Poco::Net::Context::VerificationMode M,
Poco::Net::Context::VerificationMode M,
int backlog) int backlog)
: address_(std::move(Address)), : address_(std::move(Address)), port_(port), cert_file_(std::move(Cert_file)),
port_(port), key_file_(std::move(Key_file)), root_ca_(std::move(RootCa)),
cert_file_(std::move(Cert_file)), key_file_password_(std::move(Key_file_password)), issuer_cert_file_(std::move(Issuer)),
key_file_(std::move(Key_file)), client_cas_(std::move(ClientCas)), cas_(std::move(Cas)), name_(std::move(Name)),
root_ca_(std::move(RootCa)), backlog_(backlog), level_(M){
key_file_password_(std::move(Key_file_password)),
issuer_cert_file_(std::move(Issuer)),
client_cas_(std::move(ClientCas)),
cas_(std::move(Cas)),
name_(std::move(Name)),
backlog_(backlog),
level_(M) {
}; };
[[nodiscard]] Poco::Net::SecureServerSocket PropertiesFileServerEntry::CreateSecureSocket(Poco::Logger &L) const { [[nodiscard]] Poco::Net::SecureServerSocket
PropertiesFileServerEntry::CreateSecureSocket(Poco::Logger &L) const {
Poco::Net::Context::Params P; Poco::Net::Context::Params P;
P.verificationMode = level_; P.verificationMode = level_;
@@ -45,10 +38,12 @@ namespace OpenWifi {
P.dhUse2048Bits = true; P.dhUse2048Bits = true;
P.caLocation = cas_; P.caLocation = cas_;
auto Context = Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P)); auto Context = Poco::AutoPtr<Poco::Net::Context>(
new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P));
if (!key_file_password_.empty()) { if (!key_file_password_.empty()) {
auto PassphraseHandler = Poco::SharedPtr<MyPrivateKeyPassphraseHandler>( new MyPrivateKeyPassphraseHandler(key_file_password_,L)); auto PassphraseHandler = Poco::SharedPtr<MyPrivateKeyPassphraseHandler>(
new MyPrivateKeyPassphraseHandler(key_file_password_, L));
Poco::Net::SSLManager::instance().initializeServer(PassphraseHandler, nullptr, Context); Poco::Net::SSLManager::instance().initializeServer(PassphraseHandler, nullptr, Context);
} }
@@ -111,7 +106,8 @@ namespace OpenWifi {
} }
} }
[[nodiscard]] Poco::Net::ServerSocket PropertiesFileServerEntry::CreateSocket([[maybe_unused]] Poco::Logger &L) const { [[nodiscard]] Poco::Net::ServerSocket
PropertiesFileServerEntry::CreateSocket([[maybe_unused]] Poco::Logger &L) const {
Poco::Net::Context::Params P; Poco::Net::Context::Params P;
if (address_ == "*") { if (address_ == "*") {
@@ -127,19 +123,24 @@ namespace OpenWifi {
} }
} }
void PropertiesFileServerEntry::LogCertInfo(Poco::Logger &L, const Poco::Crypto::X509Certificate &C) const { void PropertiesFileServerEntry::LogCertInfo(Poco::Logger &L,
L.information("============================================================================================="); const Poco::Crypto::X509Certificate &C) const {
L.information("============================================================================"
"=================");
L.information(fmt::format("> Issuer: {}", C.issuerName())); L.information(fmt::format("> Issuer: {}", C.issuerName()));
L.information("---------------------------------------------------------------------------------------------"); L.information("----------------------------------------------------------------------------"
"-----------------");
L.information(fmt::format("> Common Name: {}", L.information(fmt::format("> Common Name: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_COMMON_NAME))); C.issuerName(Poco::Crypto::X509Certificate::NID_COMMON_NAME)));
L.information(fmt::format("> Country: {}", L.information(fmt::format("> Country: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_COUNTRY))); C.issuerName(Poco::Crypto::X509Certificate::NID_COUNTRY)));
L.information(fmt::format("> Locality: {}", L.information(fmt::format("> Locality: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_LOCALITY_NAME))); C.issuerName(Poco::Crypto::X509Certificate::NID_LOCALITY_NAME)));
L.information(fmt::format("> State/Prov: {}", L.information(
fmt::format("> State/Prov: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_STATE_OR_PROVINCE))); C.issuerName(Poco::Crypto::X509Certificate::NID_STATE_OR_PROVINCE)));
L.information(fmt::format("> Org name: {}", L.information(
fmt::format("> Org name: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_NAME))); C.issuerName(Poco::Crypto::X509Certificate::NID_ORGANIZATION_NAME)));
L.information( L.information(
fmt::format("> Org unit: {}", fmt::format("> Org unit: {}",
@@ -149,9 +150,11 @@ namespace OpenWifi {
C.issuerName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS))); C.issuerName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS)));
L.information(fmt::format("> Serial#: {}", L.information(fmt::format("> Serial#: {}",
C.issuerName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER))); C.issuerName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER)));
L.information("---------------------------------------------------------------------------------------------"); L.information("----------------------------------------------------------------------------"
"-----------------");
L.information(fmt::format("> Subject: {}", C.subjectName())); L.information(fmt::format("> Subject: {}", C.subjectName()));
L.information("---------------------------------------------------------------------------------------------"); L.information("----------------------------------------------------------------------------"
"-----------------");
L.information(fmt::format("> Common Name: {}", L.information(fmt::format("> Common Name: {}",
C.subjectName(Poco::Crypto::X509Certificate::NID_COMMON_NAME))); C.subjectName(Poco::Crypto::X509Certificate::NID_COMMON_NAME)));
L.information(fmt::format("> Country: {}", L.information(fmt::format("> Country: {}",
@@ -172,52 +175,66 @@ namespace OpenWifi {
C.subjectName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS))); C.subjectName(Poco::Crypto::X509Certificate::NID_PKCS9_EMAIL_ADDRESS)));
L.information(fmt::format("> Serial#: {}", L.information(fmt::format("> Serial#: {}",
C.subjectName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER))); C.subjectName(Poco::Crypto::X509Certificate::NID_SERIAL_NUMBER)));
L.information("---------------------------------------------------------------------------------------------"); L.information("----------------------------------------------------------------------------"
"-----------------");
L.information(fmt::format("> Signature Algo: {}", C.signatureAlgorithm())); L.information(fmt::format("> Signature Algo: {}", C.signatureAlgorithm()));
auto From = Poco::DateTimeFormatter::format(C.validFrom(), Poco::DateTimeFormat::HTTP_FORMAT); auto From =
Poco::DateTimeFormatter::format(C.validFrom(), Poco::DateTimeFormat::HTTP_FORMAT);
L.information(fmt::format("> Valid from: {}", From)); L.information(fmt::format("> Valid from: {}", From));
auto Expires = auto Expires =
Poco::DateTimeFormatter::format(C.expiresOn(), Poco::DateTimeFormat::HTTP_FORMAT); Poco::DateTimeFormatter::format(C.expiresOn(), Poco::DateTimeFormat::HTTP_FORMAT);
L.information(fmt::format("> Expires on: {}", Expires)); L.information(fmt::format("> Expires on: {}", Expires));
L.information(fmt::format("> Version: {}", (int)C.version())); L.information(fmt::format("> Version: {}", (int)C.version()));
L.information(fmt::format("> Serial #: {}", C.serialNumber())); L.information(fmt::format("> Serial #: {}", C.serialNumber()));
L.information("============================================================================================="); L.information("============================================================================"
"=================");
} }
void PropertiesFileServerEntry::LogCert(Poco::Logger &L) const { void PropertiesFileServerEntry::LogCert(Poco::Logger &L) const {
try { try {
Poco::Crypto::X509Certificate C(cert_file_); Poco::Crypto::X509Certificate C(cert_file_);
L.information("============================================================================================="); L.information("========================================================================"
L.information("============================================================================================="); "=====================");
L.information("========================================================================"
"=====================");
L.information(fmt::format("Certificate Filename: {}", cert_file_)); L.information(fmt::format("Certificate Filename: {}", cert_file_));
LogCertInfo(L, C); LogCertInfo(L, C);
L.information("============================================================================================="); L.information("========================================================================"
"=====================");
if (!issuer_cert_file_.empty()) { if (!issuer_cert_file_.empty()) {
Poco::Crypto::X509Certificate C1(issuer_cert_file_); Poco::Crypto::X509Certificate C1(issuer_cert_file_);
L.information("============================================================================================="); L.information("===================================================================="
L.information("============================================================================================="); "=========================");
L.information("===================================================================="
"=========================");
L.information(fmt::format("Issues Certificate Filename: {}", issuer_cert_file_)); L.information(fmt::format("Issues Certificate Filename: {}", issuer_cert_file_));
LogCertInfo(L, C1); LogCertInfo(L, C1);
L.information("============================================================================================="); L.information("===================================================================="
"=========================");
} }
if (!client_cas_.empty()) { if (!client_cas_.empty()) {
std::vector<Poco::Crypto::X509Certificate> Certs = std::vector<Poco::Crypto::X509Certificate> Certs =
Poco::Net::X509Certificate::readPEM(client_cas_); Poco::Net::X509Certificate::readPEM(client_cas_);
L.information("============================================================================================="); L.information("===================================================================="
L.information("============================================================================================="); "=========================");
L.information("===================================================================="
"=========================");
L.information(fmt::format("Client CAs Filename: {}", client_cas_)); L.information(fmt::format("Client CAs Filename: {}", client_cas_));
L.information("============================================================================================="); L.information("===================================================================="
"=========================");
auto i = 1; auto i = 1;
for (const auto &C3 : Certs) { for (const auto &C3 : Certs) {
L.information(fmt::format(" Index: {}", i)); L.information(fmt::format(" Index: {}", i));
L.information("============================================================================================="); L.information("================================================================"
"=============================");
LogCertInfo(L, C3); LogCertInfo(L, C3);
i++; i++;
} }
L.information("============================================================================================="); L.information("===================================================================="
"=========================");
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
@@ -230,28 +247,31 @@ namespace OpenWifi {
std::vector<Poco::Crypto::X509Certificate> Certs = std::vector<Poco::Crypto::X509Certificate> Certs =
Poco::Net::X509Certificate::readPEM(root_ca_); Poco::Net::X509Certificate::readPEM(root_ca_);
L.information("============================================================================================="); L.information("========================================================================"
L.information("============================================================================================="); "=====================");
L.information("========================================================================"
"=====================");
L.information(fmt::format("CA Filename: {}", root_ca_)); L.information(fmt::format("CA Filename: {}", root_ca_));
L.information("============================================================================================="); L.information("========================================================================"
"=====================");
auto i = 1; auto i = 1;
for (const auto &C : Certs) { for (const auto &C : Certs) {
L.information(fmt::format(" Index: {}", i)); L.information(fmt::format(" Index: {}", i));
L.information("============================================================================================="); L.information("===================================================================="
"=========================");
LogCertInfo(L, C); LogCertInfo(L, C);
i++; i++;
} }
L.information("============================================================================================="); L.information("========================================================================"
"=====================");
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
L.log(E); L.log(E);
} }
} }
SubSystemServer::SubSystemServer(const std::string &Name, const std::string &LoggingPrefix, SubSystemServer::SubSystemServer(const std::string &Name, const std::string &LoggingPrefix,
const std::string &SubSystemConfigPrefix): const std::string &SubSystemConfigPrefix)
Name_(Name), : Name_(Name), LoggerPrefix_(LoggingPrefix), SubSystemConfigPrefix_(SubSystemConfigPrefix) {
LoggerPrefix_(LoggingPrefix),
SubSystemConfigPrefix_(SubSystemConfigPrefix) {
} }
void SubSystemServer::initialize([[maybe_unused]] Poco::Util::Application &self) { void SubSystemServer::initialize([[maybe_unused]] Poco::Util::Application &self) {
@@ -260,9 +280,12 @@ namespace OpenWifi {
auto NewLevel = MicroServiceConfigGetString("logging.level." + Name_, ""); auto NewLevel = MicroServiceConfigGetString("logging.level." + Name_, "");
if (NewLevel.empty()) if (NewLevel.empty())
Logger_ = std::make_unique<LoggerWrapper>(Poco::Logger::create(LoggerPrefix_, Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel())); Logger_ = std::make_unique<LoggerWrapper>(Poco::Logger::create(
LoggerPrefix_, Poco::Logger::root().getChannel(), Poco::Logger::root().getLevel()));
else else
Logger_ = std::make_unique<LoggerWrapper>(Poco::Logger::create(LoggerPrefix_, Poco::Logger::root().getChannel(), Poco::Logger::parseLevel(NewLevel))); Logger_ = std::make_unique<LoggerWrapper>(
Poco::Logger::create(LoggerPrefix_, Poco::Logger::root().getChannel(),
Poco::Logger::parseLevel(NewLevel)));
ConfigServersList_.clear(); ConfigServersList_.clear();
while (good) { while (good) {
@@ -297,14 +320,11 @@ namespace OpenWifi {
} else if (L == "once") } else if (L == "once")
M = Poco::Net::Context::VERIFY_ONCE; M = Poco::Net::Context::VERIFY_ONCE;
PropertiesFileServerEntry entry(MicroServiceConfigGetString(address, ""), PropertiesFileServerEntry entry(
MicroServiceConfigGetInt(port, 0), MicroServiceConfigGetString(address, ""), MicroServiceConfigGetInt(port, 0),
MicroServiceConfigPath(key, ""), MicroServiceConfigPath(key, ""), MicroServiceConfigPath(cert, ""),
MicroServiceConfigPath(cert, ""), MicroServiceConfigPath(rootca, ""), MicroServiceConfigPath(issuer, ""),
MicroServiceConfigPath(rootca, ""), MicroServiceConfigPath(clientcas, ""), MicroServiceConfigPath(cas, ""),
MicroServiceConfigPath(issuer, ""),
MicroServiceConfigPath(clientcas, ""),
MicroServiceConfigPath(cas, ""),
MicroServiceConfigGetString(key_password, ""), MicroServiceConfigGetString(key_password, ""),
MicroServiceConfigGetString(name, ""), M, MicroServiceConfigGetString(name, ""), M,
(int)MicroServiceConfigGetInt(backlog, 64)); (int)MicroServiceConfigGetInt(backlog, 64));
@@ -314,7 +334,4 @@ namespace OpenWifi {
} }
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -4,29 +4,27 @@
#pragma once #pragma once
#include <string>
#include <mutex> #include <mutex>
#include <string>
#include "Poco/Util/Application.h"
#include "Poco/Net/Context.h" #include "Poco/Net/Context.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Net/PrivateKeyPassphraseHandler.h" #include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Net/SecureServerSocket.h"
#include "Poco/Util/Application.h"
namespace OpenWifi { namespace OpenWifi {
class MyPrivateKeyPassphraseHandler : public Poco::Net::PrivateKeyPassphraseHandler { class MyPrivateKeyPassphraseHandler : public Poco::Net::PrivateKeyPassphraseHandler {
public: public:
explicit MyPrivateKeyPassphraseHandler(const std::string &Password, Poco::Logger & Logger): explicit MyPrivateKeyPassphraseHandler(const std::string &Password, Poco::Logger &Logger)
PrivateKeyPassphraseHandler(true), : PrivateKeyPassphraseHandler(true), Password_(Password), Logger_(Logger) {}
Password_(Password),
Logger_(Logger) {
}
void onPrivateKeyRequested([[maybe_unused]] const void *pSender, std::string &privateKey) { void onPrivateKeyRequested([[maybe_unused]] const void *pSender, std::string &privateKey) {
poco_information(Logger_, "Returning key passphrase."); poco_information(Logger_, "Returning key passphrase.");
privateKey = Password_; privateKey = Password_;
}; };
inline Poco::Logger &Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
private: private:
std::string Password_; std::string Password_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
@@ -80,17 +78,17 @@ namespace OpenWifi {
const std::string &SubSystemConfigPrefix); const std::string &SubSystemConfigPrefix);
void initialize(Poco::Util::Application &self) override; void initialize(Poco::Util::Application &self) override;
inline void uninitialize() override { inline void uninitialize() override {}
}
inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override { inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override {
poco_information(Logger_->L_, "Reloading of this subsystem is not supported."); poco_information(Logger_->L_, "Reloading of this subsystem is not supported.");
} }
inline void defineOptions([[maybe_unused]] Poco::Util::OptionSet &options) override { inline void defineOptions([[maybe_unused]] Poco::Util::OptionSet &options) override {}
}
inline const std::string &Name() const { return Name_; }; inline const std::string &Name() const { return Name_; };
inline const char *name() const override { return Name_.c_str(); } inline const char *name() const override { return Name_.c_str(); }
inline const PropertiesFileServerEntry & Host(uint64_t index) { return ConfigServersList_[index]; }; inline const PropertiesFileServerEntry &Host(uint64_t index) {
return ConfigServersList_[index];
};
inline uint64_t HostSize() const { return ConfigServersList_.size(); } inline uint64_t HostSize() const { return ConfigServersList_.size(); }
inline Poco::Logger &Logger() const { return Logger_->L_; } inline Poco::Logger &Logger() const { return Logger_->L_; }
inline void SetLoggingLevel(const std::string &levelName) { inline void SetLoggingLevel(const std::string &levelName) {
@@ -103,9 +101,7 @@ namespace OpenWifi {
struct LoggerWrapper { struct LoggerWrapper {
Poco::Logger &L_; Poco::Logger &L_;
LoggerWrapper(Poco::Logger &L) : LoggerWrapper(Poco::Logger &L) : L_(L) {}
L_(L) {
}
}; };
protected: protected:

View File

@@ -5,7 +5,4 @@
#include "framework/UI_WebSocketClientNotifications.h" #include "framework/UI_WebSocketClientNotifications.h"
#include "framework/UI_WebSocketClientServer.h" #include "framework/UI_WebSocketClientServer.h"
namespace OpenWifi { namespace OpenWifi {}
}

View File

@@ -37,9 +37,7 @@ namespace OpenWifi {
RESTAPI_utils::field_from_json(Obj, "content", content); RESTAPI_utils::field_from_json(Obj, "content", content);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
} } // namespace OpenWifi

View File

@@ -4,14 +4,14 @@
#include <mutex> #include <mutex>
#include "Poco/NObserver.h"
#include "Poco/JSON/JSONException.h" #include "Poco/JSON/JSONException.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/Logger.h" #include "Poco/Logger.h"
#include "Poco/NObserver.h"
#include "framework/UI_WebSocketClientServer.h"
#include "framework/AuthClient.h" #include "framework/AuthClient.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/UI_WebSocketClientServer.h"
#include "fmt/format.h" #include "fmt/format.h"
@@ -19,11 +19,13 @@
#include "AuthService.h" #include "AuthService.h"
#endif #endif
#define DBG { std::cout << __LINE__ << std::endl; } #define DBG \
{ std::cout << __LINE__ << std::endl; }
namespace OpenWifi { namespace OpenWifi {
void UI_WebSocketClientServer::NewClient(Poco::Net::WebSocket & WS, const std::string &Id, const std::string &UserName, std::uint64_t TID ) { void UI_WebSocketClientServer::NewClient(Poco::Net::WebSocket &WS, const std::string &Id,
const std::string &UserName, std::uint64_t TID) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
auto Client = std::make_unique<UI_WebSocketClientInfo>(WS, Id, UserName); auto Client = std::make_unique<UI_WebSocketClientInfo>(WS, Id, UserName);
@@ -32,28 +34,26 @@ namespace OpenWifi {
Client->WS_->setNoDelay(true); Client->WS_->setNoDelay(true);
Client->WS_->setKeepAlive(true); Client->WS_->setKeepAlive(true);
Client->WS_->setBlocking(false); Client->WS_->setBlocking(false);
Reactor_.addEventHandler(*Client->WS_, Reactor_.addEventHandler(
*Client->WS_,
Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ReadableNotification>( Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ReadableNotification>(
*this, &UI_WebSocketClientServer::OnSocketReadable)); *this, &UI_WebSocketClientServer::OnSocketReadable));
Reactor_.addEventHandler(*Client->WS_, Reactor_.addEventHandler(
*Client->WS_,
Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ShutdownNotification>( Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ShutdownNotification>(
*this, &UI_WebSocketClientServer::OnSocketShutdown)); *this, &UI_WebSocketClientServer::OnSocketShutdown));
Reactor_.addEventHandler(*Client->WS_, Reactor_.addEventHandler(
Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ErrorNotification>( *Client->WS_, Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ErrorNotification>(
*this, &UI_WebSocketClientServer::OnSocketError)); *this, &UI_WebSocketClientServer::OnSocketError));
Client->SocketRegistered_ = true; Client->SocketRegistered_ = true;
Clients_[ClientSocket] = std::move(Client); Clients_[ClientSocket] = std::move(Client);
UsersConnected_ = Clients_.size(); UsersConnected_ = Clients_.size();
} }
void UI_WebSocketClientServer::SetProcessor( UI_WebSocketClientProcessor * F) { void UI_WebSocketClientServer::SetProcessor(UI_WebSocketClientProcessor *F) { Processor_ = F; }
Processor_ = F;
}
UI_WebSocketClientServer::UI_WebSocketClientServer() noexcept: UI_WebSocketClientServer::UI_WebSocketClientServer() noexcept
SubSystemServer("WebSocketClientServer", "UI-WSCLNT-SVR", "websocketclients") : SubSystemServer("WebSocketClientServer", "UI-WSCLNT-SVR", "websocketclients") {}
{
}
void UI_WebSocketClientServer::run() { void UI_WebSocketClientServer::run() {
Running_ = true; Running_ = true;
@@ -71,21 +71,23 @@ namespace OpenWifi {
ToBeRemoved_.clear(); ToBeRemoved_.clear();
UsersConnected_ = Clients_.size(); UsersConnected_ = Clients_.size();
} }
} }
void UI_WebSocketClientServer::EndConnection(ClientList::iterator Client) { void UI_WebSocketClientServer::EndConnection(ClientList::iterator Client) {
if (Client->second->SocketRegistered_) { if (Client->second->SocketRegistered_) {
Client->second->SocketRegistered_ = false; Client->second->SocketRegistered_ = false;
Reactor_.removeEventHandler(*Client->second->WS_, Reactor_.removeEventHandler(
Poco::NObserver<UI_WebSocketClientServer, *Client->second->WS_,
Poco::Net::ReadableNotification>(*this,&UI_WebSocketClientServer::OnSocketReadable)); Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ReadableNotification>(
Reactor_.removeEventHandler(*Client->second->WS_, *this, &UI_WebSocketClientServer::OnSocketReadable));
Poco::NObserver<UI_WebSocketClientServer, Reactor_.removeEventHandler(
Poco::Net::ShutdownNotification>(*this,&UI_WebSocketClientServer::OnSocketShutdown)); *Client->second->WS_,
Reactor_.removeEventHandler(*Client->second->WS_, Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ShutdownNotification>(
Poco::NObserver<UI_WebSocketClientServer, *this, &UI_WebSocketClientServer::OnSocketShutdown));
Poco::Net::ErrorNotification>(*this,&UI_WebSocketClientServer::OnSocketError)); Reactor_.removeEventHandler(
*Client->second->WS_,
Poco::NObserver<UI_WebSocketClientServer, Poco::Net::ErrorNotification>(
*this, &UI_WebSocketClientServer::OnSocketError));
} }
ToBeRemoved_.push_back(Client); ToBeRemoved_.push_back(Client);
} }
@@ -114,11 +116,13 @@ namespace OpenWifi {
} }
}; };
bool UI_WebSocketClientServer::IsFiltered(std::uint64_t id, const OpenWifi::UI_WebSocketClientInfo &Client) { bool UI_WebSocketClientServer::IsFiltered(std::uint64_t id,
const OpenWifi::UI_WebSocketClientInfo &Client) {
return std::find(Client.Filter_.begin(), Client.Filter_.end(), id) != end(Client.Filter_); return std::find(Client.Filter_.begin(), Client.Filter_.end(), id) != end(Client.Filter_);
} }
bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id, const std::string &Payload) { bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id,
const std::string &Payload) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
for (const auto &Client : Clients_) { for (const auto &Client : Clients_) {
@@ -146,19 +150,20 @@ namespace OpenWifi {
if (!IsFiltered(id, *Client.second) && Client.second->Authenticated_) if (!IsFiltered(id, *Client.second) && Client.second->Authenticated_)
Client.second->WS_->sendFrame(Payload.c_str(), (int)Payload.size()); Client.second->WS_->sendFrame(Payload.c_str(), (int)Payload.size());
} catch (...) { } catch (...) {
} }
} }
} }
UI_WebSocketClientServer::ClientList::iterator UI_WebSocketClientServer::FindWSClient( [[maybe_unused]] std::lock_guard<std::recursive_mutex> &G, int ClientSocket) { UI_WebSocketClientServer::ClientList::iterator UI_WebSocketClientServer::FindWSClient(
[[maybe_unused]] std::lock_guard<std::recursive_mutex> &G, int ClientSocket) {
return Clients_.find(ClientSocket); return Clients_.find(ClientSocket);
} }
void UI_WebSocketClientServer::SortNotifications() { void UI_WebSocketClientServer::SortNotifications() {
struct { struct {
bool operator()(const NotificationEntry &A, const NotificationEntry &B) const { bool operator()(const NotificationEntry &A, const NotificationEntry &B) const {
return A.id < B.id; }; return A.id < B.id;
};
} CompareNotifications; } CompareNotifications;
std::sort(NotificationTypes_.begin(), NotificationTypes_.end(), CompareNotifications); std::sort(NotificationTypes_.begin(), NotificationTypes_.end(), CompareNotifications);
@@ -173,12 +178,15 @@ namespace OpenWifi {
NotificationTypesJSON_.set("notificationTypes", AllNotifications); NotificationTypesJSON_.set("notificationTypes", AllNotifications);
} }
void UI_WebSocketClientServer::RegisterNotifications(const OpenWifi::UI_WebSocketClientServer::NotificationTypeIdVec &Notifications) { void UI_WebSocketClientServer::RegisterNotifications(
std::copy(Notifications.begin(), Notifications.end(), std::back_inserter(NotificationTypes_)); const OpenWifi::UI_WebSocketClientServer::NotificationTypeIdVec &Notifications) {
std::copy(Notifications.begin(), Notifications.end(),
std::back_inserter(NotificationTypes_));
SortNotifications(); SortNotifications();
} }
void UI_WebSocketClientServer::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) { void UI_WebSocketClientServer::OnSocketError(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
auto Client = Clients_.find(pNf->socket().impl()->sockfd()); auto Client = Clients_.find(pNf->socket().impl()->sockfd());
if (Client == end(Clients_)) if (Client == end(Clients_))
@@ -186,7 +194,8 @@ namespace OpenWifi {
EndConnection(Client); EndConnection(Client);
} }
void UI_WebSocketClientServer::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) { void UI_WebSocketClientServer::OnSocketReadable(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
UI_WebSocketClientServer::ClientList::iterator Client; UI_WebSocketClientServer::ClientList::iterator Client;
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
@@ -204,7 +213,9 @@ namespace OpenWifi {
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (n == 0) { if (n == 0) {
poco_debug(Logger(),fmt::format("CLOSE({}): {} UI Client is closing WS connection.", Client->second->Id_, Client->second->UserName_)); poco_debug(Logger(),
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
Client->second->Id_, Client->second->UserName_));
return EndConnection(Client); return EndConnection(Client);
} }
@@ -217,7 +228,9 @@ namespace OpenWifi {
case Poco::Net::WebSocket::FRAME_OP_PONG: { case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: { case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
poco_debug(Logger(),fmt::format("CLOSE({}): {} UI Client is closing WS connection.", Client->second->Id_, Client->second->UserName_)); poco_debug(Logger(),
fmt::format("CLOSE({}): {} UI Client is closing WS connection.",
Client->second->Id_, Client->second->UserName_));
return EndConnection(Client); return EndConnection(Client);
} break; } break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: { case Poco::Net::WebSocket::FRAME_OP_TEXT: {
@@ -232,13 +245,17 @@ namespace OpenWifi {
#endif #endif
if (Tokens.size() == 2 && if (Tokens.size() == 2 &&
#if defined(TIP_SECURITY_SERVICE) #if defined(TIP_SECURITY_SERVICE)
AuthService()->IsAuthorized(Tokens[1], Client->second->UserInfo_, TID_, Expired)) { AuthService()->IsAuthorized(Tokens[1], Client->second->UserInfo_, TID_,
Expired)) {
#else #else
AuthClient()->IsAuthorized(Tokens[1], Client->second->UserInfo_, TID_, Expired, Contacted)) { AuthClient()->IsAuthorized(Tokens[1], Client->second->UserInfo_, TID_,
Expired, Contacted)) {
#endif #endif
Client->second->Authenticated_ = true; Client->second->Authenticated_ = true;
Client->second->UserName_ = Client->second->UserInfo_.userinfo.email; Client->second->UserName_ = Client->second->UserInfo_.userinfo.email;
poco_debug(Logger(),fmt::format("START({}): {} UI Client is starting WS connection.", Client->second->Id_, Client->second->UserName_)); poco_debug(Logger(),
fmt::format("START({}): {} UI Client is starting WS connection.",
Client->second->Id_, Client->second->UserName_));
auto WelcomeMessage = NotificationTypesJSON_; auto WelcomeMessage = NotificationTypesJSON_;
WelcomeMessage.set("success", "Welcome! Bienvenue! Bienvenidos!"); WelcomeMessage.set("success", "Welcome! Bienvenue! Bienvenidos!");
std::ostringstream OS; std::ostringstream OS;
@@ -255,8 +272,7 @@ namespace OpenWifi {
} }
} else { } else {
Poco::JSON::Parser P; Poco::JSON::Parser P;
auto Obj = auto Obj = P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>();
P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(DropMessagesCommand) && Obj->isArray(DropMessagesCommand)) { if (Obj->has(DropMessagesCommand) && Obj->isArray(DropMessagesCommand)) {
auto Filters = Obj->getArray(DropMessagesCommand); auto Filters = Obj->getArray(DropMessagesCommand);
@@ -271,7 +287,8 @@ namespace OpenWifi {
std::string Answer; std::string Answer;
bool CloseConnection = false; bool CloseConnection = false;
if (Processor_ != nullptr) { if (Processor_ != nullptr) {
Processor_->Processor(Obj, Answer, CloseConnection,Client->second->UserInfo_.userinfo); Processor_->Processor(Obj, Answer, CloseConnection,
Client->second->UserInfo_.userinfo);
} }
if (!Answer.empty()) if (!Answer.empty())
Client->second->WS_->sendFrame(Answer.c_str(), (int)Answer.size()); Client->second->WS_->sendFrame(Answer.c_str(), (int)Answer.size());
@@ -292,7 +309,8 @@ namespace OpenWifi {
} }
} }
void UI_WebSocketClientServer::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) { void UI_WebSocketClientServer::OnSocketShutdown(
[[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
try { try {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
auto Client = Clients_.find(pNf->socket().impl()->sockfd()); auto Client = Clients_.find(pNf->socket().impl()->sockfd());
@@ -300,7 +318,6 @@ namespace OpenWifi {
return; return;
EndConnection(Client); EndConnection(Client);
} catch (...) { } catch (...) {
} }
} }

View File

@@ -7,11 +7,11 @@
#include <map> #include <map>
#include <string> #include <string>
#include "Poco/Runnable.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/Net/SocketNotification.h" #include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Runnable.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h" #include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
@@ -21,7 +21,9 @@ namespace OpenWifi {
class UI_WebSocketClientProcessor { class UI_WebSocketClientProcessor {
public: public:
virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done , const SecurityObjects::UserInfo & UserInfo) = 0; virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done,
const SecurityObjects::UserInfo &UserInfo) = 0;
private: private:
}; };
@@ -34,7 +36,8 @@ namespace OpenWifi {
std::vector<std::uint64_t> Filter_; std::vector<std::uint64_t> Filter_;
SecurityObjects::UserInfoAndPolicy UserInfo_; SecurityObjects::UserInfoAndPolicy UserInfo_;
UI_WebSocketClientInfo(Poco::Net::WebSocket &WS, const std::string &Id, const std::string &username) { UI_WebSocketClientInfo(Poco::Net::WebSocket &WS, const std::string &Id,
const std::string &username) {
WS_ = std::make_unique<Poco::Net::WebSocket>(WS); WS_ = std::make_unique<Poco::Net::WebSocket>(WS);
Id_ = Id; Id_ = Id;
UserName_ = username; UserName_ = username;
@@ -49,21 +52,21 @@ namespace OpenWifi {
return instance_; return instance_;
} }
bool IsAnyoneConnected() { bool IsAnyoneConnected() { return UsersConnected_; }
return UsersConnected_;
}
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void run() override; void run() override;
Poco::Net::SocketReactor &Reactor() { return Reactor_; } Poco::Net::SocketReactor &Reactor() { return Reactor_; }
void NewClient(Poco::Net::WebSocket &WS, const std::string &Id, const std::string &UserName, std::uint64_t TID); void NewClient(Poco::Net::WebSocket &WS, const std::string &Id, const std::string &UserName,
std::uint64_t TID);
void SetProcessor(UI_WebSocketClientProcessor *F); void SetProcessor(UI_WebSocketClientProcessor *F);
[[nodiscard]] inline bool GeoCodeEnabled() const { return GeoCodeEnabled_; } [[nodiscard]] inline bool GeoCodeEnabled() const { return GeoCodeEnabled_; }
[[nodiscard]] inline std::string GoogleApiKey() const { return GoogleApiKey_; } [[nodiscard]] inline std::string GoogleApiKey() const { return GoogleApiKey_; }
template <typename T> bool template <typename T>
SendUserNotification(const std::string &userName, const WebSocketNotification<T> &Notification) { bool SendUserNotification(const std::string &userName,
const WebSocketNotification<T> &Notification) {
Poco::JSON::Object Payload; Poco::JSON::Object Payload;
Notification.to_json(Payload); Notification.to_json(Payload);
@@ -85,7 +88,8 @@ namespace OpenWifi {
SendToAll(Notification.type_id, OO.str()); SendToAll(Notification.type_id, OO.str());
} }
[[nodiscard]] bool SendToUser(const std::string &userName, std::uint64_t id, const std::string &Payload); [[nodiscard]] bool SendToUser(const std::string &userName, std::uint64_t id,
const std::string &Payload);
void SendToAll(std::uint64_t id, const std::string &Payload); void SendToAll(std::uint64_t id, const std::string &Payload);
struct NotificationEntry { struct NotificationEntry {
@@ -122,12 +126,12 @@ namespace OpenWifi {
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf); void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf); void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf);
ClientList::iterator FindWSClient( std::lock_guard<std::recursive_mutex> &G, int ClientSocket); ClientList::iterator FindWSClient(std::lock_guard<std::recursive_mutex> &G,
int ClientSocket);
void SortNotifications(); void SortNotifications();
}; };
inline auto UI_WebSocketClientServer() { return UI_WebSocketClientServer::instance(); } inline auto UI_WebSocketClientServer() { return UI_WebSocketClientServer::instance(); }
}; }; // namespace OpenWifi

View File

@@ -5,43 +5,46 @@
#pragma once #pragma once
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include "framework/UI_WebSocketClientServer.h"
#include "framework/UI_WebSocketClientNotifications.h" #include "framework/UI_WebSocketClientNotifications.h"
#include "framework/UI_WebSocketClientServer.h"
namespace OpenWifi { namespace OpenWifi {
class WebSocketLogger : public Poco::Channel { class WebSocketLogger : public Poco::Channel {
public: public:
WebSocketLogger() {}
WebSocketLogger() { ~WebSocketLogger() {}
}
~WebSocketLogger() {
}
std::string getProperty([[maybe_unused]] const std::string &p) const { std::string getProperty([[maybe_unused]] const std::string &p) const {
std::cout << "WS getProperty" << std::endl; std::cout << "WS getProperty" << std::endl;
return ""; return "";
} }
void close() final { void close() final {}
}
void open() final { void open() final {}
}
static std::string to_string(Poco::Message::Priority p) { static std::string to_string(Poco::Message::Priority p) {
switch (p) { switch (p) {
case Poco::Message::PRIO_INFORMATION: return "information"; case Poco::Message::PRIO_INFORMATION:
case Poco::Message::PRIO_CRITICAL: return "critical"; return "information";
case Poco::Message::PRIO_DEBUG: return "debug"; case Poco::Message::PRIO_CRITICAL:
case Poco::Message::PRIO_ERROR: return "error"; return "critical";
case Poco::Message::PRIO_FATAL: return "fatal"; case Poco::Message::PRIO_DEBUG:
case Poco::Message::PRIO_NOTICE: return "notice"; return "debug";
case Poco::Message::PRIO_TRACE: return "trace"; case Poco::Message::PRIO_ERROR:
case Poco::Message::PRIO_WARNING: return "warning"; return "error";
default: return "none"; case Poco::Message::PRIO_FATAL:
return "fatal";
case Poco::Message::PRIO_NOTICE:
return "notice";
case Poco::Message::PRIO_TRACE:
return "trace";
case Poco::Message::PRIO_WARNING:
return "warning";
default:
return "none";
} }
} }
@@ -72,13 +75,13 @@ namespace OpenWifi {
RESTAPI_utils::field_from_json(Obj, "thread_id", thread_id); RESTAPI_utils::field_from_json(Obj, "thread_id", thread_id);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
}; };
typedef WebSocketNotification<NotificationLogMessage> WebSocketClientNotificationLogMessage_t; typedef WebSocketNotification<NotificationLogMessage>
WebSocketClientNotificationLogMessage_t;
void log(const Poco::Message &m) final { void log(const Poco::Message &m) final {
if (UI_WebSocketClientServer()->IsAnyoneConnected()) { if (UI_WebSocketClientServer()->IsAnyoneConnected()) {
@@ -94,7 +97,8 @@ namespace OpenWifi {
} }
} }
void setProperty([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &value) { void setProperty([[maybe_unused]] const std::string &name,
[[maybe_unused]] const std::string &value) {
std::cout << "WS setProperty" << std::endl; std::cout << "WS setProperty" << std::endl;
} }
@@ -104,4 +108,4 @@ namespace OpenWifi {
// inline auto WebSocketLogger() { return WebSocketLogger::instance(); } // inline auto WebSocketLogger() { return WebSocketLogger::instance(); }
} } // namespace OpenWifi

View File

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

View File

@@ -8,41 +8,30 @@
#pragma once #pragma once
#include <string>
#include <memory>
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <array> #include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "Poco/Tuple.h"
#include "Poco/Data/SessionPool.h"
#include "Poco/Data/Statement.h"
#include "Poco/Data/RecordSet.h" #include "Poco/Data/RecordSet.h"
#include "Poco/Data/SQLite/Connector.h" #include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/SessionPool.h"
#include "Poco/Data/Statement.h"
#include "Poco/Logger.h" #include "Poco/Logger.h"
#include "Poco/StringTokenizer.h" #include "Poco/StringTokenizer.h"
#include "Poco/Tuple.h"
#include "StorageClass.h" #include "StorageClass.h"
#include "fmt/format.h" #include "fmt/format.h"
namespace ORM { namespace ORM {
enum FieldType { enum FieldType { FT_INT, FT_BIGINT, FT_TEXT, FT_VARCHAR, FT_BLOB, FT_BOOLEAN, FT_REAL };
FT_INT,
FT_BIGINT,
FT_TEXT,
FT_VARCHAR,
FT_BLOB,
FT_BOOLEAN,
FT_REAL
};
enum Indextype { enum Indextype { ASC, DESC };
ASC,
DESC
};
struct Field { struct Field {
std::string Name; std::string Name;
@@ -50,31 +39,19 @@ namespace ORM {
int Size = 0; int Size = 0;
bool Index = false; bool Index = false;
Field(std::string N, FieldType T, int S = 0, bool Index = false)
: Name(std::move(N)), Type(T), Size(S), Index(Index) {}
Field(std::string N, FieldType T, int S=0, bool Index=false) : explicit Field(std::string N) : Name(std::move(N)) { Type = FT_TEXT; }
Name(std::move(N)),
Type(T),
Size(S),
Index(Index) {}
explicit Field(std::string N) : Field(std::string N, int S) : Name(std::move(N)), Size(S) {
Name(std::move(N))
{
Type = FT_TEXT;
}
Field(std::string N, int S) :
Name(std::move(N)), Size(S)
{
if (Size > 0 && Size < 255) if (Size > 0 && Size < 255)
Type = FT_VARCHAR; Type = FT_VARCHAR;
else else
Type = FT_TEXT; Type = FT_TEXT;
} }
Field(std::string N, int S, bool I): Field(std::string N, int S, bool I) : Name(std::move(N)), Size(S), Index(I) {
Name(std::move(N)), Size(S), Index(I)
{
if (Size > 0 && Size < 255) if (Size > 0 && Size < 255)
Type = FT_VARCHAR; Type = FT_VARCHAR;
else else
@@ -97,10 +74,14 @@ namespace ORM {
inline std::string FieldTypeToChar(OpenWifi::DBType Type, FieldType T, int Size = 0) { inline std::string FieldTypeToChar(OpenWifi::DBType Type, FieldType T, int Size = 0) {
switch (T) { switch (T) {
case FT_INT: return "INT"; case FT_INT:
case FT_BIGINT: return "BIGINT"; return "INT";
case FT_TEXT: return "TEXT"; case FT_BIGINT:
case FT_BOOLEAN: return "BOOLEAN"; return "BIGINT";
case FT_TEXT:
return "TEXT";
case FT_BOOLEAN:
return "BOOLEAN";
case FT_VARCHAR: case FT_VARCHAR:
if (Size) if (Size)
return std::string("VARCHAR(") + std::to_string(Size) + std::string(")"); return std::string("VARCHAR(") + std::to_string(Size) + std::string(")");
@@ -117,7 +98,6 @@ namespace ORM {
return "REAL"; return "REAL";
default: default:
assert(false); assert(false);
} }
assert(false); assert(false);
return ""; return "";
@@ -135,13 +115,12 @@ namespace ORM {
return R; return R;
} }
inline std::string WHERE_AND_(std::string Result) { inline std::string WHERE_AND_(std::string Result) { return Result; }
return Result;
}
template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T & Value, Args... args) { template <typename T, typename... Args>
if constexpr(std::is_same_v<T,std::string>) std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value,
{ Args... args) {
if constexpr (std::is_same_v<T, std::string>) {
if (!Value.empty()) { if (!Value.empty()) {
if (!Result.empty()) if (!Result.empty())
Result += " and "; Result += " and ";
@@ -194,21 +173,13 @@ namespace ORM {
static const std::vector<std::string> BOPS{" and ", " or "}; static const std::vector<std::string> BOPS{" and ", " or "};
static const std::vector<std::string> SQLCOMPS{"=", "!=", "<", "<=", ">", ">="}; static const std::vector<std::string> SQLCOMPS{"=", "!=", "<", "<=", ">", ">="};
inline std::string to_string(uint64_t V) { inline std::string to_string(uint64_t V) { return std::to_string(V); }
return std::to_string(V);
}
inline std::string to_string(int V) { inline std::string to_string(int V) { return std::to_string(V); }
return std::to_string(V);
}
inline std::string to_string(bool V) { inline std::string to_string(bool V) { return std::to_string(V); }
return std::to_string(V);
}
inline std::string to_string(const std::string &S) { inline std::string to_string(const std::string &S) { return S; }
return S;
}
inline std::string to_string(const Poco::Data::BLOB &blob) { inline std::string to_string(const Poco::Data::BLOB &blob) {
std::string result; std::string result;
@@ -216,22 +187,17 @@ namespace ORM {
return result; return result;
} }
inline std::string to_string(const char * S) { inline std::string to_string(const char *S) { return S; }
return S;
}
template <typename RecordType> class DBCache { template <typename RecordType> class DBCache {
public: public:
DBCache(unsigned Size, unsigned Timeout) : DBCache(unsigned Size, unsigned Timeout) : Size_(Size), Timeout_(Timeout) {}
Size_(Size),
Timeout_(Timeout)
{
}
virtual void Create(const RecordType &R) = 0; virtual void Create(const RecordType &R) = 0;
virtual bool GetFromCache(const std::string &FieldName, const std::string &Value, RecordType &R)=0; virtual bool GetFromCache(const std::string &FieldName, const std::string &Value,
RecordType &R) = 0;
virtual void UpdateCache(const RecordType &R) = 0; virtual void UpdateCache(const RecordType &R) = 0;
virtual void Delete(const std::string &FieldName, const std::string &Value) = 0; virtual void Delete(const std::string &FieldName, const std::string &Value) = 0;
private: private:
size_t Size_ = 0; size_t Size_ = 0;
uint64_t Timeout_ = 0; uint64_t Timeout_ = 0;
@@ -239,24 +205,13 @@ namespace ORM {
template <typename RecordTuple, typename RecordType> class DB { template <typename RecordTuple, typename RecordType> class DB {
public: public:
typedef const char *field_name_t; typedef const char *field_name_t;
DB( OpenWifi::DBType dbtype, DB(OpenWifi::DBType dbtype, const char *TableName, const FieldVec &Fields,
const char *TableName, const IndexVec &Indexes, Poco::Data::SessionPool &Pool, Poco::Logger &L,
const FieldVec & Fields, const char *Prefix, DBCache<RecordType> *Cache = nullptr)
const IndexVec & Indexes, : TableName_(TableName), Type_(dbtype), Pool_(Pool), Logger_(L), Prefix_(Prefix),
Poco::Data::SessionPool & Pool, Cache_(Cache) {
Poco::Logger &L,
const char *Prefix,
DBCache<RecordType> * Cache=nullptr):
TableName_(TableName),
Type_(dbtype),
Pool_(Pool),
Logger_(L),
Prefix_(Prefix),
Cache_(Cache)
{
assert(RecordTuple::length == Fields.size()); assert(RecordTuple::length == Fields.size());
bool first = true; bool first = true;
@@ -274,7 +229,8 @@ namespace ORM {
SelectList_ += "("; SelectList_ += "(";
} }
CreateFields_ += FieldName + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : ""); CreateFields_ += FieldName + " " + FieldTypeToChar(Type_, i.Type, i.Size) +
(i.Index ? " unique primary key" : "");
SelectFields_ += FieldName; SelectFields_ += FieldName;
UpdateFields_ += FieldName + "=?"; UpdateFields_ += FieldName + "=?";
SelectList_ += "?"; SelectList_ += "?";
@@ -288,7 +244,8 @@ namespace ORM {
for (const auto &j : Indexes) { for (const auto &j : Indexes) {
std::string IndexLine; std::string IndexLine;
IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + TableName_+ " ("; IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name +
std::string(" ON ") + TableName_ + " (";
bool first_entry = true; bool first_entry = true;
for (const auto &k : j.Entries) { for (const auto &k : j.Entries) {
auto IndexFieldName = Poco::toLower(k.FieldName); auto IndexFieldName = Poco::toLower(k.FieldName);
@@ -297,7 +254,8 @@ namespace ORM {
IndexLine += " , "; IndexLine += " , ";
} }
first_entry = false; first_entry = false;
IndexLine += IndexFieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ; IndexLine += IndexFieldName + std::string(" ") +
std::string(k.Type == Indextype::ASC ? "ASC" : "DESC");
} }
IndexLine += " )"; IndexLine += " )";
IndexCreation_.template emplace_back(IndexLine); IndexCreation_.template emplace_back(IndexLine);
@@ -318,7 +276,8 @@ namespace ORM {
IndexLine += " ,"; IndexLine += " ,";
} }
first_entry = false; first_entry = false;
IndexLine += IndexFieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC"); IndexLine += IndexFieldName +
std::string(k.Type == Indextype::ASC ? " ASC" : " DESC");
} }
IndexLine += " ) "; IndexLine += " ) ";
} }
@@ -361,15 +320,20 @@ namespace ORM {
return std::string("(") + P1 + BOPS[BOP] + P2 + ")"; return std::string("(") + P1 + BOPS[BOP] + P2 + ")";
} }
std::string OP( [[maybe_unused]] bool Paran, const std::string &P1, SqlBinaryOp BOP , const std::string &P2) { std::string OP([[maybe_unused]] bool Paran, const std::string &P1, SqlBinaryOp BOP,
const std::string &P2) {
return P1 + BOPS[BOP] + P2 + ")"; return P1 + BOPS[BOP] + P2 + ")";
} }
template <typename... Others> std::string OP( bool ParanOpen, const std::string &P1, SqlBinaryOp BOP , const std::string &P2, Others... More) { template <typename... Others>
std::string OP(bool ParanOpen, const std::string &P1, SqlBinaryOp BOP,
const std::string &P2, Others... More) {
return P1 + BOPS[BOP] + OP(ParanOpen, P2, More...) + ")"; return P1 + BOPS[BOP] + OP(ParanOpen, P2, More...) + ")";
} }
template <typename... Others> std::string OP( const std::string &P1, SqlBinaryOp BOP , const std::string &P2, Others... More) { template <typename... Others>
std::string OP(const std::string &P1, SqlBinaryOp BOP, const std::string &P2,
Others... More) {
return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...); return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...);
} }
@@ -383,20 +347,24 @@ namespace ORM {
case OpenWifi::DBType::mysql: { case OpenWifi::DBType::mysql: {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
std::string Statement = IndexCreation_.empty() ? "create table if not exists " + TableName_ +" ( " + CreateFields_ + " )" : std::string Statement = IndexCreation_.empty()
"create table if not exists " + TableName_ +" ( " + CreateFields_ + " ), " + IndexCreation_[0] + " )"; ? "create table if not exists " + TableName_ +
" ( " + CreateFields_ + " )"
: "create table if not exists " + TableName_ +
" ( " + CreateFields_ + " ), " +
IndexCreation_[0] + " )";
Session << Statement, Poco::Data::Keywords::now; Session << Statement, Poco::Data::Keywords::now;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.error("Failure to create MySQL DB resources."); Logger_.error("Failure to create MySQL DB resources.");
Logger_.log(E); Logger_.log(E);
} }
} } break;
break;
case OpenWifi::DBType::sqlite: { case OpenWifi::DBType::sqlite: {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )"; std::string Statement =
"create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
Session << Statement, Poco::Data::Keywords::now; Session << Statement, Poco::Data::Keywords::now;
for (const auto &i : IndexCreation_) { for (const auto &i : IndexCreation_) {
Session << i, Poco::Data::Keywords::now; Session << i, Poco::Data::Keywords::now;
@@ -405,13 +373,13 @@ namespace ORM {
Logger_.error("Failure to create SQLITE DB resources."); Logger_.error("Failure to create SQLITE DB resources.");
Logger_.log(E); Logger_.log(E);
} }
} } break;
break;
case OpenWifi::DBType::pgsql: { case OpenWifi::DBType::pgsql: {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )"; std::string Statement =
"create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
Session << Statement, Poco::Data::Keywords::now; Session << Statement, Poco::Data::Keywords::now;
for (const auto &i : IndexCreation_) { for (const auto &i : IndexCreation_) {
Session << i, Poco::Data::Keywords::now; Session << i, Poco::Data::Keywords::now;
@@ -420,8 +388,7 @@ namespace ORM {
Logger_.error("Failure to create POSTGRESQL DB resources."); Logger_.error("Failure to create POSTGRESQL DB resources.");
Logger_.log(E); Logger_.log(E);
} }
} } break;
break;
} }
return Upgrade(); return Upgrade();
} }
@@ -433,8 +400,7 @@ namespace ORM {
std::string R; std::string R;
R.reserve(S.size() * 2 + 1); R.reserve(S.size() * 2 + 1);
auto Idx = 1; auto Idx = 1;
for(auto const & i:S) for (auto const &i : S) {
{
if (i == '?') { if (i == '?') {
R += '$'; R += '$';
R.append(std::to_string(Idx++)); R.append(std::to_string(Idx++));
@@ -458,9 +424,9 @@ namespace ORM {
RecordTuple RT; RecordTuple RT;
Convert(R, RT); Convert(R, RT);
std::string St = "insert into " + TableName_ + " ( " + SelectFields_ + " ) values " + SelectList_; std::string St = "insert into " + TableName_ + " ( " + SelectFields_ +
Insert << ConvertParams(St) , " ) values " + SelectList_;
Poco::Data::Keywords::use(RT); Insert << ConvertParams(St), Poco::Data::Keywords::use(RT);
Insert.execute(); Insert.execute();
if (Cache_) if (Cache_)
@@ -473,7 +439,8 @@ namespace ORM {
return false; return false;
} }
template<typename T> bool GetRecord(field_name_t FieldName, const T & Value, RecordType & R) { template <typename T>
bool GetRecord(field_name_t FieldName, const T &Value, RecordType &R) {
try { try {
assert(ValidFieldName(FieldName)); assert(ValidFieldName(FieldName));
@@ -486,12 +453,12 @@ namespace ORM {
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" + " limit 1"; std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " +
FieldName + "=?" + " limit 1";
auto tValue{Value}; auto tValue{Value};
Select << ConvertParams(St) , Select << ConvertParams(St), Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::use(tValue); Poco::Data::Keywords::use(tValue);
Select.execute(); Select.execute();
@@ -513,10 +480,10 @@ namespace ORM {
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + WhereClause + " limit 1"; std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " +
WhereClause + " limit 1";
Select << ConvertParams(St) , Select << ConvertParams(St), Poco::Data::Keywords::into(RT);
Poco::Data::Keywords::into(RT);
Select.execute(); Select.execute();
if (Select.execute() == 1) { if (Select.execute() == 1) {
@@ -533,8 +500,8 @@ namespace ORM {
typedef std::vector<std::string> StringVec; typedef std::vector<std::string> StringVec;
template < typename T, template <typename T, typename T0, typename T1>
typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) { bool GR(field_name_t FieldName, T &R, T0 &V0, T1 &V1) {
try { try {
assert(ValidFieldName(FieldName)); assert(ValidFieldName(FieldName));
@@ -543,12 +510,10 @@ namespace ORM {
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + TableName_ std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " +
+ " where " + FieldName[0] + "=? and " + FieldName[1] + "=?" ; FieldName[0] + "=? and " + FieldName[1] + "=?";
Select << ConvertParams(St) , Select << ConvertParams(St), Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::into(RT), Poco::Data::Keywords::use(V0), Poco::Data::Keywords::use(V1);
Poco::Data::Keywords::use(V0),
Poco::Data::Keywords::use(V1);
if (Select.execute() == 1) { if (Select.execute() == 1) {
Convert(RT, R); Convert(RT, R);
@@ -566,8 +531,7 @@ namespace ORM {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
Select << statement , Select << statement, Poco::Data::Keywords::into(records);
Poco::Data::Keywords::into(records);
Select.execute(); Select.execute();
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
@@ -580,7 +544,8 @@ namespace ORM {
typedef std::vector<RecordType> RecordVec; typedef std::vector<RecordType> RecordVec;
typedef RecordType RecordName; typedef RecordType RecordName;
bool GetRecords( uint64_t Offset, uint64_t HowMany, RecordVec & Records, const std::string & Where = "", const std::string & OrderBy = "") { bool GetRecords(uint64_t Offset, uint64_t HowMany, RecordVec &Records,
const std::string &Where = "", const std::string &OrderBy = "") {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
@@ -589,8 +554,7 @@ namespace ORM {
(Where.empty() ? "" : " where " + Where) + OrderBy + (Where.empty() ? "" : " where " + Where) + OrderBy +
ComputeRange(Offset, HowMany); ComputeRange(Offset, HowMany);
Select << St , Select << St, Poco::Data::Keywords::into(RL);
Poco::Data::Keywords::into(RL);
Select.execute(); Select.execute();
if (Select.rowsExtracted() > 0) { if (Select.rowsExtracted() > 0) {
@@ -608,7 +572,8 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool UpdateRecord(field_name_t FieldName, const T & Value, const RecordType & R) { template <typename T>
bool UpdateRecord(field_name_t FieldName, const T &Value, const RecordType &R) {
try { try {
assert(ValidFieldName(FieldName)); assert(ValidFieldName(FieldName));
@@ -621,9 +586,9 @@ namespace ORM {
auto tValue(Value); auto tValue(Value);
std::string St = "update " + TableName_ + " set " + UpdateFields_ + " where " + FieldName + "=?" ; std::string St =
Update << ConvertParams(St) , "update " + TableName_ + " set " + UpdateFields_ + " where " + FieldName + "=?";
Poco::Data::Keywords::use(RT), Update << ConvertParams(St), Poco::Data::Keywords::use(RT),
Poco::Data::Keywords::use(tValue); Poco::Data::Keywords::use(tValue);
Update.execute(); Update.execute();
if (Cache_) if (Cache_)
@@ -650,7 +615,8 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool ReplaceRecord(field_name_t FieldName, const T & Value, RecordType & R) { template <typename T>
bool ReplaceRecord(field_name_t FieldName, const T &Value, RecordType &R) {
try { try {
if (Exists(FieldName, Value)) { if (Exists(FieldName, Value)) {
return UpdateRecord(FieldName, Value, R); return UpdateRecord(FieldName, Value, R);
@@ -662,18 +628,20 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) { template <typename T>
bool GetNameAndDescription(field_name_t FieldName, const T &Value, std::string &Name,
std::string &Description) {
try { try {
assert(ValidFieldName(FieldName)); assert(ValidFieldName(FieldName));
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" ; std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " +
FieldName + "=?";
RecordType R; RecordType R;
auto tValue{Value}; auto tValue{Value};
Select << ConvertParams(St) , Select << ConvertParams(St), Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::use(tValue); Poco::Data::Keywords::use(tValue);
if (Select.execute() == 1) { if (Select.execute() == 1) {
@@ -699,8 +667,7 @@ namespace ORM {
std::string St = "delete from " + TableName_ + " where " + FieldName + "=?"; std::string St = "delete from " + TableName_ + " where " + FieldName + "=?";
auto tValue{Value}; auto tValue{Value};
Delete << ConvertParams(St) , Delete << ConvertParams(St), Poco::Data::Keywords::use(tValue);
Poco::Data::Keywords::use(tValue);
Delete.execute(); Delete.execute();
if (Cache_) if (Cache_)
Cache_->Delete(FieldName, Value); Cache_->Delete(FieldName, Value);
@@ -741,7 +708,8 @@ namespace ORM {
return false; return false;
} }
bool Iterate( std::function<bool(const RecordType &R)> F, const std::string & WhereClause = "" ) { bool Iterate(std::function<bool(const RecordType &R)> F,
const std::string &WhereClause = "") {
try { try {
uint64_t Offset = 0; uint64_t Offset = 0;
@@ -802,10 +770,10 @@ namespace ORM {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
std::string st{"SELECT COUNT(*) FROM " + TableName_ + " " + (Where.empty() ? "" : (" where " + Where)) }; std::string st{"SELECT COUNT(*) FROM " + TableName_ + " " +
(Where.empty() ? "" : (" where " + Where))};
Select << st , Select << st, Poco::Data::Keywords::into(Cnt);
Poco::Data::Keywords::into(Cnt);
Select.execute(); Select.execute();
return Cnt; return Cnt;
@@ -816,7 +784,9 @@ namespace ORM {
return 0; return 0;
} }
template <typename X> bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) { template <typename X>
bool ManipulateVectorMember(X T, field_name_t FieldName, const std::string &ParentUUID,
const std::string &ChildUUID, bool Add) {
try { try {
assert(ValidFieldName(FieldName)); assert(ValidFieldName(FieldName));
@@ -853,7 +823,9 @@ namespace ORM {
Command << i, Poco::Data::Keywords::now; Command << i, Poco::Data::Keywords::now;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
// Logger_.log(E); // Logger_.log(E);
// Logger_.error(Poco::format("The following statement '%s' generated an exception during a table upgrade. This may or may not be a problem.", i)); // Logger_.error(Poco::format("The following statement '%s' generated an
// exception during a table upgrade. This may or may not be a problem.",
// i));
if (!IgnoreExceptions) { if (!IgnoreExceptions) {
return false; return false;
} }
@@ -867,98 +839,137 @@ namespace ORM {
return false; return false;
} }
virtual uint32_t Version() { virtual uint32_t Version() { return 0; }
return 0;
}
virtual bool Upgrade(uint32_t from, uint32_t &to) { virtual bool Upgrade(uint32_t from, uint32_t &to) {
to = from; to = from;
return true; return true;
} }
inline bool AddChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddChild(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteChild(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddLocation(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteLocation(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddContact(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteContact(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddVenue(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteVenue(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddDevice(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteDevice(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddEntity(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DeleteEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteEntity(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddUser(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DelUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DelUser(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddConfiguration(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddConfiguration(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::deviceConfiguration, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::deviceConfiguration, FieldName, ParentUUID,
ChildUUID, true);
} }
inline bool DelConfiguration(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DelConfiguration(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::deviceConfiguration, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::deviceConfiguration, FieldName, ParentUUID,
ChildUUID, false);
} }
inline bool AddVariable(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddVariable(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::variables, FieldName, ParentUUID, ChildUUID, true); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::variables, FieldName, ParentUUID, ChildUUID,
true);
} }
inline bool DelVariable(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) { inline bool DelVariable(field_name_t FieldName, const std::string &ParentUUID,
return ManipulateVectorMember(&RecordType::variables, FieldName, ParentUUID, ChildUUID, false); const std::string &ChildUUID) {
return ManipulateVectorMember(&RecordType::variables, FieldName, ParentUUID, ChildUUID,
false);
} }
inline bool AddInUse(field_name_t FieldName, const std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) { inline bool AddInUse(field_name_t FieldName, const std::string &ParentUUID,
const std::string &Prefix, const std::string &ChildUUID) {
std::string FakeUUID{Prefix + ":" + ChildUUID}; std::string FakeUUID{Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true); return ManipulateVectorMember(&RecordType::inUse, FieldName, ParentUUID, FakeUUID,
true);
} }
inline bool DeleteInUse(field_name_t FieldName, const std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) { inline bool DeleteInUse(field_name_t FieldName, const std::string &ParentUUID,
const std::string &Prefix, const std::string &ChildUUID) {
std::string FakeUUID{Prefix + ":" + ChildUUID}; std::string FakeUUID{Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false); return ManipulateVectorMember(&RecordType::inUse, FieldName, ParentUUID, FakeUUID,
false);
} }
inline bool GetInUse(field_name_t FieldName, const std::string & UUID, std::vector<std::string> & UUIDs ) { inline bool GetInUse(field_name_t FieldName, const std::string &UUID,
std::vector<std::string> &UUIDs) {
RecordType R; RecordType R;
if (GetRecord(FieldName, UUID, R)) { if (GetRecord(FieldName, UUID, R)) {
UUIDs = R.inUse; UUIDs = R.inUse;
@@ -977,16 +988,20 @@ namespace ORM {
} }
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(From<1) From=0; if (From < 1)
From = 0;
switch (Type_) { switch (Type_) {
case OpenWifi::DBType::sqlite: case OpenWifi::DBType::sqlite:
return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " "; return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " ";
case OpenWifi::DBType::pgsql: case OpenWifi::DBType::pgsql:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) +
" ";
case OpenWifi::DBType::mysql: case OpenWifi::DBType::mysql:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) +
" ";
default: default:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) +
" ";
} }
} }
@@ -1010,6 +1025,7 @@ namespace ORM {
Poco::Logger &Logger_; Poco::Logger &Logger_;
std::string Prefix_; std::string Prefix_;
DBCache<RecordType> *Cache_ = nullptr; DBCache<RecordType> *Cache_ = nullptr;
private: private:
std::string CreateFields_; std::string CreateFields_;
std::string SelectFields_; std::string SelectFields_;
@@ -1018,5 +1034,4 @@ namespace ORM {
std::vector<std::string> IndexCreation_; std::vector<std::string> IndexCreation_;
std::map<std::string, int> FieldNames_; std::map<std::string, int> FieldNames_;
}; };
} } // namespace ORM

View File

@@ -4,8 +4,8 @@
#pragma once #pragma once
#include <string>
#include <cstring> #include <cstring>
#include <string>
#include "Poco/String.h" #include "Poco/String.h"
@@ -41,7 +41,10 @@ namespace OpenWifi {
} }
namespace OpenWifi::RESTAPI::Errors { namespace OpenWifi::RESTAPI::Errors {
struct msg { uint64_t err_num; std::string err_txt; }; struct msg {
uint64_t err_num;
std::string err_txt;
};
static const struct msg Error404 { 404, "Resource does not exist." }; static const struct msg Error404 { 404, "Resource does not exist." };
static const struct msg SUCCESS { 0, "No error." }; static const struct msg SUCCESS { 0, "No error." };
@@ -57,7 +60,9 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg RATE_LIMIT_EXCEEDED { 10, "Rate limit exceeded." }; static const struct msg RATE_LIMIT_EXCEEDED { 10, "Rate limit exceeded." };
static const struct msg BAD_MFA_TRANSACTION { 11, "Bad MFA transaction." }; static const struct msg BAD_MFA_TRANSACTION { 11, "Bad MFA transaction." };
static const struct msg MFA_FAILURE { 12, "MFA failure." }; static const struct msg MFA_FAILURE { 12, "MFA failure." };
static const struct msg SECURITY_SERVICE_UNREACHABLE{13,"Security service is unreachable, try again later."}; static const struct msg SECURITY_SERVICE_UNREACHABLE {
13, "Security service is unreachable, try again later."
};
static const struct msg CANNOT_REFRESH_TOKEN { 14, "Cannot refresh token." }; static const struct msg CANNOT_REFRESH_TOKEN { 14, "Cannot refresh token." };
static const struct msg ACCOUNT_SUSPENDED { 15, "Account has been suspended." }; static const struct msg ACCOUNT_SUSPENDED { 15, "Account has been suspended." };
@@ -75,7 +80,9 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg RecordNotCreated { 1011, "Record could not be created." }; static const struct msg RecordNotCreated { 1011, "Record could not be created." };
static const struct msg RecordNotUpdated { 1012, "Record could not be updated." }; static const struct msg RecordNotUpdated { 1012, "Record could not be updated." };
static const struct msg UnknownManagementPolicyUUID { 1013, "Unknown management policy UUID." }; static const struct msg UnknownManagementPolicyUUID { 1013, "Unknown management policy UUID." };
static const struct msg CannotDeleteRoot{1014,"Root Entity cannot be removed, only modified."}; static const struct msg CannotDeleteRoot {
1014, "Root Entity cannot be removed, only modified."
};
static const struct msg MustCreateRootFirst { 1015, "Root entity must be created first." }; static const struct msg MustCreateRootFirst { 1015, "Root entity must be created first." };
static const struct msg ParentUUIDMustExist { 1016, "Parent UUID must exist." }; static const struct msg ParentUUIDMustExist { 1016, "Parent UUID must exist." };
static const struct msg ConfigurationMustExist { 1017, "Configuration must exist." }; static const struct msg ConfigurationMustExist { 1017, "Configuration must exist." };
@@ -95,41 +102,76 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidCommand { 1031, "Invalid command." }; static const struct msg InvalidCommand { 1031, "Invalid command." };
static const struct msg NoRecordsDeleted { 1032, "No records deleted." }; static const struct msg NoRecordsDeleted { 1032, "No records deleted." };
static const struct msg DeviceNotConnected { 1033, "Device is not currently connected." }; static const struct msg DeviceNotConnected { 1033, "Device is not currently connected." };
static const struct msg CannotCreateWS{1034,"Telemetry system could not create WS endpoint. Please try again."}; static const struct msg CannotCreateWS {
static const struct msg BothDeviceTypeRevision{1035,"Both deviceType and revision must be set."}; 1034, "Telemetry system could not create WS endpoint. Please try again."
};
static const struct msg BothDeviceTypeRevision {
1035, "Both deviceType and revision must be set."
};
static const struct msg IdOrSerialEmpty { 1036, "SerialNumber and Id must not be empty." }; static const struct msg IdOrSerialEmpty { 1036, "SerialNumber and Id must not be empty." };
static const struct msg MissingUserID { 1037, "Missing user ID." }; static const struct msg MissingUserID { 1037, "Missing user ID." };
static const struct msg IdMustBe0 { 1038, "To create a user, you must set the ID to 0" }; static const struct msg IdMustBe0 { 1038, "To create a user, you must set the ID to 0" };
static const struct msg InvalidUserRole { 1039, "Invalid userRole." }; static const struct msg InvalidUserRole { 1039, "Invalid userRole." };
static const struct msg InvalidEmailAddress { 1040, "Invalid email address." }; static const struct msg InvalidEmailAddress { 1040, "Invalid email address." };
static const struct msg PasswordRejected{1041,"Password was rejected. This maybe an old password."}; static const struct msg PasswordRejected {
1041, "Password was rejected. This maybe an old password."
};
static const struct msg InvalidIPRanges { 1042, "Invalid IP range specifications." }; static const struct msg InvalidIPRanges { 1042, "Invalid IP range specifications." };
static const struct msg InvalidLOrderBy { 1043, "Invalid orderBy specification." }; static const struct msg InvalidLOrderBy { 1043, "Invalid orderBy specification." };
static const struct msg NeedMobileNumber{1044,"You must provide at least one validated phone number."}; static const struct msg NeedMobileNumber {
1044, "You must provide at least one validated phone number."
};
static const struct msg BadMFAMethod { 1045, "MFA only supports sms or email." }; static const struct msg BadMFAMethod { 1045, "MFA only supports sms or email." };
static const struct msg InvalidCredentials { 1046, "Invalid credentials (username/password)." }; static const struct msg InvalidCredentials { 1046, "Invalid credentials (username/password)." };
static const struct msg InvalidPassword{1047,"Password does not conform to basic password rules."}; static const struct msg InvalidPassword {
static const struct msg UserPendingVerification{1048,"User access denied pending email verification."}; 1047, "Password does not conform to basic password rules."
};
static const struct msg UserPendingVerification {
1048, "User access denied pending email verification."
};
static const struct msg PasswordMustBeChanged { 1049, "Password must be changed." }; static const struct msg PasswordMustBeChanged { 1049, "Password must be changed." };
static const struct msg UnrecognizedRequest{1050,"Ill-formed request. Please consult documentation."}; static const struct msg UnrecognizedRequest {
static const struct msg MissingAuthenticationInformation{1051,"Missing authentication information."}; 1050, "Ill-formed request. Please consult documentation."
static const struct msg InsufficientAccessRights{1052,"Insufficient access rights to complete the operation."}; };
static const struct msg MissingAuthenticationInformation {
1051, "Missing authentication information."
};
static const struct msg InsufficientAccessRights {
1052, "Insufficient access rights to complete the operation."
};
static const struct msg ExpiredToken { 1053, "Token has expired, user must login." }; static const struct msg ExpiredToken { 1053, "Token has expired, user must login." };
static const struct msg SubscriberMustExist { 1054, "Subscriber must exist." }; static const struct msg SubscriberMustExist { 1054, "Subscriber must exist." };
static const struct msg AuthenticatorVerificationIncomplete{1055,"Authenticator validation is not complete."}; static const struct msg AuthenticatorVerificationIncomplete {
static const struct msg SMSCouldNotBeSentRetry{1056,"SMS could not be sent to validate device, try later or change the phone number."}; 1055, "Authenticator validation is not complete."
};
static const struct msg SMSCouldNotBeSentRetry {
1056, "SMS could not be sent to validate device, try later or change the phone number."
};
static const struct msg SMSCouldNotValidate { 1057, "Code and number could not be validated" }; static const struct msg SMSCouldNotValidate { 1057, "Code and number could not be validated" };
static const struct msg InvalidDeviceClass{1058,"Invalid device class. Must be: any, venue, entity, or subscriber"}; static const struct msg InvalidDeviceClass {
static const struct msg SerialNumberAlreadyProvisioned{1059,"This device has already been provisioned to a subscriber."}; 1058, "Invalid device class. Must be: any, venue, entity, or subscriber"
static const struct msg SerialNumberNotTheProperClass{1060,"Device is not available to subscribers. It ahs been assigned to another class of devices."}; };
static const struct msg SerialNumberAlreadyProvisioned {
1059, "This device has already been provisioned to a subscriber."
};
static const struct msg SerialNumberNotTheProperClass {
1060, "Device is not available to subscribers. It ahs been assigned to another class of "
"devices."
};
static const struct msg UserAlreadyExists { 1061, "Username already exists." }; static const struct msg UserAlreadyExists { 1061, "Username already exists." };
static const struct msg NotImplemented { 1062, "Function not implemented." }; static const struct msg NotImplemented { 1062, "Function not implemented." };
static const struct msg VariableMustExist { 1063, "Specified variable does not exist." }; static const struct msg VariableMustExist { 1063, "Specified variable does not exist." };
static const struct msg InvalidEntityType { 1064, "Invalid entity type." }; static const struct msg InvalidEntityType { 1064, "Invalid entity type." };
static const struct msg CannotDeleteSubEntity{1065,"Cannot delete the default subscriber entity."}; static const struct msg CannotDeleteSubEntity {
1065, "Cannot delete the default subscriber entity."
};
static const struct msg OperatorIdMustExist { 1066, "Missing or bad Operator ID" }; static const struct msg OperatorIdMustExist { 1066, "Missing or bad Operator ID" };
static const struct msg CannotDeleteDefaultOperator{1067,"Cannot delete the default operator."}; static const struct msg CannotDeleteDefaultOperator {
static const struct msg CannotCreateDefaultOperator{1068,"Cannot create the default operator."}; 1067, "Cannot delete the default operator."
};
static const struct msg CannotCreateDefaultOperator {
1068, "Cannot create the default operator."
};
static const struct msg InvalidRRM { 1069, "Invalid RRM value." }; static const struct msg InvalidRRM { 1069, "Invalid RRM value." };
static const struct msg InvalidIPAddresses { 1070, "Invalid IP addresses." }; static const struct msg InvalidIPAddresses { 1070, "Invalid IP addresses." };
static const struct msg InvalidBillingCode { 1071, "Empty of invalid billing code." }; static const struct msg InvalidBillingCode { 1071, "Empty of invalid billing code." };
@@ -142,11 +184,19 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidOperatorId { 1078, "Invalid operator ID." }; static const struct msg InvalidOperatorId { 1078, "Invalid operator ID." };
static const struct msg InvalidServiceClassId { 1079, "Invalid service class ID." }; static const struct msg InvalidServiceClassId { 1079, "Invalid service class ID." };
static const struct msg InvalidSubscriberDeviceId { 1080, "Invalid subscriber device ID." }; static const struct msg InvalidSubscriberDeviceId { 1080, "Invalid subscriber device ID." };
static const struct msg InvalidRegistrationOperatorId{1081,"Invalid registration operator ID."}; static const struct msg InvalidRegistrationOperatorId {
static const struct msg InvalidRegistrationOperatorName{1082,"Invalid registration operator name."}; 1081, "Invalid registration operator ID."
};
static const struct msg InvalidRegistrationOperatorName {
1082, "Invalid registration operator name."
};
static const struct msg RegistrationNameDuplicate { 1083, "Registration name must be unique." }; static const struct msg RegistrationNameDuplicate { 1083, "Registration name must be unique." };
static const struct msg SMSMFANotEnabled{1084,"SMS is not enabled in the security service."}; static const struct msg SMSMFANotEnabled {
static const struct msg EMailMFANotEnabled{1085,"email is not enabled in the security service."}; 1084, "SMS is not enabled in the security service."
};
static const struct msg EMailMFANotEnabled {
1085, "email is not enabled in the security service."
};
static const struct msg TOTInvalidCode { 1086, "Invalid code." }; static const struct msg TOTInvalidCode { 1086, "Invalid code." };
static const struct msg TOTInvalidIndex { 1087, "Invalid index." }; static const struct msg TOTInvalidIndex { 1087, "Invalid index." };
@@ -159,7 +209,9 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg SignupWaitingForDevice { 1093, "Waiting for device." }; static const struct msg SignupWaitingForDevice { 1093, "Waiting for device." };
static const struct msg SMSMissingPhoneNumber { 1094, "Missing phone number" }; static const struct msg SMSMissingPhoneNumber { 1094, "Missing phone number" };
static const struct msg SMSTryLater{1095,"SMS could not be sent. Verify the number or try again later."}; static const struct msg SMSTryLater {
1095, "SMS could not be sent. Verify the number or try again later."
};
static const struct msg SMSMissingChallenge { 1096, "Missing 'challengeCode'" }; static const struct msg SMSMissingChallenge { 1096, "Missing 'challengeCode'" };
static const struct msg MustHaveConfigElement { 1097, "Must have 'configuration' element." }; static const struct msg MustHaveConfigElement { 1097, "Must have 'configuration' element." };
@@ -169,60 +221,122 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg SubNoDeviceActivated { 1100, "No devices activated yet." }; static const struct msg SubNoDeviceActivated { 1100, "No devices activated yet." };
static const struct msg SubConfigNotRefreshed { 1101, "Configuration could not be refreshed." }; static const struct msg SubConfigNotRefreshed { 1101, "Configuration could not be refreshed." };
static const struct msg ProvServiceNotAvailable{1102,"Provisioning service not available yet."}; static const struct msg ProvServiceNotAvailable {
static const struct msg SSIDInvalidPassword{1103,"Invalid password length. Must be 8 characters or greater, and a maximum of 32 characters."}; 1102, "Provisioning service not available yet."
static const struct msg InvalidStartingIPAddress{1104,"Invalid starting/ending IP address."}; };
static const struct msg SubnetFormatError{1105,"Subnet must be in format like 192.168.1.1/24."}; static const struct msg SSIDInvalidPassword {
static const struct msg DeviceModeError{1106,"Device mode subnet must be of the form 192.168.1.1/24."}; 1103, "Invalid password length. Must be 8 characters or greater, and a maximum of 32 "
"characters."
};
static const struct msg InvalidStartingIPAddress {
1104, "Invalid starting/ending IP address."
};
static const struct msg SubnetFormatError {
1105, "Subnet must be in format like 192.168.1.1/24."
};
static const struct msg DeviceModeError {
1106, "Device mode subnet must be of the form 192.168.1.1/24."
};
static const struct msg BadDeviceMode { 1107, "Mode must be bridge, nat, or manual." }; static const struct msg BadDeviceMode { 1107, "Mode must be bridge, nat, or manual." };
static const struct msg DefaultGatewayFormat{1108,"Default gateway must be in format like 192.168.1.1."}; static const struct msg DefaultGatewayFormat {
static const struct msg PrimaryDNSFormat{1109,"Primary DNS must be an IP address i.e. 192.168.1.1."}; 1108, "Default gateway must be in format like 192.168.1.1."
};
static const struct msg PrimaryDNSFormat {
1109, "Primary DNS must be an IP address i.e. 192.168.1.1."
};
static const struct msg SecondaryDNSFormat{1110,"Secondary DNS must be an IP address i.e. 192.168.1.1."}; static const struct msg SecondaryDNSFormat {
static const struct msg BadConnectionType{1111,"Internet Connection must be automatic, bridge, pppoe, or manual."}; 1110, "Secondary DNS must be an IP address i.e. 192.168.1.1."
};
static const struct msg BadConnectionType {
1111, "Internet Connection must be automatic, bridge, pppoe, or manual."
};
static const struct msg InvalidDeviceID { 1112, "Invalid deviceID." }; static const struct msg InvalidDeviceID { 1112, "Invalid deviceID." };
static const struct msg InvalidVisibilityAttribute { 1113, "Invalid visibility attribute." }; static const struct msg InvalidVisibilityAttribute { 1113, "Invalid visibility attribute." };
static const struct msg UnknownConfigurationSection { 1114, "Unknown section." }; static const struct msg UnknownConfigurationSection { 1114, "Unknown section." };
static const struct msg CannotValidatePhoneNumber{1115,"Phone number could not be validated."}; static const struct msg CannotValidatePhoneNumber {
1115, "Phone number could not be validated."
};
static const struct msg RootUsersNoOwners { 1116, "ROOT users may not have owners." }; static const struct msg RootUsersNoOwners { 1116, "ROOT users may not have owners." };
static const struct msg PartnerMustHaveEntity{1118,"Partner user must belong to an entity."}; static const struct msg PartnerMustHaveEntity {
1118, "Partner user must belong to an entity."
};
static const struct msg RootCannotModifyUsers { 1119, "ROOT may not modify user roles." }; static const struct msg RootCannotModifyUsers { 1119, "ROOT may not modify user roles." };
static const struct msg CertificateNotIssued { 1120, "Certificate was not issued." }; static const struct msg CertificateNotIssued { 1120, "Certificate was not issued." };
static const struct msg IncompleteCertificate{1121,"Incomplete certificate information. Cannot be downloaded. You must delete and recreate."}; static const struct msg IncompleteCertificate {
1121, "Incomplete certificate information. Cannot be downloaded. You must delete and "
"recreate."
};
static const struct msg InvalidCertificateType { 1122, "Invalid certificate type." }; static const struct msg InvalidCertificateType { 1122, "Invalid certificate type." };
static const struct msg InvalidDeviceName { 1123, "Invalid device name." }; static const struct msg InvalidDeviceName { 1123, "Invalid device name." };
static const struct msg InvalidRedirectorName { 1124, "Invalid redirector name" }; static const struct msg InvalidRedirectorName { 1124, "Invalid redirector name" };
static const struct msg CommonNameAlreadyExists{1125,"A device/server of this name already exists"}; static const struct msg CommonNameAlreadyExists {
static const struct msg CertificateAlreadyExists{1126,"A certificate for this device already exists."}; 1125, "A device/server of this name already exists"
static const struct msg CannotCreateCertTryAgain{1127,"Device certificate could not be created. Please try later."}; };
static const struct msg CertificateAlreadyExists {
1126, "A certificate for this device already exists."
};
static const struct msg CannotCreateCertTryAgain {
1127, "Device certificate could not be created. Please try later."
};
static const struct msg CouldNotRevoke { 1128, "Certificate could not be revoked." }; static const struct msg CouldNotRevoke { 1128, "Certificate could not be revoked." };
static const struct msg CouldNotModifyCert{1129,"Certificate could not me modified. Please verify the information you supplied."}; static const struct msg CouldNotModifyCert {
static const struct msg BatchCertNoCreated{1130,"Certificates have not been created for this batch."}; 1129, "Certificate could not me modified. Please verify the information you supplied."
static const struct msg BatchTooBig{1131,"Illegal number of MAC Addresses: must be between 1 and 1000."}; };
static const struct msg BatchCertNoCreated {
1130, "Certificates have not been created for this batch."
};
static const struct msg BatchTooBig {
1131, "Illegal number of MAC Addresses: must be between 1 and 1000."
};
static const struct msg OutstandingJobs{1132,"Batch has running outstanding jobs. Please wait until job is finished."}; static const struct msg OutstandingJobs {
1132, "Batch has running outstanding jobs. Please wait until job is finished."
};
static const struct msg InvalidSMSNotificationList { 1133, "Invalid SMS Notification list." }; static const struct msg InvalidSMSNotificationList { 1133, "Invalid SMS Notification list." };
static const struct msg InvalidEMailNotificationList{1134,"Invalid email Notification list."}; static const struct msg InvalidEMailNotificationList {
static const struct msg CannotChangeCommanNames{1135,"You cannot provide new/modified common names after jobs have been run for a batch."}; 1134, "Invalid email Notification list."
static const struct msg FailedToVerifyDigicert{1136,"Failed to verify the DigiCert information provided."}; };
static const struct msg CannotChangeCommanNames {
1135, "You cannot provide new/modified common names after jobs have been run for a batch."
};
static const struct msg FailedToVerifyDigicert {
1136, "Failed to verify the DigiCert information provided."
};
static const struct msg CouldNotPerformCommand { 1137, "Could not perform command." }; static const struct msg CouldNotPerformCommand { 1137, "Could not perform command." };
static const struct msg PoolNameInvalid { 1138, "Pool name is invalid." }; static const struct msg PoolNameInvalid { 1138, "Pool name is invalid." };
static const struct msg InvalidRadiusProxyStrategy{1139,"Strategy name must be: random, round_robin, weighted."}; static const struct msg InvalidRadiusProxyStrategy {
static const struct msg InvalidRadiusProxyMonitorMethod{1140,"monitorMethod must be: none, https, radius."}; 1139, "Strategy name must be: random, round_robin, weighted."
static const struct msg MustHaveAtLeastOneRadiusServer{1141,"Must have at least one RADIUS server."}; };
static const struct msg InvalidRadiusServerEntry{1142,"RADIUS Server IP address invalid or port missing."}; static const struct msg InvalidRadiusProxyMonitorMethod {
static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."}; 1140, "monitorMethod must be: none, https, radius."
};
static const struct msg MustHaveAtLeastOneRadiusServer {
1141, "Must have at least one RADIUS server."
};
static const struct msg InvalidRadiusServerEntry {
1142, "RADIUS Server IP address invalid or port missing."
};
static const struct msg InvalidRadiusServerWeigth {
1143, "RADIUS Server IP weight cannot be 0."
};
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"}; static const struct msg MaximumRTTYSessionsReached {
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."}; 1144, "Too many RTTY sessions currently active"
};
static const struct msg DeviceIsAlreadyBusy {
1145, "Device is already executing a command. Please try later."
};
static const struct msg DeviceRequiresSignature{1146,"Device requires device signature to be provided."}; static const struct msg DeviceRequiresSignature {
1146, "Device requires device signature to be provided."
};
static const struct msg ApiKeyNameAlreadyExists { 1147, "API Key name must be unique." }; static const struct msg ApiKeyNameAlreadyExists { 1147, "API Key name must be unique." };
static const struct msg TooManyApiKeys { 1148, "Too many API Keys have already been created." }; static const struct msg TooManyApiKeys { 1148, "Too many API Keys have already been created." };
@@ -230,32 +344,73 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg ApiKeyNameDoesNotExist { 1150, "API Key name does not exist." }; static const struct msg ApiKeyNameDoesNotExist { 1150, "API Key name does not exist." };
static const struct msg ApiKeyDoesNotExist { 1150, "API Key does not exist." }; static const struct msg ApiKeyDoesNotExist { 1150, "API Key does not exist." };
static const struct msg DeviceIsRestricted{1151,"Device is protected by regulation. This function is not allowed."}; static const struct msg DeviceIsRestricted {
1151, "Device is protected by regulation. This function is not allowed."
};
static const struct msg InvalidURI { 1152, "Invalid URI." }; static const struct msg InvalidURI { 1152, "Invalid URI." };
static const struct msg InvalidScriptSelection{1153,"Only script or scriptId must be specified. Not both."}; static const struct msg InvalidScriptSelection {
1153, "Only script or scriptId must be specified. Not both."
};
static const struct msg NoDeviceStatisticsYet { 1154, "Device statistics not available yet." }; static const struct msg NoDeviceStatisticsYet { 1154, "Device statistics not available yet." };
static const struct msg AccountSuspended{1155,"You account was suspended. You can only use this site in read-only mode for now."}; static const struct msg AccountSuspended {
1155, "You account was suspended. You can only use this site in read-only mode for now."
};
static const struct msg BatchNameAlreadyExists { 1156, "Batch name must be unique." }; static const struct msg BatchNameAlreadyExists { 1156, "Batch name must be unique." };
static const struct msg RedirectorNameIsInvalid { 1157, "Redirector name is invalid." }; static const struct msg RedirectorNameIsInvalid { 1157, "Redirector name is invalid." };
static const struct msg CertificateAlreadyBelongsToYou{1158,"The serial number already belongs to you. Please use the certificate modification API to change the redirector."}; static const struct msg CertificateAlreadyBelongsToYou {
static const struct msg RelocationDisabledForThisDevice{1159,"Relocation disabled for this device."}; 1158, "The serial number already belongs to you. Please use the certificate modification "
static const struct msg CannotModifyServerCertificates{1160,"Server certificates cannot be modified."}; "API to change the redirector."
};
static const struct msg RelocationDisabledForThisDevice {
1159, "Relocation disabled for this device."
};
static const struct msg CannotModifyServerCertificates {
1160, "Server certificates cannot be modified."
};
static const struct msg TransferNotInDispute{1161,"The specified transfer is not being disputed."}; static const struct msg TransferNotInDispute {
1161, "The specified transfer is not being disputed."
};
static const struct msg MissingComment { 1162, "Missing comment." }; static const struct msg MissingComment { 1162, "Missing comment." };
static const struct msg EntityNotAllowedToTransfer{1163,"Entity is not allowed to transfer devices."}; static const struct msg EntityNotAllowedToTransfer {
static const struct msg DailyTransferQuotaExceeded{1164,"Entity has exceeded its daily quota."}; 1163, "Entity is not allowed to transfer devices."
static const struct msg CertificateWasNotRevoked{1165,"Certificate was not revoked, so it may not be re-created."}; };
static const struct msg CertificateTransferNoLongerExists{1166,"The device certificate associated with this transfer no longer seem to exist."}; static const struct msg DailyTransferQuotaExceeded {
static const struct msg CertificateTransferEntityNoLongerExists{1167,"The entity tied to this transfer no longer seems to exist."}; 1164, "Entity has exceeded its daily quota."
static const struct msg CannotRollBackDueToDigiCert{1168,"The change could not be rolled back at this time. Please try later."}; };
static const struct msg CertificateTransferAlreadyRolledBack{1169,"The certificate has already been rolled back."}; static const struct msg CertificateWasNotRevoked {
static const struct msg FirmwareBDInProgress{1170,"Firmware DB update already in progress."}; 1165, "Certificate was not revoked, so it may not be re-created."
};
static const struct msg CertificateTransferNoLongerExists {
1166, "The device certificate associated with this transfer no longer seem to exist."
};
static const struct msg CertificateTransferEntityNoLongerExists {
1167, "The entity tied to this transfer no longer seems to exist."
};
static const struct msg CannotRollBackDueToDigiCert {
1168, "The change could not be rolled back at this time. Please try later."
};
static const struct msg CertificateTransferAlreadyRolledBack {
1169, "The certificate has already been rolled back."
};
static const struct msg FirmwareBDInProgress {
1170, "Firmware DB update already in progress."
};
static const struct msg SimulatedDeviceNotSupported {
1171, "Command not supported on simulated device."
};
} static const struct msg SimulationDoesNotExist {
7000, "Simulation Instance ID does not exist."
};
static const struct msg SimulationIsAlreadyRunning {
7001, "There is an instance of this simulation already running.."
};
} // namespace OpenWifi::RESTAPI::Errors
namespace OpenWifi::RESTAPI::Protocol { namespace OpenWifi::RESTAPI::Protocol {
static const char *CAPABILITIES = "capabilities"; static const char *CAPABILITIES = "capabilities";
@@ -388,7 +543,7 @@ 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";
} } // namespace OpenWifi::RESTAPI::Protocol
namespace OpenWifi::uCentralProtocol { namespace OpenWifi::uCentralProtocol {
@@ -411,6 +566,7 @@ namespace OpenWifi::uCentralProtocol {
static const char *HEALTHCHECK = "healthcheck"; static const char *HEALTHCHECK = "healthcheck";
static const char *LOG = "log"; static const char *LOG = "log";
static const char *CRASHLOG = "crashlog"; static const char *CRASHLOG = "crashlog";
static const char *REBOOTLOG = "rebootLog";
static const char *PING = "ping"; static const char *PING = "ping";
static const char *CFGPENDING = "cfgpending"; static const char *CFGPENDING = "cfgpending";
static const char *RECOVERY = "recovery"; static const char *RECOVERY = "recovery";
@@ -469,6 +625,8 @@ namespace OpenWifi::uCentralProtocol {
static const char *DEVICEUPDATE = "deviceupdate"; static const char *DEVICEUPDATE = "deviceupdate";
static const char *FWSIGNATURE = "FWsignature"; static const char *FWSIGNATURE = "FWsignature";
static const char *SIGNATURE = "signature"; static const char *SIGNATURE = "signature";
static const char *INFO = "info";
static const char *DATE = "date";
static const char *SERIALNUMBER = "serialNumber"; static const char *SERIALNUMBER = "serialNumber";
static const char *COMPATIBLE = "compatible"; static const char *COMPATIBLE = "compatible";
@@ -490,7 +648,7 @@ namespace OpenWifi::uCentralProtocol {
static const char *RADIUSCOA = "coa"; static const char *RADIUSCOA = "coa";
static const char *RADIUSDST = "dst"; static const char *RADIUSDST = "dst";
static const char *IES = "ies"; static const char *IES = "ies";
} } // namespace OpenWifi::uCentralProtocol
namespace OpenWifi::uCentralProtocol::Events { namespace OpenWifi::uCentralProtocol::Events {
@@ -499,6 +657,7 @@ namespace OpenWifi::uCentralProtocol::Events {
static const char *HEALTHCHECK = "healthcheck"; static const char *HEALTHCHECK = "healthcheck";
static const char *LOG = "log"; static const char *LOG = "log";
static const char *CRASHLOG = "crashlog"; static const char *CRASHLOG = "crashlog";
static const char *REBOOTLOG = "rebootLog";
static const char *PING = "ping"; static const char *PING = "ping";
static const char *CFGPENDING = "cfgpending"; static const char *CFGPENDING = "cfgpending";
static const char *RECOVERY = "recovery"; static const char *RECOVERY = "recovery";
@@ -522,7 +681,8 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_VENUEBROADCAST, ET_VENUEBROADCAST,
ET_EVENT, ET_EVENT,
ET_WIFISCAN, ET_WIFISCAN,
ET_ALARM ET_ALARM,
ET_REBOOTLOG
}; };
inline EVENT_MSG EventFromString(const std::string &Method) { inline EVENT_MSG EventFromString(const std::string &Method) {
@@ -553,10 +713,12 @@ namespace OpenWifi::uCentralProtocol::Events {
else if (strcmp(WIFISCAN, Method.c_str()) == 0) else if (strcmp(WIFISCAN, Method.c_str()) == 0)
return ET_WIFISCAN; return ET_WIFISCAN;
else if (strcmp(ALARM, Method.c_str()) == 0) else if (strcmp(ALARM, Method.c_str()) == 0)
return ET_WIFISCAN;
return ET_ALARM; return ET_ALARM;
else if (strcmp(REBOOTLOG, Method.c_str()) == 0)
return ET_REBOOTLOG;
return ET_UNKNOWN;
}; };
} } // namespace OpenWifi::uCentralProtocol::Events
namespace OpenWifi::APCommands { namespace OpenWifi::APCommands {
enum class Commands : uint8_t { enum class Commands : uint8_t {
@@ -582,28 +744,17 @@ namespace OpenWifi::APCommands {
}; };
inline static const std::vector<const char *> uCentralAPCommands{ inline static const std::vector<const char *> uCentralAPCommands{
RESTAPI::Protocol::CAPABILITIES, RESTAPI::Protocol::CAPABILITIES, RESTAPI::Protocol::LOGS,
RESTAPI::Protocol::LOGS, RESTAPI::Protocol::HEALTHCHECKS, RESTAPI::Protocol::STATISTICS,
RESTAPI::Protocol::HEALTHCHECKS, RESTAPI::Protocol::STATUS, RESTAPI::Protocol::RTTY,
RESTAPI::Protocol::STATISTICS, RESTAPI::Protocol::CONFIGURE, RESTAPI::Protocol::UPGRADE,
RESTAPI::Protocol::STATUS, RESTAPI::Protocol::REBOOT, RESTAPI::Protocol::FACTORY,
RESTAPI::Protocol::RTTY, RESTAPI::Protocol::LEDS, RESTAPI::Protocol::TRACE,
RESTAPI::Protocol::CONFIGURE, RESTAPI::Protocol::REQUEST, RESTAPI::Protocol::WIFISCAN,
RESTAPI::Protocol::UPGRADE, RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::REBOOT, RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT};
RESTAPI::Protocol::FACTORY,
RESTAPI::Protocol::LEDS,
RESTAPI::Protocol::TRACE,
RESTAPI::Protocol::REQUEST,
RESTAPI::Protocol::WIFISCAN,
RESTAPI::Protocol::EVENTQUEUE,
RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::PING,
RESTAPI::Protocol::SCRIPT};
inline const char * to_string(Commands Cmd) { inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }
return uCentralAPCommands[(uint8_t)Cmd];
}
inline Commands to_apcommand(const char *cmd) { inline Commands to_apcommand(const char *cmd) {
for (auto i = (uint8_t)Commands::capabilities; i != (uint8_t)Commands::unknown; ++i) { for (auto i = (uint8_t)Commands::capabilities; i != (uint8_t)Commands::unknown; ++i) {
@@ -613,7 +764,7 @@ namespace OpenWifi::APCommands {
return Commands::unknown; return Commands::unknown;
} }
} } // namespace OpenWifi::APCommands
namespace OpenWifi::Provisioning::DeviceClass { namespace OpenWifi::Provisioning::DeviceClass {
@@ -627,7 +778,7 @@ namespace OpenWifi::Provisioning::DeviceClass {
return std::find(cbegin(Values), cend(Values), s) != cend(Values); return std::find(cbegin(Values), cend(Values), s) != cend(Values);
} }
} } // namespace OpenWifi::Provisioning::DeviceClass
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@@ -636,5 +787,3 @@ namespace OpenWifi::Provisioning::DeviceClass {
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif

View File

@@ -4,8 +4,8 @@
#include "Poco/Path.h" #include "Poco/Path.h"
#include "framework/utils.h"
#include "framework/AppServiceRegistry.h" #include "framework/AppServiceRegistry.h"
#include "framework/utils.h"
namespace OpenWifi::Utils { namespace OpenWifi::Utils {
@@ -27,11 +27,21 @@ bool NormalizeMac(std::string & Mac) {
std::all_of(Serial.begin(), Serial.end(), [](auto i) { return std::isxdigit(i); })); std::all_of(Serial.begin(), Serial.end(), [](auto i) { return std::isxdigit(i); }));
} }
[[nodiscard]] bool ValidSerialNumbers(const std::vector<std::string> &numbers) {
return std::all_of(numbers.begin(),numbers.end(),[](auto &number) {return ValidSerialNumber(number);});
}
[[nodiscard]] bool ValidUUID(const std::string &UUID) { [[nodiscard]] bool ValidUUID(const std::string &UUID) {
if (UUID.size() > 36) if (UUID.size() > 36)
return false; return false;
uint dashes = 0; uint dashes = 0;
return (std::all_of(UUID.begin(),UUID.end(),[&](auto i){ if(i=='-') dashes++; return i=='-' || std::isxdigit(i);})) && (dashes>0); return (std::all_of(UUID.begin(), UUID.end(),
[&](auto i) {
if (i == '-')
dashes++;
return i == '-' || std::isxdigit(i);
})) &&
(dashes > 0);
} }
[[nodiscard]] std::vector<std::string> Split(const std::string &List, char Delimiter) { [[nodiscard]] std::vector<std::string> Split(const std::string &List, char Delimiter) {
@@ -39,25 +49,20 @@ bool NormalizeMac(std::string & Mac) {
unsigned long P = 0; unsigned long P = 0;
while(P<List.size()) while (P < List.size()) {
{
unsigned long P2 = List.find_first_of(Delimiter, P); unsigned long P2 = List.find_first_of(Delimiter, P);
if (P2 == std::string::npos) { if (P2 == std::string::npos) {
ReturnList.push_back(List.substr(P)); ReturnList.push_back(List.substr(P));
break; break;
} } else
else
ReturnList.push_back(List.substr(P, P2 - P)); ReturnList.push_back(List.substr(P, P2 - P));
P = P2 + 1; P = P2 + 1;
} }
return ReturnList; return ReturnList;
} }
[[nodiscard]] std::string FormatIPv6(const std::string &I) {
[[nodiscard]] std::string FormatIPv6(const std::string & I ) if (I.substr(0, 8) == "[::ffff:") {
{
if(I.substr(0,8) == "[::ffff:")
{
unsigned long PClosingBracket = I.find_first_of(']'); unsigned long PClosingBracket = I.find_first_of(']');
std::string ip = I.substr(8, PClosingBracket - 8); std::string ip = I.substr(8, PClosingBracket - 8);
@@ -82,12 +87,24 @@ void padTo(std::string& str, size_t num, char paddingChar) {
char buf[18]; char buf[18];
buf[0] = R[0]; buf[1] = R[1] ; buf[2] = ':' ; buf[0] = R[0];
buf[3] = R[2] ; buf[4] = R[3]; buf[5] = ':' ; buf[1] = R[1];
buf[6] = R[4]; buf[7] = R[5] ; buf[8] = ':' ; buf[2] = ':';
buf[9] = R[6] ; buf[10]= R[7]; buf[11] = ':'; buf[3] = R[2];
buf[12] = R[8] ; buf[13]= R[9]; buf[14] = ':'; buf[4] = R[3];
buf[15] = R[10] ; buf[16]= R[11];buf[17] = 0; buf[5] = ':';
buf[6] = R[4];
buf[7] = R[5];
buf[8] = ':';
buf[9] = R[6];
buf[10] = R[7];
buf[11] = ':';
buf[12] = R[8];
buf[13] = R[9];
buf[14] = ':';
buf[15] = R[10];
buf[16] = R[11];
buf[17] = 0;
return buf; return buf;
} }
@@ -110,7 +127,8 @@ uint64_t MACToInt(const std::string &MAC) {
} }
[[nodiscard]] bool ValidHostname(const std::string &Hostname) { [[nodiscard]] bool ValidHostname(const std::string &Hostname) {
static std::regex HostNameRegex("^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,6}$"); static std::regex HostNameRegex(
"^(?!-)[A-Za-z0-9-]+([\\-\\.]{1}[a-z0-9]+)*\\.[A-Za-z]{2,6}$");
return std::regex_match(Hostname, HostNameRegex); return std::regex_match(Hostname, HostNameRegex);
} }
@@ -120,8 +138,7 @@ uint64_t MACToInt(const std::string &MAC) {
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
for(const auto &i:B) for (const auto &i : B) {
{
R += (hex[(i & 0xf0) >> 4]); R += (hex[(i & 0xf0) >> 4]);
R += (hex[(i & 0x0f)]); R += (hex[(i & 0x0f)]);
} }
@@ -129,7 +146,8 @@ uint64_t MACToInt(const std::string &MAC) {
return R; return R;
} }
inline static const char kEncodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; inline static const char kEncodeLookup[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
inline static const char kPadCharacter = '='; inline static const char kPadCharacter = '=';
using byte = std::uint8_t; using byte = std::uint8_t;
@@ -171,17 +189,17 @@ using byte = std::uint8_t;
return encoded; return encoded;
} }
[[nodiscard]] std::vector<byte> base64decode(const std::string& input) [[nodiscard]] std::vector<byte> base64decode(const std::string &input) {
{
if (input.length() % 4) if (input.length() % 4)
throw std::runtime_error("Invalid base64 length!"); throw std::runtime_error("Invalid base64 length!");
std::size_t padding = 0; std::size_t padding = 0;
if(input.length()) if (input.length()) {
{ if (input[input.length() - 1] == kPadCharacter)
if(input[input.length() - 1] == kPadCharacter) padding++; padding++;
if(input[input.length() - 2] == kPadCharacter) padding++; if (input[input.length() - 2] == kPadCharacter)
padding++;
} }
std::vector<byte> decoded; std::vector<byte> decoded;
@@ -190,20 +208,21 @@ using byte = std::uint8_t;
std::uint32_t temp = 0; std::uint32_t temp = 0;
auto it = input.begin(); auto it = input.begin();
while(it < input.end()) while (it < input.end()) {
{ for (std::size_t i = 0; i < 4; ++i) {
for(std::size_t i = 0; i < 4; ++i)
{
temp <<= 6; temp <<= 6;
if (*it >= 0x41 && *it <= 0x5A) temp |= *it - 0x41; if (*it >= 0x41 && *it <= 0x5A)
else if(*it >= 0x61 && *it <= 0x7A) temp |= *it - 0x47; temp |= *it - 0x41;
else if(*it >= 0x30 && *it <= 0x39) temp |= *it + 0x04; else if (*it >= 0x61 && *it <= 0x7A)
else if(*it == 0x2B) temp |= 0x3E; temp |= *it - 0x47;
else if(*it == 0x2F) temp |= 0x3F; else if (*it >= 0x30 && *it <= 0x39)
else if(*it == kPadCharacter) temp |= *it + 0x04;
{ else if (*it == 0x2B)
switch(input.end() - it) temp |= 0x3E;
{ else if (*it == 0x2F)
temp |= 0x3F;
else if (*it == kPadCharacter) {
switch (input.end() - it) {
case 1: case 1:
decoded.push_back((temp >> 16) & 0x000000FF); decoded.push_back((temp >> 16) & 0x000000FF);
decoded.push_back((temp >> 8) & 0x000000FF); decoded.push_back((temp >> 8) & 0x000000FF);
@@ -214,8 +233,8 @@ using byte = std::uint8_t;
default: default:
throw std::runtime_error("Invalid padding in base64!"); throw std::runtime_error("Invalid padding in base64!");
} }
} } else
else throw std::runtime_error("Invalid character in base64!"); throw std::runtime_error("Invalid character in base64!");
++it; ++it;
} }
@@ -246,7 +265,6 @@ bool ParseTime(const std::string &Time, int & Hours, int & Minutes, int & Second
return true; return true;
} }
bool ParseDate(const std::string &Time, int &Year, int &Month, int &Day) { bool ParseDate(const std::string &Time, int &Year, int &Month, int &Day) {
Poco::StringTokenizer DateTokens(Time, "-", Poco::StringTokenizer::TOK_TRIM); Poco::StringTokenizer DateTokens(Time, "-", Poco::StringTokenizer::TOK_TRIM);
@@ -276,15 +294,24 @@ bool CompareTime( int H1, int H2, int M1, int M2, int S1, int S2) {
[[nodiscard]] std::string LogLevelToString(int Level) { [[nodiscard]] std::string LogLevelToString(int Level) {
switch (Level) { switch (Level) {
case Poco::Message::PRIO_DEBUG: return "debug"; case Poco::Message::PRIO_DEBUG:
case Poco::Message::PRIO_INFORMATION: return "information"; return "debug";
case Poco::Message::PRIO_FATAL: return "fatal"; case Poco::Message::PRIO_INFORMATION:
case Poco::Message::PRIO_WARNING: return "warning"; return "information";
case Poco::Message::PRIO_NOTICE: return "notice"; case Poco::Message::PRIO_FATAL:
case Poco::Message::PRIO_CRITICAL: return "critical"; return "fatal";
case Poco::Message::PRIO_ERROR: return "error"; case Poco::Message::PRIO_WARNING:
case Poco::Message::PRIO_TRACE: return "trace"; return "warning";
default: return "none"; case Poco::Message::PRIO_NOTICE:
return "notice";
case Poco::Message::PRIO_CRITICAL:
return "critical";
case Poco::Message::PRIO_ERROR:
return "error";
case Poco::Message::PRIO_TRACE:
return "trace";
default:
return "none";
} }
} }
@@ -306,7 +333,6 @@ bool CompareTime( int H1, int H2, int M1, int M2, int S1, int S2) {
return b; return b;
} }
[[nodiscard]] bool SerialNumberMatch(const std::string &S1, const std::string &S2, int Bits) { [[nodiscard]] bool SerialNumberMatch(const std::string &S1, const std::string &S2, int Bits) {
auto S1_i = SerialNumberToInt(S1); auto S1_i = SerialNumberToInt(S1);
auto S2_i = SerialNumberToInt(S2); auto S2_i = SerialNumberToInt(S2);
@@ -375,8 +401,8 @@ bool CompareTime( int H1, int H2, int M1, int M2, int S1, int S2) {
[[nodiscard]] bool ValidEMailAddress(const std::string &email) { [[nodiscard]] bool ValidEMailAddress(const std::string &email) {
// define a regular expression // define a regular expression
static const std::regex pattern static const std::regex pattern(
("[_a-z0-9-]+(\\.[_a-z0-9-]+)*(\\+[a-z0-9-]+)?@[a-z0-9-]+(\\.[a-z0-9-]+)*"); "[_a-z0-9-]+(\\.[_a-z0-9-]+)*(\\+[a-z0-9-]+)?@[a-z0-9-]+(\\.[a-z0-9-]+)*");
// try to match the string with the regular expression // try to match the string with the regular expression
return std::regex_match(email, pattern); return std::regex_match(email, pattern);
} }
@@ -389,7 +415,6 @@ bool CompareTime( int H1, int H2, int M1, int M2, int S1, int S2) {
Poco::StreamCopier::copyStream(IF, OS); Poco::StreamCopier::copyStream(IF, OS);
Result = OS.str(); Result = OS.str();
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
@@ -403,28 +428,29 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
[[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F) { [[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F) {
const auto E = Poco::Path(F.path()).getExtension(); const auto E = Poco::Path(F.path()).getExtension();
if (E == "png") if (E == "png")
return MediaTypeEncoding{ .Encoding = BINARY, return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "image/png"};
.ContentType = "image/png" };
if (E == "gif") if (E == "gif")
return MediaTypeEncoding{ .Encoding = BINARY, return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "image/gif"};
.ContentType = "image/gif" };
if (E == "jpeg" || E == "jpg") if (E == "jpeg" || E == "jpg")
return MediaTypeEncoding{ .Encoding = BINARY, return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "image/jpeg"};
.ContentType = "image/jpeg" };
if (E == "svg" || E == "svgz") if (E == "svg" || E == "svgz")
return MediaTypeEncoding{ .Encoding = PLAIN, return MediaTypeEncoding{.Encoding = PLAIN, .ContentType = "image/svg+xml"};
.ContentType = "image/svg+xml" };
if (E == "html") if (E == "html")
return MediaTypeEncoding{ .Encoding = PLAIN, return MediaTypeEncoding{.Encoding = PLAIN, .ContentType = "text/html"};
.ContentType = "text/html" };
if (E == "css") if (E == "css")
return MediaTypeEncoding{ .Encoding = PLAIN, return MediaTypeEncoding{.Encoding = PLAIN, .ContentType = "text/css"};
.ContentType = "text/css" };
if (E == "js") if (E == "js")
return MediaTypeEncoding{ .Encoding = PLAIN, return MediaTypeEncoding{.Encoding = PLAIN, .ContentType = "application/javascript"};
.ContentType = "application/javascript" }; if (E == "pcap")
return MediaTypeEncoding{ .Encoding = BINARY, return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "application/vnd.tcpdump.pcap"};
.ContentType = "application/octet-stream" }; if (E == "txt")
return MediaTypeEncoding{.Encoding = PLAIN, .ContentType = "text/plain"};
if (E == "tgz")
return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "application/tar+gzip"};
if (E == "gz" || E=="gzip")
return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "application/gzip"};
return MediaTypeEncoding{.Encoding = BINARY, .ContentType = "application/octet-stream"};
} }
[[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F) { [[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F) {
@@ -446,7 +472,6 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
Result += (char)(hex[(C & 0x0f)]); Result += (char)(hex[(C & 0x0f)]);
} }
} catch (...) { } catch (...) {
} }
return Result; return Result;
} }
@@ -459,7 +484,8 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
Seconds -= Hours * (60 * 60); Seconds -= Hours * (60 * 60);
int Minutes = Seconds / 60; int Minutes = Seconds / 60;
Seconds -= Minutes * 60; Seconds -= Minutes * 60;
Result = std::to_string(Days) +" days, " + std::to_string(Hours) + ":" + std::to_string(Minutes) + ":" + std::to_string(Seconds); Result = std::to_string(Days) + " days, " + std::to_string(Hours) + ":" +
std::to_string(Minutes) + ":" + std::to_string(Seconds);
return Result; return Result;
} }
@@ -475,7 +501,8 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
} }
// send request // send request
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, path,
Poco::Net::HTTPMessage::HTTP_1_1);
session.sendRequest(req); session.sendRequest(req);
Poco::Net::HTTPResponse res; Poco::Net::HTTPResponse res;
@@ -487,7 +514,6 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
@@ -497,16 +523,17 @@ void ReplaceVariables( std::string & Content , const Types::StringPairVec & P) {
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort()); Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());
// send request // send request
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, uri.getPath(), Poco::Net::HTTPMessage::HTTP_1_1); Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, uri.getPath(),
Poco::Net::HTTPMessage::HTTP_1_1);
session.sendRequest(req); session.sendRequest(req);
Poco::Net::HTTPResponse res; Poco::Net::HTTPResponse res;
std::istream &is = session.receiveResponse(res); std::istream &is = session.receiveResponse(res);
std::fstream os(FileName,std::ios_base::trunc | std::ios_base::binary | std::ios_base::out); std::fstream os(FileName,
std::ios_base::trunc | std::ios_base::binary | std::ios_base::out);
Poco::StreamCopier::copyStream(is, os); Poco::StreamCopier::copyStream(is, os);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
@@ -519,7 +546,8 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
Poco::StreamCopier::copyStream(b64in, ofs); Poco::StreamCopier::copyStream(b64in, ofs);
int factor = 20; int factor = 20;
unsigned long MaxSize = compress_sz ? (unsigned long) (compress_sz + 5000) : (unsigned long) (ofs.str().size() * factor); unsigned long MaxSize = compress_sz ? (unsigned long)(compress_sz + 5000)
: (unsigned long)(ofs.str().size() * factor);
while (true) { while (true) {
std::vector<uint8_t> UncompressedBuffer(MaxSize); std::vector<uint8_t> UncompressedBuffer(MaxSize);
unsigned long FinalSize = MaxSize; unsigned long FinalSize = MaxSize;
@@ -560,7 +588,6 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
Poco::URI u(uri); Poco::URI u(uri);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
@@ -572,4 +599,4 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
return DT.timestamp().epochTime(); return DT.timestamp().epochTime();
} }
} } // namespace OpenWifi::Utils

View File

@@ -4,34 +4,34 @@
#pragma once #pragma once
#include <string>
#include <fstream> #include <fstream>
#include <iostream>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <random> #include <random>
#include <regex> #include <regex>
#include <thread>
#include <shared_mutex> #include <shared_mutex>
#include <string>
#include <thread>
#include "Poco/Thread.h"
#include "Poco/StringTokenizer.h"
#include "Poco/String.h"
#include "Poco/SHA2Engine.h"
#include "Poco/Message.h"
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "Poco/Net/NetworkInterface.h"
#include "Poco/URI.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Base64Decoder.h" #include "Poco/Base64Decoder.h"
#include "Poco/Base64Encoder.h" #include "Poco/Base64Encoder.h"
#include "Poco/File.h"
#include "Poco/Message.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/NetworkInterface.h"
#include "Poco/SHA2Engine.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Thread.h"
#include "Poco/URI.h"
#include "Poco/zlib.h" #include "Poco/zlib.h"
#include "framework/ow_constants.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "framework/ow_constants.h"
namespace OpenWifi::Utils { namespace OpenWifi::Utils {
@@ -60,11 +60,7 @@ namespace OpenWifi::Utils {
#endif #endif
} }
enum MediaTypeEncodings { enum MediaTypeEncodings { PLAIN, BINARY, BASE64 };
PLAIN,
BINARY,
BASE64
};
struct MediaTypeEncoding { struct MediaTypeEncoding {
MediaTypeEncodings Encoding = PLAIN; MediaTypeEncodings Encoding = PLAIN;
@@ -72,6 +68,7 @@ namespace OpenWifi::Utils {
}; };
[[nodiscard]] bool ValidSerialNumber(const std::string &Serial); [[nodiscard]] bool ValidSerialNumber(const std::string &Serial);
[[nodiscard]] bool ValidSerialNumbers(const std::vector<std::string> &Serial);
[[nodiscard]] bool ValidUUID(const std::string &UUID); [[nodiscard]] bool ValidUUID(const std::string &UUID);
[[nodiscard]] bool ValidHostname(const std::string &hostname); [[nodiscard]] bool ValidHostname(const std::string &hostname);
@@ -98,14 +95,16 @@ namespace OpenWifi::Utils {
using byte = std::uint8_t; using byte = std::uint8_t;
[[nodiscard]] std::string base64encode(const byte *input, uint32_t size); [[nodiscard]] std::string base64encode(const byte *input, uint32_t size);
[[nodiscard]] std::vector<byte> base64decode(const std::string& input);; [[nodiscard]] std::vector<byte> base64decode(const std::string &input);
;
bool ParseTime(const std::string &Time, int &Hours, int &Minutes, int &Seconds); bool ParseTime(const std::string &Time, int &Hours, int &Minutes, int &Seconds);
bool ParseDate(const std::string &Time, int &Year, int &Month, int &Day); bool ParseDate(const std::string &Time, int &Year, int &Month, int &Day);
bool CompareTime(int H1, int H2, int M1, int M2, int S1, int S2); bool CompareTime(int H1, int H2, int M1, int M2, int S1, int S2);
[[nodiscard]] std::string LogLevelToString(int Level); [[nodiscard]] std::string LogLevelToString(int Level);
[[nodiscard]] uint64_t SerialNumberToInt(const std::string &S); [[nodiscard]] uint64_t SerialNumberToInt(const std::string &S);
[[nodiscard]] std::string IntToSerialNumber(uint64_t S); [[nodiscard]] std::string IntToSerialNumber(uint64_t S);
[[nodiscard]] bool SerialNumberMatch(const std::string &S1, const std::string &S2, int Bits=2); [[nodiscard]] bool SerialNumberMatch(const std::string &S1, const std::string &S2,
int Bits = 2);
[[nodiscard]] uint64_t SerialNumberToOUI(const std::string &S); [[nodiscard]] uint64_t SerialNumberToOUI(const std::string &S);
[[nodiscard]] uint64_t GetDefaultMacAsInt64(); [[nodiscard]] uint64_t GetDefaultMacAsInt64();
[[nodiscard]] uint64_t InitializeSystemId(); [[nodiscard]] uint64_t InitializeSystemId();
@@ -124,12 +123,9 @@ namespace OpenWifi::Utils {
[[nodiscard]] std::uint64_t ConvertDate(const std::string &d); [[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
template< typename T > template <typename T> std::string int_to_hex(T i) {
std::string int_to_hex( T i )
{
std::stringstream stream; std::stringstream stream;
stream << std::setfill ('0') << std::setw(12) stream << std::setfill('0') << std::setw(12) << std::hex << i;
<< std::hex << i;
return stream.str(); return stream.str();
} }
@@ -151,4 +147,38 @@ 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);
inline bool match(const char* first, const char* second)
{
// If we reach at the end of both strings, we are done
if (*first == '\0' && *second == '\0')
return true;
// Make sure to eliminate consecutive '*'
if (*first == '*') {
while (*(first + 1) == '*')
first++;
} }
// Make sure that the characters after '*' are present
// in second string. This function assumes that the
// first string will not contain two consecutive '*'
if (*first == '*' && *(first + 1) != '\0'
&& *second == '\0')
return false;
// If the first string contains '?', or current
// characters of both strings match
if (*first == '?' || *first == *second)
return match(first + 1, second + 1);
// If there is *, then there are two possibilities
// a) We consider current character of second string
// b) We ignore current character of second string.
if (*first == '*')
return match(first + 1, second)
|| match(first, second + 1);
return false;
}
} // namespace OpenWifi::Utils