stephb9959
2023-02-21 08:31:20 -08:00
parent c7d8da1b69
commit c0e3303e49
67 changed files with 4291 additions and 3897 deletions

View File

@@ -1,7 +1,178 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Always
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...
BasedOnStyle: LLVM
TabWidth: 4
IndentWidth: 4
UseTab: Always
ColumnLimit: 100
Language: Cpp

View File

@@ -195,7 +195,7 @@ add_executable( owgw
src/AP_WS_Process_telemetry.cpp src/AP_WS_Process_telemetry.cpp
src/AP_WS_Process_venuebroadcast.cpp src/AP_WS_Process_venuebroadcast.cpp
src/RADSEC_server.h src/RADSEC_server.h
src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/ScriptManager.cpp src/ScriptManager.h src/RESTAPI/RESTAPI_scripts_handler.cpp src/RESTAPI/RESTAPI_scripts_handler.h src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h src/storage/storage_scripts.cpp src/storage/storage_scripts.h src/SignatureMgr.cpp src/SignatureMgr.h src/AP_WS_Process_event.cpp src/AP_WS_Process_wifiscan.cpp src/AP_WS_Process_alarm.cpp src/GWKafkaEvents.cpp src/GWKafkaEvents.h) src/UI_GW_WebSocketNotifications.cpp src/UI_GW_WebSocketNotifications.h src/framework/RESTAPI_SystemConfiguration.h src/ScriptManager.cpp src/ScriptManager.h src/RESTAPI/RESTAPI_scripts_handler.cpp src/RESTAPI/RESTAPI_scripts_handler.h src/RESTAPI/RESTAPI_script_handler.cpp src/RESTAPI/RESTAPI_script_handler.h src/storage/storage_scripts.cpp src/storage/storage_scripts.h src/SignatureMgr.h src/AP_WS_Process_event.cpp src/AP_WS_Process_wifiscan.cpp src/AP_WS_Process_alarm.cpp src/GWKafkaEvents.cpp src/GWKafkaEvents.h)
if(NOT SMALL_BUILD) if(NOT SMALL_BUILD)

2
build
View File

@@ -1 +1 @@
35 36

File diff suppressed because it is too large Load Diff

View File

@@ -4,14 +4,14 @@
#pragma once #pragma once
#include <string>
#include <shared_mutex> #include <shared_mutex>
#include <string>
#include "Poco/JSON/Object.h"
#include "Poco/Logger.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketReactor.h" #include "Poco/Net/SocketReactor.h"
#include "Poco/Net/StreamSocket.h" #include "Poco/Net/StreamSocket.h"
#include "Poco/JSON/Object.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Logger.h"
#include "Poco/Net/WebSocket.h" #include "Poco/Net/WebSocket.h"
#include "RESTObjects/RESTAPI_GWobjects.h" #include "RESTObjects/RESTAPI_GWobjects.h"
@@ -20,65 +20,70 @@ namespace OpenWifi {
class AP_WS_Connection { class AP_WS_Connection {
static constexpr int BufSize = 256000; static constexpr int BufSize = 256000;
public: public:
explicit AP_WS_Connection( Poco::Net::HTTPServerRequest &request, explicit AP_WS_Connection(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response, Poco::Net::HTTPServerResponse &response, uint64_t connection_id,
uint64_t connection_id, Poco::Logger &L, Poco::Net::SocketReactor &R);
Poco::Logger &L,
Poco::Net::SocketReactor &R);
~AP_WS_Connection(); ~AP_WS_Connection();
void EndConnection(); void EndConnection();
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc); void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc); void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
void ProcessIncomingFrame(); void ProcessIncomingFrame();
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc); void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
[[nodiscard]] bool Send(const std::string &Payload); [[nodiscard]] bool Send(const std::string &Payload);
bool SendRadiusAuthenticationData(const unsigned char * buffer, std::size_t size); bool SendRadiusAuthenticationData(const unsigned char *buffer, std::size_t size);
bool SendRadiusAccountingData(const unsigned char * buffer, std::size_t size); bool SendRadiusAccountingData(const unsigned char *buffer, std::size_t size);
bool SendRadiusCoAData(const unsigned char * buffer, std::size_t size); bool SendRadiusCoAData(const unsigned char *buffer, std::size_t size);
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf); void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
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);
bool LookForUpgrade(uint64_t UUID, uint64_t & UpgradedUUID); bool LookForUpgrade(uint64_t UUID, uint64_t &UpgradedUUID);
static bool ExtractBase64CompressedData(const std::string & CompressedData, std::string & UnCompressedData, uint64_t compress_sz); static bool ExtractBase64CompressedData(const std::string &CompressedData,
std::string &UnCompressedData,
uint64_t compress_sz);
void LogException(const Poco::Exception &E); void LogException(const Poco::Exception &E);
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval, uint64_t TelemetryWebSocketTimer, const std::vector<std::string> & TelemetryTypes); bool SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t interval,
bool SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t interval, uint64_t TelemetryKafkaTimer, const std::vector<std::string> & TelemetryTypes); uint64_t TelemetryWebSocketTimer,
const std::vector<std::string> &TelemetryTypes);
bool SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t interval,
uint64_t TelemetryKafkaTimer,
const std::vector<std::string> &TelemetryTypes);
bool StopWebSocketTelemetry(uint64_t RPCID); bool StopWebSocketTelemetry(uint64_t RPCID);
bool StopKafkaTelemetry(uint64_t RPCID); bool StopKafkaTelemetry(uint64_t RPCID);
inline void GetLastStats(std::string &LastStats) const { inline void GetLastStats(std::string &LastStats) const {
std::shared_lock G(ConnectionMutex_); std::shared_lock G(ConnectionMutex_);
LastStats = RawLastStats_; LastStats = RawLastStats_;
} }
inline void SetLastStats(const std::string &LastStats) { inline void SetLastStats(const std::string &LastStats) {
std::unique_lock G(ConnectionMutex_); std::unique_lock G(ConnectionMutex_);
RawLastStats_ = LastStats; RawLastStats_ = LastStats;
} }
inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) { inline void SetLastHealthCheck(const GWObjects::HealthCheck &H) {
std::unique_lock G(ConnectionMutex_); std::unique_lock G(ConnectionMutex_);
RawLastHealthcheck_ = H; RawLastHealthcheck_ = H;
} }
inline void GetLastHealthCheck(GWObjects::HealthCheck &H) { inline void GetLastHealthCheck(GWObjects::HealthCheck &H) {
std::shared_lock G(ConnectionMutex_); std::shared_lock G(ConnectionMutex_);
H = RawLastHealthcheck_; H = RawLastHealthcheck_;
} }
inline void GetState(GWObjects::ConnectionState &State) const { inline void GetState(GWObjects::ConnectionState &State) const {
std::shared_lock G(ConnectionMutex_); std::shared_lock G(ConnectionMutex_);
State = State_; State = State_;
} }
inline void GetRestrictions(GWObjects::DeviceRestrictions & R) const { inline void GetRestrictions(GWObjects::DeviceRestrictions &R) const {
std::shared_lock G(ConnectionMutex_); std::shared_lock G(ConnectionMutex_);
R = Restrictions_; R = Restrictions_;
} }
@@ -99,11 +104,11 @@ namespace OpenWifi {
bool ValidatedDevice(); bool ValidatedDevice();
inline bool GetTelemetryParameters(bool & Reporting, uint64_t & Interval, inline bool GetTelemetryParameters(bool &Reporting, uint64_t &Interval,
uint64_t & WebSocketTimer, uint64_t & KafkaTimer, uint64_t &WebSocketTimer, uint64_t &KafkaTimer,
uint64_t &WebSocketCount, uint64_t & KafkaCount, uint64_t &WebSocketCount, uint64_t &KafkaCount,
uint64_t &WebSocketPackets, uint64_t &WebSocketPackets,
uint64_t &KafkaPackets ) const { uint64_t &KafkaPackets) const {
Reporting = TelemetryReporting_; Reporting = TelemetryReporting_;
WebSocketTimer = TelemetryWebSocketTimer_; WebSocketTimer = TelemetryWebSocketTimer_;
KafkaTimer = TelemetryKafkaTimer_; KafkaTimer = TelemetryKafkaTimer_;
@@ -117,48 +122,49 @@ namespace OpenWifi {
friend class AP_WS_Server; friend class AP_WS_Server;
inline GWObjects::DeviceRestrictions Restrictions() const { inline GWObjects::DeviceRestrictions Restrictions() const {
std::shared_lock G(ConnectionMutex_); std::shared_lock G(ConnectionMutex_);
return Restrictions_; return Restrictions_;
} }
private: private:
mutable std::shared_mutex ConnectionMutex_; mutable std::shared_mutex ConnectionMutex_;
std::shared_mutex TelemetryMutex_; std::shared_mutex TelemetryMutex_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
Poco::Net::SocketReactor &Reactor_; Poco::Net::SocketReactor &Reactor_;
std::unique_ptr<Poco::Net::WebSocket> WS_; std::unique_ptr<Poco::Net::WebSocket> WS_;
std::string SerialNumber_; std::string SerialNumber_;
uint64_t SerialNumberInt_=0; uint64_t SerialNumberInt_ = 0;
std::string Compatible_; std::string Compatible_;
std::atomic_bool Registered_ = false ; std::atomic_bool Registered_ = false;
std::string CId_; std::string CId_;
std::string CN_; std::string CN_;
uint64_t Errors_=0; uint64_t Errors_ = 0;
Poco::Net::IPAddress PeerAddress_; Poco::Net::IPAddress PeerAddress_;
volatile bool TelemetryReporting_ = false; volatile bool TelemetryReporting_ = false;
volatile uint64_t TelemetryWebSocketRefCount_ = 0; volatile uint64_t TelemetryWebSocketRefCount_ = 0;
volatile uint64_t TelemetryKafkaRefCount_ = 0; volatile uint64_t TelemetryKafkaRefCount_ = 0;
volatile uint64_t TelemetryWebSocketTimer_ = 0; volatile uint64_t TelemetryWebSocketTimer_ = 0;
volatile uint64_t TelemetryKafkaTimer_ = 0 ; volatile uint64_t TelemetryKafkaTimer_ = 0;
volatile uint64_t TelemetryInterval_ = 0; volatile uint64_t TelemetryInterval_ = 0;
volatile uint64_t TelemetryWebSocketPackets_=0; volatile uint64_t TelemetryWebSocketPackets_ = 0;
volatile uint64_t TelemetryKafkaPackets_=0; volatile uint64_t TelemetryKafkaPackets_ = 0;
GWObjects::ConnectionState State_; GWObjects::ConnectionState State_;
std::string RawLastStats_; std::string RawLastStats_;
GWObjects::HealthCheck RawLastHealthcheck_; GWObjects::HealthCheck RawLastHealthcheck_;
std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ = std::chrono::high_resolution_clock::now(); std::chrono::time_point<std::chrono::high_resolution_clock> ConnectionStart_ =
std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0}; std::chrono::duration<double, std::milli> ConnectionCompletionTime_{0.0};
std::atomic_flag Dead_=false; std::atomic_flag Dead_ = false;
std::atomic_bool DeviceValidated_=false; std::atomic_bool DeviceValidated_ = false;
std::atomic_bool Valid_=false; std::atomic_bool Valid_ = false;
OpenWifi::GWObjects::DeviceRestrictions Restrictions_; OpenWifi::GWObjects::DeviceRestrictions Restrictions_;
static inline std::atomic_uint64_t ConcurrentStartingDevices_=0; static inline std::atomic_uint64_t ConcurrentStartingDevices_ = 0;
bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> & TelemetryTypes); bool StartTelemetry(uint64_t RPCID, const std::vector<std::string> &TelemetryTypes);
bool StopTelemetry(uint64_t RPCID); bool StopTelemetry(uint64_t RPCID);
void UpdateCounts(); void UpdateCounts();
}; };
} } // namespace OpenWifi

View File

@@ -4,16 +4,16 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_alarm(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_alarm(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning( poco_warning(Logger_,
Logger_, fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -29,4 +29,4 @@ namespace OpenWifi {
} }
} }
} }
} } // namespace OpenWifi

View File

@@ -9,8 +9,9 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_cfgpending(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning(Logger_, fmt::format( poco_warning(Logger_,
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -18,9 +19,10 @@ namespace OpenWifi {
[[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID); [[maybe_unused]] uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
[[maybe_unused]] uint64_t Active = ParamsObj->get(uCentralProtocol::ACTIVE); [[maybe_unused]] uint64_t Active = ParamsObj->get(uCentralProtocol::ACTIVE);
poco_trace(Logger_, fmt::format("CFG-PENDING({}): Active: {} Target: {}", CId_, Active, UUID)); poco_trace(Logger_,
fmt::format("CFG-PENDING({}): Active: {} Target: {}", CId_, Active, UUID));
} else { } else {
poco_warning(Logger_, fmt::format("CFG-PENDING({}): Missing some parameters", CId_)); poco_warning(Logger_, fmt::format("CFG-PENDING({}): Missing some parameters", CId_));
} }
} }
} } // namespace OpenWifi

View File

@@ -4,10 +4,10 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "StorageService.h"
#include "FindCountry.h"
#include "Daemon.h"
#include "CentralConfig.h" #include "CentralConfig.h"
#include "Daemon.h"
#include "FindCountry.h"
#include "StorageService.h"
#include "CommandManager.h" #include "CommandManager.h"
@@ -19,13 +19,15 @@
namespace OpenWifi { namespace OpenWifi {
[[maybe_unused]] static void SendKafkaFirmwareUpdate(const std::string &SerialNumber, const std::string &OldFirmware, const std::string &NewFirmware) { [[maybe_unused]] static void SendKafkaFirmwareUpdate(const std::string &SerialNumber,
if(KafkaManager()->Enabled()) { const std::string &OldFirmware,
const std::string &NewFirmware) {
if (KafkaManager()->Enabled()) {
Poco::JSON::Object EventDetails; Poco::JSON::Object EventDetails;
EventDetails.set("oldFirmware", OldFirmware); EventDetails.set("oldFirmware", OldFirmware);
EventDetails.set("newFirmware",NewFirmware); EventDetails.set("newFirmware", NewFirmware);
Poco::JSON::Object Event; Poco::JSON::Object Event;
Event.set("type","device.firmware_change"); Event.set("type", "device.firmware_change");
Event.set("timestamp", Utils::Now()); Event.set("timestamp", Utils::Now());
Event.set("payload", EventDetails); Event.set("payload", EventDetails);
std::ostringstream OS; std::ostringstream OS;
@@ -34,9 +36,9 @@ namespace OpenWifi {
} }
} }
void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj, const std::string &Serial) { void AP_WS_Connection::Process_connect(Poco::JSON::Object::Ptr ParamsObj,
if (ParamsObj->has(uCentralProtocol::UUID) && const std::string &Serial) {
ParamsObj->has(uCentralProtocol::FIRMWARE) && if (ParamsObj->has(uCentralProtocol::UUID) && ParamsObj->has(uCentralProtocol::FIRMWARE) &&
ParamsObj->has(uCentralProtocol::CAPABILITIES)) { ParamsObj->has(uCentralProtocol::CAPABILITIES)) {
uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID); uint64_t UUID = ParamsObj->get(uCentralProtocol::UUID);
auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString(); auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString();
@@ -47,10 +49,10 @@ namespace OpenWifi {
CommandManager()->ClearQueue(SerialNumberInt_); CommandManager()->ClearQueue(SerialNumberInt_);
AP_WS_Server()->SetSessionDetails(State_.sessionId,SerialNumberInt_); AP_WS_Server()->SetSessionDetails(State_.sessionId, SerialNumberInt_);
std::lock_guard Lock(ConnectionMutex_); std::lock_guard Lock(ConnectionMutex_);
Config::Capabilities Caps(Capabilities); Config::Capabilities Caps(Capabilities);
Compatible_ = Caps.Compatible(); Compatible_ = Caps.Compatible();
@@ -61,120 +63,131 @@ namespace OpenWifi {
CId_ = SerialNumber_ + "@" + CId_; CId_ = SerialNumber_ + "@" + CId_;
auto IP = PeerAddress_.toString(); auto IP = PeerAddress_.toString();
if(IP.substr(0,7)=="::ffff:") { if (IP.substr(0, 7) == "::ffff:") {
IP = IP.substr(7); IP = IP.substr(7);
} }
bool RestrictedDevice = false; bool RestrictedDevice = false;
if(Capabilities->has("restrictions")){ if (Capabilities->has("restrictions")) {
RestrictedDevice = true; RestrictedDevice = true;
Poco::JSON::Object::Ptr RestrictionObject = Capabilities->getObject("restrictions"); Poco::JSON::Object::Ptr RestrictionObject = Capabilities->getObject("restrictions");
Restrictions_.from_json(RestrictionObject); Restrictions_.from_json(RestrictionObject);
} }
State_.locale = FindCountryFromIP()->Get(IP); State_.locale = FindCountryFromIP()->Get(IP);
GWObjects::Device DeviceInfo; GWObjects::Device DeviceInfo;
auto DeviceExists = StorageService()->GetDevice(SerialNumber_,DeviceInfo); auto DeviceExists = StorageService()->GetDevice(SerialNumber_, DeviceInfo);
if (Daemon()->AutoProvisioning() && !DeviceExists) { if (Daemon()->AutoProvisioning() && !DeviceExists) {
StorageService()->CreateDefaultDevice(SerialNumber_, Caps, Firmware, PeerAddress_); StorageService()->CreateDefaultDevice(SerialNumber_, Caps, Firmware, PeerAddress_);
} else if (DeviceExists) { } else if (DeviceExists) {
StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps ); StorageService()->UpdateDeviceCapabilities(SerialNumber_, Caps);
int Updated{0}; int Updated{0};
if(!Firmware.empty()) { if (!Firmware.empty()) {
if(Firmware!=DeviceInfo.Firmware) { if (Firmware != DeviceInfo.Firmware) {
DeviceFirmwareChangeKafkaEvent KEvent(SerialNumber_, Utils::Now(),DeviceInfo.Firmware, Firmware ); DeviceFirmwareChangeKafkaEvent KEvent(SerialNumber_, Utils::Now(),
DeviceInfo.Firmware, Firmware);
DeviceInfo.Firmware = Firmware; DeviceInfo.Firmware = Firmware;
DeviceInfo.LastFWUpdate = Utils::Now(); DeviceInfo.LastFWUpdate = Utils::Now();
++Updated; ++Updated;
GWWebSocketNotifications::SingleDeviceFirmwareChange_t Notification; GWWebSocketNotifications::SingleDeviceFirmwareChange_t Notification;
Notification.content.serialNumber = SerialNumber_; Notification.content.serialNumber = SerialNumber_;
Notification.content.newFirmware = Firmware; Notification.content.newFirmware = Firmware;
GWWebSocketNotifications::DeviceFirmwareUpdated(Notification); GWWebSocketNotifications::DeviceFirmwareUpdated(Notification);
} else if(DeviceInfo.LastFWUpdate==0) { } else if (DeviceInfo.LastFWUpdate == 0) {
DeviceInfo.LastFWUpdate = Utils::Now(); DeviceInfo.LastFWUpdate = Utils::Now();
++Updated; ++Updated;
} }
} }
if(DeviceInfo.locale != State_.locale) { if (DeviceInfo.locale != State_.locale) {
DeviceInfo.locale = State_.locale; DeviceInfo.locale = State_.locale;
++Updated; ++Updated;
} }
if(Compatible_ != DeviceInfo.DeviceType) { if (Compatible_ != DeviceInfo.DeviceType) {
DeviceInfo.DeviceType = Compatible_; DeviceInfo.DeviceType = Compatible_;
++Updated; ++Updated;
} }
if(RestrictedDevice != DeviceInfo.restrictedDevice) { if (RestrictedDevice != DeviceInfo.restrictedDevice) {
DeviceInfo.restrictedDevice = RestrictedDevice; DeviceInfo.restrictedDevice = RestrictedDevice;
++Updated; ++Updated;
} }
if(Restrictions_ != DeviceInfo.restrictionDetails) { if (Restrictions_ != DeviceInfo.restrictionDetails) {
DeviceInfo.restrictionDetails = Restrictions_; DeviceInfo.restrictionDetails = Restrictions_;
++Updated; ++Updated;
} }
if(Updated) { if (Updated) {
StorageService()->UpdateDevice(DeviceInfo); StorageService()->UpdateDevice(DeviceInfo);
} }
uint64_t UpgradedUUID=0; uint64_t UpgradedUUID = 0;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID, UpgradedUUID);
State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
} }
State_.Compatible = Compatible_; State_.Compatible = Compatible_;
State_.Connected = true; State_.Connected = true;
ConnectionCompletionTime_ = std::chrono::high_resolution_clock::now() - ConnectionStart_; ConnectionCompletionTime_ =
std::chrono::high_resolution_clock::now() - ConnectionStart_;
State_.connectionCompletionTime = ConnectionCompletionTime_.count(); State_.connectionCompletionTime = ConnectionCompletionTime_.count();
if(State_.VerifiedCertificate == GWObjects::VALID_CERTIFICATE) { if (State_.VerifiedCertificate == GWObjects::VALID_CERTIFICATE) {
if (( Utils::SerialNumberMatch(CN_, SerialNumber_, (int)AP_WS_Server()->MismatchDepth())) || if ((Utils::SerialNumberMatch(CN_, SerialNumber_,
AP_WS_Server()->IsSimSerialNumber(CN_)) { (int)AP_WS_Server()->MismatchDepth())) ||
AP_WS_Server()->IsSimSerialNumber(CN_)) {
State_.VerifiedCertificate = GWObjects::VERIFIED; State_.VerifiedCertificate = GWObjects::VERIFIED;
poco_information(Logger_, fmt::format("CONNECT({}): Fully validated and authenticated device. Session={} ConnectionCompletion Time={}", poco_information(Logger_,
CId_, fmt::format("CONNECT({}): Fully validated and authenticated "
State_.sessionId, "device. Session={} ConnectionCompletion Time={}",
State_.connectionCompletionTime )); CId_, State_.sessionId,
State_.connectionCompletionTime));
} else { } else {
State_.VerifiedCertificate = GWObjects::MISMATCH_SERIAL; State_.VerifiedCertificate = GWObjects::MISMATCH_SERIAL;
if(AP_WS_Server()->AllowSerialNumberMismatch()) { if (AP_WS_Server()->AllowSerialNumberMismatch()) {
poco_information( poco_information(
Logger_, fmt::format("CONNECT({}): Serial number mismatch allowed. CN={} Serial={} Session={} ConnectionCompletion Time={}", Logger_,
CId_, CN_, SerialNumber_, State_.sessionId, fmt::format("CONNECT({}): Serial number mismatch allowed. CN={} "
State_.connectionCompletionTime)); "Serial={} Session={} ConnectionCompletion Time={}",
CId_, CN_, SerialNumber_, State_.sessionId,
State_.connectionCompletionTime));
} else { } else {
poco_information( poco_information(
Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. Device rejected. CN={} Serial={} Session={}", Logger_, fmt::format("CONNECT({}): Serial number mismatch disallowed. "
"Device rejected. CN={} Serial={} Session={}",
CId_, CN_, SerialNumber_, State_.sessionId)); CId_, CN_, SerialNumber_, State_.sessionId));
return EndConnection(); return EndConnection();
} }
} }
} }
GWWebSocketNotifications::SingleDevice_t Notification; GWWebSocketNotifications::SingleDevice_t Notification;
Notification.content.serialNumber = SerialNumber_; Notification.content.serialNumber = SerialNumber_;
GWWebSocketNotifications::DeviceConnected(Notification); GWWebSocketNotifications::DeviceConnected(Notification);
// std::cout << "Serial: " << SerialNumber_ << "Session: " << State_.sessionId << std::endl; // std::cout << "Serial: " << SerialNumber_ << "Session: " << State_.sessionId <<
// std::endl;
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
ParamsObj->set(uCentralProtocol::CONNECTIONIP, CId_); ParamsObj->set(uCentralProtocol::CONNECTIONIP, CId_);
ParamsObj->set("locale", State_.locale ); ParamsObj->set("locale", State_.locale);
ParamsObj->set(uCentralProtocol::TIMESTAMP, Utils::Now()); ParamsObj->set(uCentralProtocol::TIMESTAMP, Utils::Now());
std::ostringstream OS; std::ostringstream OS;
Stringify.condense(ParamsObj, OS); Stringify.condense(ParamsObj, OS);
KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str()); KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, OS.str());
} }
} else { } else {
poco_warning(Logger_,fmt::format("INVALID-PROTOCOL({}): Missing one of uuid, firmware, or capabilities", CId_)); poco_warning(
Logger_,
fmt::format("INVALID-PROTOCOL({}): Missing one of uuid, firmware, or capabilities",
CId_));
Errors_++; Errors_++;
} }
} }
} } // namespace OpenWifi

View File

@@ -5,8 +5,8 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_crashlog(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_crashlog(Poco::JSON::Object::Ptr ParamsObj) {
@@ -34,4 +34,4 @@ namespace OpenWifi {
return; return;
} }
} }
} } // namespace OpenWifi

View File

@@ -9,10 +9,12 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj, std::string &Serial) { void AP_WS_Connection::Process_deviceupdate(Poco::JSON::Object::Ptr ParamsObj,
std::string &Serial) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning(Logger_, fmt::format( poco_warning(Logger_,
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -20,8 +22,10 @@ namespace OpenWifi {
auto Password = ParamsObj->get("currentPassword").toString(); auto Password = ParamsObj->get("currentPassword").toString();
StorageService()->SetDevicePassword(Serial, Password); StorageService()->SetDevicePassword(Serial, Password);
poco_trace(Logger_, fmt::format("DEVICEUPDATE({}): Device is updating its login password.", Serial)); poco_trace(
Logger_,
fmt::format("DEVICEUPDATE({}): Device is updating its login password.", Serial));
} }
} }
} } // namespace OpenWifi

View File

@@ -4,16 +4,16 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_event(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_event(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning( poco_warning(Logger_,
Logger_, fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -41,10 +41,9 @@ namespace OpenWifi {
OS.str()); OS.str());
} }
} }
} catch(const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
} catch(...) { } catch (...) {
} }
} }
} } // namespace OpenWifi

View File

@@ -5,16 +5,17 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "fmt/format.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/utils.h" #include "framework/utils.h"
#include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_healthcheck(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning(Logger_, fmt::format( poco_warning(Logger_,
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -31,16 +32,14 @@ namespace OpenWifi {
request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString(); request_uuid = ParamsObj->get(uCentralProtocol::REQUEST_UUID).toString();
if (request_uuid.empty()) { if (request_uuid.empty()) {
poco_trace(Logger_, poco_trace(Logger_, fmt::format("HEALTHCHECK({}): UUID={} Updating.", CId_, UUID));
fmt::format("HEALTHCHECK({}): UUID={} Updating.", CId_, UUID));
} else { } else {
poco_trace(Logger_, poco_trace(Logger_, fmt::format("HEALTHCHECK({}): UUID={} Updating for CMD={}.",
fmt::format("HEALTHCHECK({}): UUID={} Updating for CMD={}.", CId_, CId_, UUID, request_uuid));
UUID, request_uuid));
} }
uint64_t UpgradedUUID; uint64_t UpgradedUUID;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID, UpgradedUUID);
State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
GWObjects::HealthCheck Check; GWObjects::HealthCheck Check;
@@ -71,4 +70,4 @@ namespace OpenWifi {
} }
} }
} } // namespace OpenWifi

View File

@@ -5,15 +5,15 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_log(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_log(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning( poco_warning(Logger_,
Logger_, fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -41,4 +41,4 @@ namespace OpenWifi {
return; return;
} }
} }
} } // namespace OpenWifi

View File

@@ -15,4 +15,4 @@ namespace OpenWifi {
poco_warning(Logger_, fmt::format("PING({}): Missing parameter.", CId_)); poco_warning(Logger_, fmt::format("PING({}): Missing parameter.", CId_));
} }
} }
} } // namespace OpenWifi

View File

@@ -3,12 +3,11 @@
// //
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h"
#include "CommandManager.h" #include "CommandManager.h"
#include "StorageService.h"
#include "framework/ow_constants.h"
#include "framework/MicroServiceFuncs.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/ow_constants.h" #include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
@@ -52,16 +51,24 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(Params, O); Poco::JSON::Stringifier::stringify(Params, O);
Cmd.Details = O.str(); Cmd.Details = O.str();
bool Sent; bool Sent;
CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(), APCommands::Commands::reboot, SerialNumber_, Cmd.Command, Params, Cmd.UUID, Sent, false, false); CommandManager()->PostCommand(CommandManager()->Next_RPC_ID(),
StorageService()->AddCommand(SerialNumber_, Cmd, Storage::CommandExecutionType::COMMAND_EXECUTED); APCommands::Commands::reboot, SerialNumber_,
poco_information(Logger_, fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_)); Cmd.Command, Params, Cmd.UUID, Sent, false, false);
StorageService()->AddCommand(SerialNumber_, Cmd,
Storage::CommandExecutionType::COMMAND_EXECUTED);
poco_information(
Logger_,
fmt::format("RECOVERY({}): Recovery mode received, need for a reboot.", CId_));
} else { } else {
poco_information(Logger_, fmt::format( poco_information(
"RECOVERY({}): Recovery mode received, no need for a reboot.", CId_)); Logger_,
fmt::format("RECOVERY({}): Recovery mode received, no need for a reboot.",
CId_));
} }
} else { } else {
poco_warning(Logger_, fmt::format("RECOVERY({}): Recovery missing one of serialnumber, firmware, uuid, loglines, reboot", poco_warning(Logger_, fmt::format("RECOVERY({}): Recovery missing one of serialnumber, "
CId_)); "firmware, uuid, loglines, reboot",
CId_));
} }
} }
} } // namespace OpenWifi

View File

@@ -3,8 +3,8 @@
// //
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h"
#include "StateUtils.h" #include "StateUtils.h"
#include "StorageService.h"
#include "UI_GW_WebSocketNotifications.h" #include "UI_GW_WebSocketNotifications.h"
@@ -16,8 +16,9 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_state(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_state(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning(Logger_, fmt::format( poco_warning(Logger_,
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -34,12 +35,12 @@ namespace OpenWifi {
if (request_uuid.empty()) { if (request_uuid.empty()) {
poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating.", CId_, UUID)); poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating.", CId_, UUID));
} else { } else {
poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating for CMD={}.", poco_trace(Logger_, fmt::format("STATE({}): UUID={} Updating for CMD={}.", CId_,
CId_, UUID, request_uuid)); UUID, request_uuid));
} }
uint64_t UpgradedUUID; uint64_t UpgradedUUID;
LookForUpgrade(UUID,UpgradedUUID); LookForUpgrade(UUID, UpgradedUUID);
State_.UUID = UpgradedUUID; State_.UUID = UpgradedUUID;
SetLastStats(StateStr); SetLastStats(StateStr);
@@ -51,10 +52,8 @@ namespace OpenWifi {
StorageService()->SetCommandResult(request_uuid, StateStr); StorageService()->SetCommandResult(request_uuid, StateStr);
} }
StateUtils::ComputeAssociations(StateObj, State_.Associations_2G, StateUtils::ComputeAssociations(StateObj, State_.Associations_2G,
State_.Associations_5G, State_.Associations_5G, State_.Associations_6G);
State_.Associations_6G
);
if (KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Stringifier Stringify; Poco::JSON::Stringifier Stringify;
@@ -63,12 +62,14 @@ namespace OpenWifi {
KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, OS.str()); KafkaManager()->PostMessage(KafkaTopics::STATE, SerialNumber_, OS.str());
} }
GWWebSocketNotifications::SingleDevice_t N; GWWebSocketNotifications::SingleDevice_t N;
N.content.serialNumber = SerialNumber_; N.content.serialNumber = SerialNumber_;
GWWebSocketNotifications::DeviceStatistics(N); GWWebSocketNotifications::DeviceStatistics(N);
} else { } else {
poco_warning(Logger_, fmt::format("STATE({}): Invalid request. Missing serial, uuid, or state", CId_)); poco_warning(
Logger_,
fmt::format("STATE({}): Invalid request. Missing serial, uuid, or state", CId_));
} }
} }
} } // namespace OpenWifi

View File

@@ -3,37 +3,39 @@
// //
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "TelemetryStream.h"
#include "CommandManager.h" #include "CommandManager.h"
#include "TelemetryStream.h"
#include "fmt/format.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/utils.h" #include "framework/utils.h"
#include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_telemetry(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_telemetry(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning(Logger_, fmt::format( poco_warning(Logger_,
"INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
poco_trace(Logger_,fmt::format("Telemetry data received for {}", SerialNumber_)); poco_trace(Logger_, fmt::format("Telemetry data received for {}", SerialNumber_));
if (TelemetryReporting_ || ParamsObj->has("adhoc")) { if (TelemetryReporting_ || ParamsObj->has("adhoc")) {
if (ParamsObj->has("data")) { if (ParamsObj->has("data")) {
auto Payload = ParamsObj->get("data").extract<Poco::JSON::Object::Ptr>(); auto Payload = ParamsObj->get("data").extract<Poco::JSON::Object::Ptr>();
Payload->set("timestamp", Utils::Now()); Payload->set("timestamp", Utils::Now());
std::ostringstream SS; std::ostringstream SS;
Payload->stringify(SS); Payload->stringify(SS);
auto now=Utils::Now(); auto now = Utils::Now();
if(ParamsObj->has("adhoc")) { if (ParamsObj->has("adhoc")) {
KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_, KafkaManager()->PostMessage(KafkaTopics::DEVICE_TELEMETRY, SerialNumber_,
SS.str()); SS.str());
return; return;
} }
if (TelemetryWebSocketRefCount_) { if (TelemetryWebSocketRefCount_) {
if(now<TelemetryWebSocketTimer_) { if (now < TelemetryWebSocketTimer_) {
// std::cout << SerialNumber_ << ": Updating WebSocket telemetry" << std::endl; // std::cout << SerialNumber_ << ": Updating WebSocket telemetry" <<
// std::endl;
TelemetryWebSocketPackets_++; TelemetryWebSocketPackets_++;
State_.websocketPackets = TelemetryWebSocketPackets_; State_.websocketPackets = TelemetryWebSocketPackets_;
TelemetryStream()->NotifyEndPoint(SerialNumberInt_, SS.str()); TelemetryStream()->NotifyEndPoint(SerialNumberInt_, SS.str());
@@ -42,7 +44,7 @@ namespace OpenWifi {
} }
} }
if (TelemetryKafkaRefCount_) { if (TelemetryKafkaRefCount_) {
if(KafkaManager()->Enabled() && now<TelemetryKafkaTimer_) { if (KafkaManager()->Enabled() && now < TelemetryKafkaTimer_) {
// std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl; // std::cout << SerialNumber_ << ": Updating Kafka telemetry" << std::endl;
TelemetryKafkaPackets_++; TelemetryKafkaPackets_++;
State_.kafkaPackets = TelemetryKafkaPackets_; State_.kafkaPackets = TelemetryKafkaPackets_;
@@ -53,12 +55,14 @@ namespace OpenWifi {
} }
} }
} else { } else {
poco_debug(Logger_,fmt::format("TELEMETRY({}): Invalid telemetry packet.",SerialNumber_)); poco_debug(Logger_,
fmt::format("TELEMETRY({}): Invalid telemetry packet.", SerialNumber_));
} }
} else { } else {
// if we are ignoring telemetry, then close it down on the device. // if we are ignoring telemetry, then close it down on the device.
poco_debug(Logger_,fmt::format("TELEMETRY({}): Stopping runaway telemetry.",SerialNumber_)); poco_debug(Logger_,
fmt::format("TELEMETRY({}): Stopping runaway telemetry.", SerialNumber_));
StopTelemetry(CommandManager()->Next_RPC_ID()); StopTelemetry(CommandManager()->Next_RPC_ID());
} }
} }
} } // namespace OpenWifi

View File

@@ -7,11 +7,10 @@
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_venuebroadcast(Poco::JSON::Object::Ptr ParamsObj) {
if(ParamsObj->has("data") && ParamsObj->has("serial") && ParamsObj->has("timestamp")) { if (ParamsObj->has("data") && ParamsObj->has("serial") && ParamsObj->has("timestamp")) {
VenueBroadcaster()->Broadcast( VenueBroadcaster()->Broadcast(ParamsObj->get("serial").toString(),
ParamsObj->get("serial").toString(), ParamsObj->get("data").toString(),
ParamsObj->get("data").toString(), ParamsObj->get("timestamp"));
ParamsObj->get("timestamp"));
} }
} }
} } // namespace OpenWifi

View File

@@ -4,16 +4,16 @@
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/KafkaManager.h" #include "framework/KafkaManager.h"
#include "framework/ow_constants.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_Connection::Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj) { void AP_WS_Connection::Process_wifiscan(Poco::JSON::Object::Ptr ParamsObj) {
if (!State_.Connected) { if (!State_.Connected) {
poco_warning( poco_warning(Logger_,
Logger_, fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol",
fmt::format("INVALID-PROTOCOL({}): Device '{}' is not following protocol", CId_, CN_)); CId_, CN_));
Errors_++; Errors_++;
return; return;
} }
@@ -29,4 +29,4 @@ namespace OpenWifi {
} }
} }
} }
} } // namespace OpenWifi

View File

@@ -4,11 +4,11 @@
#pragma once #pragma once
#include <string>
#include <shared_mutex> #include <shared_mutex>
#include <string>
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Environment.h" #include "Poco/Environment.h"
#include "Poco/Net/SocketAcceptor.h"
#include "framework/utils.h" #include "framework/utils.h"
@@ -16,14 +16,12 @@ namespace OpenWifi {
class AP_WS_ReactorThreadPool { class AP_WS_ReactorThreadPool {
public: public:
explicit AP_WS_ReactorThreadPool() { explicit AP_WS_ReactorThreadPool() {
NumberOfThreads_ = Poco::Environment::processorCount()*2; NumberOfThreads_ = Poco::Environment::processorCount() * 2;
if(NumberOfThreads_==0) if (NumberOfThreads_ == 0)
NumberOfThreads_=4; NumberOfThreads_ = 4;
} }
~ AP_WS_ReactorThreadPool() { ~AP_WS_ReactorThreadPool() { Stop(); }
Stop();
}
void Start() { void Start() {
for (uint64_t i = 0; i < NumberOfThreads_; ++i) { for (uint64_t i = 0; i < NumberOfThreads_; ++i) {
@@ -31,7 +29,7 @@ namespace OpenWifi {
auto NewThread = std::make_unique<Poco::Thread>(); auto NewThread = std::make_unique<Poco::Thread>();
NewThread->start(*NewReactor); NewThread->start(*NewReactor);
std::string ThreadName{"ap:react:" + std::to_string(i)}; std::string ThreadName{"ap:react:" + std::to_string(i)};
Utils::SetThreadName(*NewThread,ThreadName.c_str()); Utils::SetThreadName(*NewThread, ThreadName.c_str());
Reactors_.emplace_back(std::move(NewReactor)); Reactors_.emplace_back(std::move(NewReactor));
Threads_.emplace_back(std::move(NewThread)); Threads_.emplace_back(std::move(NewThread));
} }
@@ -48,17 +46,17 @@ namespace OpenWifi {
} }
Poco::Net::SocketReactor &NextReactor() { Poco::Net::SocketReactor &NextReactor() {
std::shared_lock Lock(Mutex_); std::shared_lock Lock(Mutex_);
NextReactor_++; NextReactor_++;
NextReactor_ %= NumberOfThreads_; NextReactor_ %= NumberOfThreads_;
return *Reactors_[NextReactor_]; return *Reactors_[NextReactor_];
} }
private: private:
std::shared_mutex Mutex_; std::shared_mutex Mutex_;
uint64_t NumberOfThreads_; uint64_t NumberOfThreads_;
uint64_t NextReactor_ = 0; uint64_t NextReactor_ = 0;
std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_; std::vector<std::unique_ptr<Poco::Net::SocketReactor>> Reactors_;
std::vector<std::unique_ptr<Poco::Thread>> Threads_; std::vector<std::unique_ptr<Poco::Thread>> Threads_;
}; };
} } // namespace OpenWifi

View File

@@ -6,35 +6,41 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/Context.h" #include "Poco/Net/Context.h"
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "AP_WS_Server.h"
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "AP_WS_Server.h"
#include "ConfigurationCache.h" #include "ConfigurationCache.h"
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
#include "UI_GW_WebSocketNotifications.h" #include "UI_GW_WebSocketNotifications.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request, void AP_WS_RequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) { Poco::Net::HTTPServerResponse &response) {
try { try {
AP_WS_Server()->AddConnection(id_,std::make_shared<AP_WS_Connection>(request,response,id_, Logger_, AP_WS_Server()->NextReactor())); AP_WS_Server()->AddConnection(
id_, std::make_shared<AP_WS_Connection>(request, response, id_, Logger_,
AP_WS_Server()->NextReactor()));
} catch (...) { } catch (...) {
poco_warning(Logger_,"Exception during WS creation"); poco_warning(Logger_, "Exception during WS creation");
} }
}; };
bool AP_WS_Server::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) { bool AP_WS_Server::ValidateCertificate(const std::string &ConnectionId,
if(IsCertOk()) { const Poco::Crypto::X509Certificate &Certificate) {
if(!Certificate.issuedBy(*IssuerCert_)) { if (IsCertOk()) {
poco_warning(Logger(),fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName())); if (!Certificate.issuedBy(*IssuerCert_)) {
poco_warning(
Logger(),
fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'",
ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
return false; return false;
} }
return true; return true;
@@ -44,16 +50,18 @@ namespace OpenWifi {
int AP_WS_Server::Start() { int AP_WS_Server::Start() {
AllowSerialNumberMismatch_ = MicroServiceConfigGetBool("openwifi.certificates.allowmismatch",true); AllowSerialNumberMismatch_ =
MismatchDepth_ = MicroServiceConfigGetInt("openwifi.certificates.mismatchdepth",2); MicroServiceConfigGetBool("openwifi.certificates.allowmismatch", true);
MismatchDepth_ = MicroServiceConfigGetInt("openwifi.certificates.mismatchdepth", 2);
Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>(); Reactor_pool_ = std::make_unique<AP_WS_ReactorThreadPool>();
Reactor_pool_->Start(); Reactor_pool_->Start();
for(const auto & Svr : ConfigServersList_ ) { for (const auto &Svr : ConfigServersList_) {
poco_notice(Logger(),fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}", Svr.Address(), poco_notice(Logger(),
Svr.Port(), 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())
@@ -61,8 +69,8 @@ namespace OpenWifi {
if (!IsCertOk()) { if (!IsCertOk()) {
IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile()); IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile());
poco_information(Logger(), poco_information(
fmt::format("Certificate Issuer Name:{}", IssuerCert_->issuerName())); Logger(), fmt::format("Certificate Issuer Name:{}", IssuerCert_->issuerName()));
} }
Poco::Net::Context::Params P; Poco::Net::Context::Params P;
@@ -74,7 +82,8 @@ namespace OpenWifi {
P.dhUse2048Bits = true; P.dhUse2048Bits = true;
P.caLocation = Svr.Cas(); P.caLocation = Svr.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));
Poco::Crypto::X509Certificate Cert(Svr.CertFile()); Poco::Crypto::X509Certificate Cert(Svr.CertFile());
Poco::Crypto::X509Certificate Root(Svr.RootCA()); Poco::Crypto::X509Certificate Root(Svr.RootCA());
@@ -96,7 +105,8 @@ namespace OpenWifi {
Context->enableSessionCache(true); Context->enableSessionCache(true);
Context->enableExtendedCertificateVerification(false); Context->enableExtendedCertificateVerification(false);
// Context->disableStatelessSessionResumption(); // Context->disableStatelessSessionResumption();
Context->disableProtocols(Poco::Net::Context::PROTO_TLSV1 | Poco::Net::Context::PROTO_TLSV1_1); Context->disableProtocols(Poco::Net::Context::PROTO_TLSV1 |
Poco::Net::Context::PROTO_TLSV1_1);
auto WebServerHttpParams = new Poco::Net::HTTPServerParams; auto WebServerHttpParams = new Poco::Net::HTTPServerParams;
WebServerHttpParams->setMaxThreads(50); WebServerHttpParams->setMaxThreads(50);
@@ -110,25 +120,29 @@ namespace OpenWifi {
: Poco::Net::AddressFamily::IPv4)); : Poco::Net::AddressFamily::IPv4));
Poco::Net::SocketAddress SockAddr(Addr, Svr.Port()); Poco::Net::SocketAddress SockAddr(Addr, Svr.Port());
auto NewWebServer = std::make_unique<Poco::Net::HTTPServer>( auto NewWebServer = std::make_unique<Poco::Net::HTTPServer>(
new AP_WS_RequestHandlerFactory(Logger()), DeviceConnectionPool_, Poco::Net::SecureServerSocket(SockAddr, Svr.Backlog(), Context), WebServerHttpParams); new AP_WS_RequestHandlerFactory(Logger()), DeviceConnectionPool_,
Poco::Net::SecureServerSocket(SockAddr, Svr.Backlog(), Context),
WebServerHttpParams);
WebServers_.push_back(std::move(NewWebServer)); WebServers_.push_back(std::move(NewWebServer));
} else { } else {
Poco::Net::IPAddress Addr(Svr.Address()); Poco::Net::IPAddress Addr(Svr.Address());
Poco::Net::SocketAddress SockAddr(Addr, Svr.Port()); Poco::Net::SocketAddress SockAddr(Addr, Svr.Port());
auto NewWebServer = std::make_unique<Poco::Net::HTTPServer>( auto NewWebServer = std::make_unique<Poco::Net::HTTPServer>(
new AP_WS_RequestHandlerFactory(Logger()), DeviceConnectionPool_, Poco::Net::SecureServerSocket(SockAddr, Svr.Backlog(), Context), WebServerHttpParams); new AP_WS_RequestHandlerFactory(Logger()), DeviceConnectionPool_,
Poco::Net::SecureServerSocket(SockAddr, Svr.Backlog(), Context),
WebServerHttpParams);
WebServers_.push_back(std::move(NewWebServer)); WebServers_.push_back(std::move(NewWebServer));
} }
} }
for(auto &server:WebServers_) { for (auto &server : WebServers_) {
server->start(); server->start();
} }
ReactorThread_.start(Reactor_); ReactorThread_.start(Reactor_);
auto ProvString = MicroServiceConfigGetString("autoprovisioning.process","default"); auto ProvString = MicroServiceConfigGetString("autoprovisioning.process", "default");
if(ProvString!="default") { if (ProvString != "default") {
auto Tokens = Poco::StringTokenizer(ProvString, ","); auto Tokens = Poco::StringTokenizer(ProvString, ",");
for (const auto &i : Tokens) { for (const auto &i : Tokens) {
if (i == "prov") if (i == "prov")
@@ -140,11 +154,12 @@ namespace OpenWifi {
UseDefaultConfig_ = true; UseDefaultConfig_ = true;
} }
SimulatorId_ = MicroServiceConfigGetString("simulatorid",""); SimulatorId_ = MicroServiceConfigGetString("simulatorid", "");
SimulatorEnabled_ = !SimulatorId_.empty(); SimulatorEnabled_ = !SimulatorId_.empty();
Utils::SetThreadName(ReactorThread_,"dev:react:head"); Utils::SetThreadName(ReactorThread_, "dev:react:head");
GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(*this,&AP_WS_Server::onGarbageCollecting); GarbageCollectorCallback_ = std::make_unique<Poco::TimerCallback<AP_WS_Server>>(
*this, &AP_WS_Server::onGarbageCollecting);
Timer_.setStartInterval(10 * 1000); Timer_.setStartInterval(10 * 1000);
Timer_.setPeriodicInterval(5 * 1000); // every minute Timer_.setPeriodicInterval(5 * 1000); // every minute
Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool()); Timer_.start(*GarbageCollectorCallback_, MicroServiceTimerPool());
@@ -154,8 +169,8 @@ namespace OpenWifi {
} }
void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) { void AP_WS_Server::onGarbageCollecting([[maybe_unused]] Poco::Timer &timer) {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
if(!Garbage_.empty()) { if (!Garbage_.empty()) {
Garbage_.clear(); Garbage_.clear();
} }
@@ -164,11 +179,11 @@ namespace OpenWifi {
NumberOfConnectedDevices_ = 0; NumberOfConnectedDevices_ = 0;
NumberOfConnectingDevices_ = 0; NumberOfConnectingDevices_ = 0;
AverageDeviceConnectionTime_ = 0; AverageDeviceConnectionTime_ = 0;
uint64_t total_connected_time=0; uint64_t total_connected_time = 0;
auto now = Utils::Now(); auto now = Utils::Now();
for (const auto & connection:SerialNumbers_) { for (const auto &connection : SerialNumbers_) {
if(connection.second.second == nullptr) { if (connection.second.second == nullptr) {
continue; continue;
} }
if (connection.second.second->State_.Connected) { if (connection.second.second->State_.Connected) {
@@ -179,15 +194,19 @@ namespace OpenWifi {
} }
} }
AverageDeviceConnectionTime_ = (NumberOfConnectedDevices_!=0) ? total_connected_time/NumberOfConnectedDevices_ : 0; AverageDeviceConnectionTime_ =
if((now-last_log)>120) { (NumberOfConnectedDevices_ != 0) ? total_connected_time / NumberOfConnectedDevices_ : 0;
if ((now - last_log) > 120) {
last_log = now; last_log = now;
poco_information(Logger(), poco_information(
fmt::format("Active AP connections: {} Connecting: {} Average connection time: {} seconds", Logger(),
NumberOfConnectedDevices_, NumberOfConnectingDevices_, AverageDeviceConnectionTime_)); fmt::format(
"Active AP connections: {} Connecting: {} Average connection time: {} seconds",
NumberOfConnectedDevices_, NumberOfConnectingDevices_,
AverageDeviceConnectionTime_));
} }
GWWebSocketNotifications::NumberOfConnection_t Notification; GWWebSocketNotifications::NumberOfConnection_t Notification;
Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_; Notification.content.numberOfConnectingDevices = NumberOfConnectingDevices_;
Notification.content.numberOfDevices = NumberOfConnectedDevices_; Notification.content.numberOfDevices = NumberOfConnectedDevices_;
Notification.content.averageConnectedTime = AverageDeviceConnectionTime_; Notification.content.averageConnectedTime = AverageDeviceConnectionTime_;
@@ -195,22 +214,22 @@ namespace OpenWifi {
} }
void AP_WS_Server::Stop() { void AP_WS_Server::Stop() {
poco_information(Logger(),"Stopping..."); poco_information(Logger(), "Stopping...");
Running_ = false; Running_ = false;
Timer_.stop(); Timer_.stop();
for(auto &server:WebServers_) { for (auto &server : WebServers_) {
server->stopAll(); server->stopAll();
} }
Reactor_pool_->Stop(); Reactor_pool_->Stop();
Reactor_.stop(); Reactor_.stop();
ReactorThread_.join(); ReactorThread_.join();
poco_information(Logger(),"Stopped..."); poco_information(Logger(), "Stopped...");
} }
bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const { bool AP_WS_Server::GetStatistics(uint64_t SerialNumber, std::string &Statistics) const {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -223,8 +242,8 @@ namespace OpenWifi {
return true; return true;
} }
bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState & State) const { bool AP_WS_Server::GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -237,8 +256,9 @@ namespace OpenWifi {
return true; return true;
} }
bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const { bool AP_WS_Server::GetHealthcheck(uint64_t SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; GWObjects::HealthCheck &CheckData) const {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -252,15 +272,15 @@ namespace OpenWifi {
} }
void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) { void AP_WS_Server::SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber) {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Conn = Sessions_.find(connection_id); auto Conn = Sessions_.find(connection_id);
if(Conn == end(Sessions_)) if (Conn == end(Sessions_))
return; return;
auto CurrentSerialNumber = SerialNumbers_.find(SerialNumber); auto CurrentSerialNumber = SerialNumbers_.find(SerialNumber);
if( (CurrentSerialNumber==SerialNumbers_.end()) || if ((CurrentSerialNumber == SerialNumbers_.end()) ||
(CurrentSerialNumber->second.first<connection_id)) { (CurrentSerialNumber->second.first < connection_id)) {
SerialNumbers_[SerialNumber] = std::make_pair(connection_id, Conn->second); SerialNumbers_[SerialNumber] = std::make_pair(connection_id, Conn->second);
return; return;
} }
@@ -270,7 +290,7 @@ namespace OpenWifi {
std::lock_guard G(WSServerMutex_); std::lock_guard G(WSServerMutex_);
auto Session = Sessions_.find(session_id); auto Session = Sessions_.find(session_id);
if(Session==end(Sessions_)) if (Session == end(Sessions_))
return false; return false;
Garbage_.push_back(Session->second); Garbage_.push_back(Session->second);
@@ -281,7 +301,7 @@ namespace OpenWifi {
return false; return false;
} }
if(Device->second.first==session_id) { if (Device->second.first == session_id) {
Sessions_.erase(Session); Sessions_.erase(Session);
SerialNumbers_.erase(Device); SerialNumbers_.erase(Device);
return true; return true;
@@ -291,8 +311,9 @@ namespace OpenWifi {
return false; return false;
} }
bool AP_WS_Server::Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions & Restrictions) const { bool AP_WS_Server::Connected(uint64_t SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; GWObjects::DeviceRestrictions &Restrictions) const {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -302,11 +323,11 @@ namespace OpenWifi {
DevicePtr = Device->second.second; DevicePtr = Device->second.second;
} }
DevicePtr->GetRestrictions(Restrictions); DevicePtr->GetRestrictions(Restrictions);
return DevicePtr->State_.Connected; return DevicePtr->State_.Connected;
} }
bool AP_WS_Server::Connected(uint64_t SerialNumber) const { bool AP_WS_Server::Connected(uint64_t SerialNumber) const {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -315,11 +336,11 @@ namespace OpenWifi {
} }
DevicePtr = Device->second.second; DevicePtr = Device->second.second;
} }
return DevicePtr->State_.Connected; return DevicePtr->State_.Connected;
} }
bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string & Payload) const { bool AP_WS_Server::SendFrame(uint64_t SerialNumber, const std::string &Payload) const {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -331,13 +352,14 @@ namespace OpenWifi {
try { try {
return DevicePtr->Send(Payload); return DevicePtr->Send(Payload);
} catch (...) { } catch (...) {
poco_debug(Logger(),fmt::format(": SendFrame: Could not send data to device '{}'", Utils::IntToSerialNumber(SerialNumber))); poco_debug(Logger(), fmt::format(": SendFrame: Could not send data to device '{}'",
Utils::IntToSerialNumber(SerialNumber)));
} }
return false; return false;
} }
void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) { void AP_WS_Server::StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
@@ -350,8 +372,11 @@ namespace OpenWifi {
DevicePtr->StopWebSocketTelemetry(RPCID); DevicePtr->StopWebSocketTelemetry(RPCID);
} }
void AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime, const std::vector<std::string> & TelemetryTypes) { void
std::shared_ptr<AP_WS_Connection> DevicePtr; AP_WS_Server::SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -363,8 +388,10 @@ namespace OpenWifi {
DevicePtr->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes); DevicePtr->SetWebSocketTelemetryReporting(RPCID, Interval, Lifetime, TelemetryTypes);
} }
void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime, const std::vector<std::string> & TelemetryTypes) { void AP_WS_Server::SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -377,7 +404,7 @@ namespace OpenWifi {
} }
void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) { void AP_WS_Server::StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber) {
std::shared_ptr<AP_WS_Connection> DevicePtr; std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -389,15 +416,12 @@ namespace OpenWifi {
DevicePtr->StopKafkaTelemetry(RPCID); DevicePtr->StopKafkaTelemetry(RPCID);
} }
void AP_WS_Server::GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning, void AP_WS_Server::GetTelemetryParameters(
uint64_t & TelemetryInterval, uint64_t SerialNumber, bool &TelemetryRunning, uint64_t &TelemetryInterval,
uint64_t & TelemetryWebSocketTimer, uint64_t &TelemetryWebSocketTimer, uint64_t &TelemetryKafkaTimer,
uint64_t & TelemetryKafkaTimer, uint64_t &TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
uint64_t & TelemetryWebSocketCount, uint64_t &TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets) {
uint64_t & TelemetryKafkaCount, std::shared_ptr<AP_WS_Connection> DevicePtr;
uint64_t & TelemetryWebSocketPackets,
uint64_t & TelemetryKafkaPackets) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(SerialNumber); auto Device = SerialNumbers_.find(SerialNumber);
@@ -406,14 +430,15 @@ namespace OpenWifi {
} }
DevicePtr = Device->second.second; DevicePtr = Device->second.second;
} }
DevicePtr->GetTelemetryParameters( DevicePtr->GetTelemetryParameters(TelemetryRunning, TelemetryInterval,
TelemetryRunning, TelemetryInterval, TelemetryWebSocketTimer, TelemetryKafkaTimer, TelemetryWebSocketTimer, TelemetryKafkaTimer,
TelemetryWebSocketCount, TelemetryKafkaCount, TelemetryWebSocketPackets, TelemetryWebSocketCount, TelemetryKafkaCount,
TelemetryKafkaPackets); TelemetryWebSocketPackets, TelemetryKafkaPackets);
} }
bool AP_WS_Server::SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool AP_WS_Server::SendRadiusAccountingData(const std::string &SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
@@ -424,15 +449,19 @@ namespace OpenWifi {
} }
try { try {
return DevicePtr->SendRadiusAccountingData(buffer,size); return DevicePtr->SendRadiusAccountingData(buffer, size);
} catch (...) { } catch (...) {
poco_debug(Logger(),fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'", SerialNumber)); poco_debug(
Logger(),
fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'",
SerialNumber));
} }
return false; return false;
} }
bool AP_WS_Server::SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool AP_WS_Server::SendRadiusAuthenticationData(const std::string &SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
@@ -443,15 +472,19 @@ namespace OpenWifi {
} }
try { try {
return DevicePtr->SendRadiusAuthenticationData(buffer,size); return DevicePtr->SendRadiusAuthenticationData(buffer, size);
} catch (...) { } catch (...) {
poco_debug(Logger(),fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'", SerialNumber)); poco_debug(
Logger(),
fmt::format(": SendRadiusAuthenticationData: Could not send data to device '{}'",
SerialNumber));
} }
return false; return false;
} }
bool AP_WS_Server::SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size) { bool AP_WS_Server::SendRadiusCoAData(const std::string &SerialNumber,
std::shared_ptr<AP_WS_Connection> DevicePtr; const unsigned char *buffer, std::size_t size) {
std::shared_ptr<AP_WS_Connection> DevicePtr;
{ {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber)); auto Device = SerialNumbers_.find(Utils::SerialNumberToInt(SerialNumber));
@@ -462,11 +495,13 @@ namespace OpenWifi {
} }
try { try {
return DevicePtr->SendRadiusCoAData(buffer,size); return DevicePtr->SendRadiusCoAData(buffer, size);
} catch (...) { } catch (...) {
poco_debug(Logger(),fmt::format(": SendRadiusCoAData: Could not send data to device '{}'", SerialNumber)); poco_debug(Logger(),
fmt::format(": SendRadiusCoAData: Could not send data to device '{}'",
SerialNumber));
} }
return false; return false;
} }
} //namespace } // namespace OpenWifi

View File

@@ -8,62 +8,59 @@
#pragma once #pragma once
#include <mutex>
#include <thread>
#include <array> #include <array>
#include <ctime> #include <ctime>
#include <mutex>
#include <thread>
#include "Poco/AutoPtr.h" #include "Poco/AutoPtr.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Timer.h"
#include "Poco/Net/HTTPRequestHandler.h" #include "Poco/Net/HTTPRequestHandler.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/HTTPServerRequest.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Timer.h"
#include "AP_WS_Connection.h" #include "AP_WS_Connection.h"
#include "AP_WS_ReactorPool.h" #include "AP_WS_ReactorPool.h"
#include "framework/utils.h"
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
#include "framework/utils.h"
namespace OpenWifi { namespace OpenWifi {
class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler { class AP_WS_RequestHandler : public Poco::Net::HTTPRequestHandler {
public: public:
explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) explicit AP_WS_RequestHandler(Poco::Logger &L, uint64_t id) : Logger_(L), id_(id){};
: Logger_(L),
id_(id){
};
void handleRequest(Poco::Net::HTTPServerRequest &request, void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override; Poco::Net::HTTPServerResponse &response) override;
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
uint64_t id_=0; uint64_t id_ = 0;
}; };
class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { class AP_WS_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public: public:
inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) inline explicit AP_WS_RequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
: Logger_(L) {
}
inline Poco::Net::HTTPRequestHandler * inline Poco::Net::HTTPRequestHandler *
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override { createRequestHandler(const Poco::Net::HTTPServerRequest &request) override {
if (request.find("Upgrade") != request.end() && if (request.find("Upgrade") != request.end() &&
Poco::icompare(request["Upgrade"], "websocket") == 0) { Poco::icompare(request["Upgrade"], "websocket") == 0) {
Utils::SetThreadName("ws:conn-init"); Utils::SetThreadName("ws:conn-init");
return new AP_WS_RequestHandler(Logger_,id_++); return new AP_WS_RequestHandler(Logger_, id_++);
} else { } else {
return nullptr; return nullptr;
} }
} }
private: private:
Poco::Logger &Logger_; Poco::Logger &Logger_;
inline static uint64_t id_=1; inline static uint64_t id_ = 1;
}; };
class AP_WS_Server : public SubSystemServer { class AP_WS_Server : public SubSystemServer {
@@ -75,136 +72,143 @@ namespace OpenWifi {
int Start() override; int Start() override;
void Stop() override; void Stop() override;
bool IsCertOk() { return IssuerCert_!= nullptr; } bool IsCertOk() { return IssuerCert_ != nullptr; }
bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate); bool ValidateCertificate(const std::string &ConnectionId,
const Poco::Crypto::X509Certificate &Certificate);
// Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); } // Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); }
inline bool IsSimSerialNumber(const std::string & SerialNumber) const { inline bool IsSimSerialNumber(const std::string &SerialNumber) const {
return IsSim(Poco::toLower(SerialNumber)) && Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_); return IsSim(Poco::toLower(SerialNumber)) &&
Poco::toLower(SerialNumber) == Poco::toLower(SimulatorId_);
} }
inline static bool IsSim(const std::string & SerialNumber) { inline static bool IsSim(const std::string &SerialNumber) {
return SerialNumber.substr(0,6) == "53494d"; return SerialNumber.substr(0, 6) == "53494d";
} }
inline bool IsSimEnabled() const { inline bool IsSimEnabled() const { return SimulatorEnabled_; }
return SimulatorEnabled_;
}
inline bool AllowSerialNumberMismatch() const { inline bool AllowSerialNumberMismatch() const { return AllowSerialNumberMismatch_; }
return AllowSerialNumberMismatch_;
}
inline uint64_t MismatchDepth() const { inline uint64_t MismatchDepth() const { return MismatchDepth_; }
return MismatchDepth_;
}
inline bool UseProvisioning() const { return LookAtProvisioning_; } inline bool UseProvisioning() const { return LookAtProvisioning_; }
inline bool UseDefaults() const { return UseDefaultConfig_; } inline bool UseDefaults() const { return UseDefaultConfig_; }
[[nodiscard]] inline Poco::Net::SocketReactor & NextReactor() { return Reactor_pool_->NextReactor(); } [[nodiscard]] inline Poco::Net::SocketReactor &NextReactor() {
return Reactor_pool_->NextReactor();
}
[[nodiscard]] inline bool Running() const { return Running_; } [[nodiscard]] inline bool Running() const { return Running_; }
inline void AddConnection(uint64_t session_id, std::shared_ptr<AP_WS_Connection> Connection ) { inline void AddConnection(uint64_t session_id,
std::lock_guard Lock(WSServerMutex_); std::shared_ptr<AP_WS_Connection> Connection) {
std::lock_guard Lock(WSServerMutex_);
Sessions_[session_id] = std::move(Connection); Sessions_[session_id] = std::move(Connection);
} }
inline std::shared_ptr<AP_WS_Connection> FindConnection(uint64_t session_id) const { inline std::shared_ptr<AP_WS_Connection> FindConnection(uint64_t session_id) const {
std::lock_guard Lock(WSServerMutex_); std::lock_guard Lock(WSServerMutex_);
auto Connection = Sessions_.find(session_id); auto Connection = Sessions_.find(session_id);
if(Connection!=end(Sessions_)) if (Connection != end(Sessions_))
return Connection->second; return Connection->second;
return nullptr; return nullptr;
} }
inline bool GetStatistics(const std::string &SerialNumber, std::string & Statistics) const { inline bool GetStatistics(const std::string &SerialNumber, std::string &Statistics) const {
return GetStatistics(Utils::SerialNumberToInt(SerialNumber),Statistics); return GetStatistics(Utils::SerialNumberToInt(SerialNumber), Statistics);
} }
bool GetStatistics(uint64_t SerialNumber, std::string & Statistics) const ; bool GetStatistics(uint64_t SerialNumber, std::string &Statistics) const;
inline bool GetState(const std::string & SerialNumber, GWObjects::ConnectionState & State) const { inline bool GetState(const std::string &SerialNumber,
GWObjects::ConnectionState &State) const {
return GetState(Utils::SerialNumberToInt(SerialNumber), State); return GetState(Utils::SerialNumberToInt(SerialNumber), State);
} }
bool GetState(uint64_t SerialNumber, GWObjects::ConnectionState & State) const; bool GetState(uint64_t SerialNumber, GWObjects::ConnectionState &State) const;
inline bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData) const { inline bool GetHealthcheck(const std::string &SerialNumber,
GWObjects::HealthCheck &CheckData) const {
return GetHealthcheck(Utils::SerialNumberToInt(SerialNumber), CheckData); return GetHealthcheck(Utils::SerialNumberToInt(SerialNumber), CheckData);
} }
bool GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck & CheckData) const ; bool GetHealthcheck(uint64_t SerialNumber, GWObjects::HealthCheck &CheckData) const;
bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions & Restrictions) const ; bool Connected(uint64_t SerialNumber, GWObjects::DeviceRestrictions &Restrictions) const;
bool Connected(uint64_t SerialNumber) const ; bool Connected(uint64_t SerialNumber) const;
inline bool SendFrame(const std::string & SerialNumber, const std::string & Payload) const { inline bool SendFrame(const std::string &SerialNumber, const std::string &Payload) const {
return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload); return SendFrame(Utils::SerialNumberToInt(SerialNumber), Payload);
} }
bool SendFrame(uint64_t SerialNumber, const std::string & Payload) const ; bool SendFrame(uint64_t SerialNumber, const std::string &Payload) const;
bool SendRadiusAuthenticationData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); bool SendRadiusAuthenticationData(const std::string &SerialNumber,
bool SendRadiusAccountingData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); const unsigned char *buffer, std::size_t size);
bool SendRadiusCoAData(const std::string & SerialNumber, const unsigned char * buffer, std::size_t size); bool SendRadiusAccountingData(const std::string &SerialNumber, const unsigned char *buffer,
std::size_t size);
bool SendRadiusCoAData(const std::string &SerialNumber, const unsigned char *buffer,
std::size_t size);
void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber); void SetSessionDetails(uint64_t connection_id, uint64_t SerialNumber);
bool EndSession(uint64_t connection_id, uint64_t serial_number); bool EndSession(uint64_t connection_id, uint64_t serial_number);
void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime, const std::vector<std::string> & TelemetryTypes); void SetWebSocketTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber,
uint64_t Interval, uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes);
void StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber); void StopWebSocketTelemetry(uint64_t RPCID, uint64_t SerialNumber);
void SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval, uint64_t Lifetime, const std::vector<std::string> & TelemetryTypes); void SetKafkaTelemetryReporting(uint64_t RPCID, uint64_t SerialNumber, uint64_t Interval,
uint64_t Lifetime,
const std::vector<std::string> &TelemetryTypes);
void StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber); void StopKafkaTelemetry(uint64_t RPCID, uint64_t SerialNumber);
void GetTelemetryParameters(uint64_t SerialNumber , bool & TelemetryRunning, void GetTelemetryParameters(uint64_t SerialNumber, bool &TelemetryRunning,
uint64_t & TelemetryInterval, uint64_t &TelemetryInterval, uint64_t &TelemetryWebSocketTimer,
uint64_t & TelemetryWebSocketTimer, uint64_t &TelemetryKafkaTimer,
uint64_t & TelemetryKafkaTimer, uint64_t &TelemetryWebSocketCount,
uint64_t & TelemetryWebSocketCount, uint64_t &TelemetryKafkaCount,
uint64_t & TelemetryKafkaCount, uint64_t &TelemetryWebSocketPackets,
uint64_t & TelemetryWebSocketPackets, uint64_t &TelemetryKafkaPackets);
uint64_t & TelemetryKafkaPackets);
void onGarbageCollecting(Poco::Timer & timer); void onGarbageCollecting(Poco::Timer &timer);
inline void AverageDeviceStatistics( uint64_t & Connections, uint64_t & AverageConnectionTime, uint64_t & NumberOfConnectingDevices) const { inline void AverageDeviceStatistics(uint64_t &Connections, uint64_t &AverageConnectionTime,
uint64_t &NumberOfConnectingDevices) const {
Connections = NumberOfConnectedDevices_; Connections = NumberOfConnectedDevices_;
AverageConnectionTime = AverageDeviceConnectionTime_; AverageConnectionTime = AverageDeviceConnectionTime_;
NumberOfConnectingDevices = NumberOfConnectingDevices_; NumberOfConnectingDevices = NumberOfConnectingDevices_;
} }
private: private:
mutable std::recursive_mutex WSServerMutex_; mutable std::recursive_mutex WSServerMutex_;
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_; std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_; std::list<std::unique_ptr<Poco::Net::HTTPServer>> WebServers_;
Poco::Net::SocketReactor Reactor_; Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_; Poco::Thread ReactorThread_;
std::string SimulatorId_; std::string SimulatorId_;
Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64}; Poco::ThreadPool DeviceConnectionPool_{"ws:dev-pool", 2, 64};
bool LookAtProvisioning_ = false; bool LookAtProvisioning_ = false;
bool UseDefaultConfig_ = true; bool UseDefaultConfig_ = true;
bool SimulatorEnabled_=false; bool SimulatorEnabled_ = false;
std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_; std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
std::atomic_bool Running_=false; std::atomic_bool Running_ = false;
// std::map<uint64_t, std::pair<std::shared_ptr<AP_WS_Connection>,bool>> Sessions_; // std::map<uint64_t, std::pair<std::shared_ptr<AP_WS_Connection>,bool>> Sessions_;
std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_; std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>> Sessions_;
std::map<uint64_t, std::pair<uint64_t,std::shared_ptr<AP_WS_Connection>>> SerialNumbers_; std::map<uint64_t, std::pair<uint64_t, std::shared_ptr<AP_WS_Connection>>> SerialNumbers_;
std::atomic_bool AllowSerialNumberMismatch_=true; std::atomic_bool AllowSerialNumberMismatch_ = true;
std::atomic_uint64_t MismatchDepth_=2; std::atomic_uint64_t MismatchDepth_ = 2;
std::atomic_uint64_t NumberOfConnectedDevices_=0; std::atomic_uint64_t NumberOfConnectedDevices_ = 0;
std::atomic_uint64_t AverageDeviceConnectionTime_=0; std::atomic_uint64_t AverageDeviceConnectionTime_ = 0;
std::atomic_uint64_t NumberOfConnectingDevices_=0; std::atomic_uint64_t NumberOfConnectingDevices_ = 0;
std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_; std::vector<std::shared_ptr<AP_WS_Connection>> Garbage_;
std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_; std::unique_ptr<Poco::TimerCallback<AP_WS_Server>> GarbageCollectorCallback_;
Poco::Timer Timer_; Poco::Timer Timer_;
Poco::Thread GarbageCollector_; Poco::Thread GarbageCollector_;
AP_WS_Server() noexcept: AP_WS_Server() noexcept
SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") { : SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {}
}
}; };
inline auto AP_WS_Server() { return AP_WS_Server::instance(); } inline auto AP_WS_Server() { return AP_WS_Server::instance(); }
} //namespace } // namespace OpenWifi

View File

@@ -4,54 +4,53 @@
#pragma once #pragma once
#include <string> #include <fstream>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <fstream> #include <string>
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "nlohmann/json.hpp"
#include "CentralConfig.h" #include "CentralConfig.h"
#include "nlohmann/json.hpp"
namespace OpenWifi { namespace OpenWifi {
const std::string PlatformCacheFileName{"/plat_cache.json"}; const std::string PlatformCacheFileName{"/plat_cache.json"};
const std::string CapabilitiesCacheFileName{"/caps_cache.json"}; const std::string CapabilitiesCacheFileName{"/caps_cache.json"};
typedef std::map<std::string,nlohmann::json> CapabilitiesCache_t; typedef std::map<std::string, nlohmann::json> CapabilitiesCache_t;
class CapabilitiesCache { class CapabilitiesCache {
public: public:
static auto instance() { static auto instance() {
static auto instance = new CapabilitiesCache; static auto instance = new CapabilitiesCache;
return instance; return instance;
} }
inline void Add(const Config::Capabilities &Caps) { inline void Add(const Config::Capabilities &Caps) {
if(Caps.Compatible().empty() || Caps.Platform().empty()) if (Caps.Compatible().empty() || Caps.Platform().empty())
return; return;
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(!PlatformsLoaded_) if (!PlatformsLoaded_)
LoadPlatforms(); LoadPlatforms();
auto P = Poco::toUpper(Caps.Platform()); auto P = Poco::toUpper(Caps.Platform());
auto Hint = Platforms_.find(Caps.Compatible()); auto Hint = Platforms_.find(Caps.Compatible());
if(Hint==Platforms_.end()) { if (Hint == Platforms_.end()) {
Platforms_.insert(std::make_pair(Caps.Compatible(),P)); Platforms_.insert(std::make_pair(Caps.Compatible(), P));
SavePlatforms(); SavePlatforms();
} else if(Hint->second != P) { } else if (Hint->second != P) {
Hint->second = P; Hint->second = P;
SavePlatforms(); SavePlatforms();
} }
if(!CapabilitiesLoaded_) if (!CapabilitiesLoaded_)
LoadCapabilities(); LoadCapabilities();
auto CapHint = Capabilities_.find(Caps.Compatible()); auto CapHint = Capabilities_.find(Caps.Compatible());
if(CapHint==Capabilities_.end()) { if (CapHint == Capabilities_.end()) {
auto C = nlohmann::json::parse(Caps.AsString()); auto C = nlohmann::json::parse(Caps.AsString());
C.erase("restrictions"); C.erase("restrictions");
Capabilities_[Caps.Compatible()] = nlohmann::json::parse(Caps.AsString()); Capabilities_[Caps.Compatible()] = nlohmann::json::parse(Caps.AsString());
SaveCapabilities(); SaveCapabilities();
} else { } else {
@@ -60,48 +59,49 @@ namespace OpenWifi {
} }
} }
inline std::string GetPlatform(const std::string & DeviceType) { inline std::string GetPlatform(const std::string &DeviceType) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(!PlatformsLoaded_) { if (!PlatformsLoaded_) {
LoadPlatforms(); LoadPlatforms();
} }
auto Hint = Platforms_.find(DeviceType); auto Hint = Platforms_.find(DeviceType);
if(Hint==Platforms_.end()) if (Hint == Platforms_.end())
return "AP"; return "AP";
return Hint->second; return Hint->second;
} }
inline nlohmann::json GetCapabilities(const std::string & DeviceType) { inline nlohmann::json GetCapabilities(const std::string &DeviceType) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(!CapabilitiesLoaded_) { if (!CapabilitiesLoaded_) {
LoadCapabilities(); LoadCapabilities();
} }
auto Hint = Capabilities_.find(DeviceType); auto Hint = Capabilities_.find(DeviceType);
if(Hint==Capabilities_.end()) if (Hint == Capabilities_.end())
return nlohmann::json{}; return nlohmann::json{};
return Hint->second; return Hint->second;
} }
inline const CapabilitiesCache_t & AllCapabilities() { inline const CapabilitiesCache_t &AllCapabilities() {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(!CapabilitiesLoaded_) { if (!CapabilitiesLoaded_) {
LoadCapabilities(); LoadCapabilities();
} }
return Capabilities_; return Capabilities_;
} }
private: private:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
std::atomic_bool PlatformsLoaded_=false; std::atomic_bool PlatformsLoaded_ = false;
std::atomic_bool CapabilitiesLoaded_=false; std::atomic_bool CapabilitiesLoaded_ = false;
std::map<std::string,std::string> Platforms_; std::map<std::string, std::string> Platforms_;
CapabilitiesCache_t Capabilities_; CapabilitiesCache_t Capabilities_;
std::string PlatformCacheFileName_{ MicroServiceDataDirectory()+PlatformCacheFileName }; std::string PlatformCacheFileName_{MicroServiceDataDirectory() + PlatformCacheFileName};
std::string CapabilitiesCacheFileName_{ MicroServiceDataDirectory()+CapabilitiesCacheFileName }; std::string CapabilitiesCacheFileName_{MicroServiceDataDirectory() +
CapabilitiesCacheFileName};
inline void LoadPlatforms() { inline void LoadPlatforms() {
try { try {
@@ -109,11 +109,10 @@ namespace OpenWifi {
nlohmann::json cache; nlohmann::json cache;
i >> cache; i >> cache;
for(const auto &[Type,Platform]:cache.items()) { for (const auto &[Type, Platform] : cache.items()) {
Platforms_[Type] = Platform; Platforms_[Type] = Platform;
} }
} catch(...) { } catch (...) {
} }
PlatformsLoaded_ = true; PlatformsLoaded_ = true;
} }
@@ -124,36 +123,35 @@ namespace OpenWifi {
nlohmann::json cache(Platforms_); nlohmann::json cache(Platforms_);
i << cache; i << cache;
} catch (...) { } catch (...) {
} }
} }
inline void LoadCapabilities() { inline void LoadCapabilities() {
try { try {
std::ifstream i(CapabilitiesCacheFileName_, std::ios_base::binary|std::ios_base::in); std::ifstream i(CapabilitiesCacheFileName_,
std::ios_base::binary | std::ios_base::in);
nlohmann::json cache; nlohmann::json cache;
i >> cache; i >> cache;
for(const auto &[Type,Caps]:cache.items()) { for (const auto &[Type, Caps] : cache.items()) {
Capabilities_[Type] = Caps; Capabilities_[Type] = Caps;
} }
} catch(...) { } catch (...) {
} }
CapabilitiesLoaded_ = true; CapabilitiesLoaded_ = true;
} }
inline void SaveCapabilities() { inline void SaveCapabilities() {
try { try {
std::ofstream i(CapabilitiesCacheFileName_, std::ios_base::trunc | std::ios_base::out | std::ios_base::binary ); std::ofstream i(CapabilitiesCacheFileName_,
std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
nlohmann::json cache(Capabilities_); nlohmann::json cache(Capabilities_);
i << cache; i << cache;
} catch (...) { } catch (...) {
} }
} }
}; };
inline auto CapabilitiesCache() { return CapabilitiesCache::instance(); }; inline auto CapabilitiesCache() { return CapabilitiesCache::instance(); };
} } // namespace OpenWifi

View File

@@ -7,17 +7,17 @@
// //
#include <fstream> #include <fstream>
#include "Poco/File.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "Poco/File.h"
#include "CentralConfig.h" #include "CentralConfig.h"
#include "Daemon.h" #include "Daemon.h"
namespace OpenWifi::Config { namespace OpenWifi::Config {
const static std::string BasicConfig { const static std::string BasicConfig{
R"lit( R"lit(
{ {
"interfaces": [ "interfaces": [
{ {
@@ -150,10 +150,11 @@ R"lit(
void Config::SetBasicConfigFile() { void Config::SetBasicConfigFile() {
try { try {
Poco::File DefaultConfigFileName{MicroService::instance().DataDir() + "/default_config.json"}; Poco::File DefaultConfigFileName{MicroService::instance().DataDir() +
"/default_config.json"};
DefaultConfiguration_ = BasicConfig; DefaultConfiguration_ = BasicConfig;
std::ofstream OS(DefaultConfigFileName.path(), std::ios::binary | std::ios::trunc ); std::ofstream OS(DefaultConfigFileName.path(), std::ios::binary | std::ios::trunc);
std::istringstream IS(DefaultConfiguration_); std::istringstream IS(DefaultConfiguration_);
Poco::StreamCopier::copyStream(IS, OS); Poco::StreamCopier::copyStream(IS, OS);
} catch (...) { } catch (...) {
DefaultConfiguration_ = BasicConfig; DefaultConfiguration_ = BasicConfig;
@@ -161,22 +162,23 @@ R"lit(
} }
Config::Config() { Config::Config() {
if(DefaultConfiguration_.empty()) if (DefaultConfiguration_.empty())
Init(); Init();
Config_ = DefaultConfiguration_; Config_ = DefaultConfiguration_;
} }
void Config::Init() { void Config::Init() {
if(DefaultConfiguration_.empty()) { if (DefaultConfiguration_.empty()) {
// open the file // open the file
try { try {
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"}; Poco::File DefaultConfigFileName{MicroService::instance().DataDir() +
"/default_config.json"};
if (!DefaultConfigFileName.exists()) { if (!DefaultConfigFileName.exists()) {
SetBasicConfigFile(); SetBasicConfigFile();
} else { } else {
std::ifstream F(DefaultConfigFileName.path(),std::ios::binary | std::ios::in); std::ifstream F(DefaultConfigFileName.path(), std::ios::binary | std::ios::in);
std::ostringstream C; std::ostringstream C;
Poco::StreamCopier::copyStream(F,C); Poco::StreamCopier::copyStream(F, C);
DefaultConfiguration_ = C.str(); DefaultConfiguration_ = C.str();
} }
} catch (...) { } catch (...) {
@@ -185,101 +187,89 @@ R"lit(
} }
} }
bool Config::SetUUID(uint64_t UUID) { bool Config::SetUUID(uint64_t UUID) {
try { try {
Poco::JSON::Parser Parser; Poco::JSON::Parser Parser;
auto Object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>(); auto Object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
Object->set("uuid", UUID); Object->set("uuid", UUID);
std::ostringstream NewConfig; std::ostringstream NewConfig;
Poco::JSON::Stringifier Stringifier; Poco::JSON::Stringifier Stringifier;
Stringifier.condense(Object, NewConfig); Stringifier.condense(Object, NewConfig);
Config_ = NewConfig.str(); Config_ = NewConfig.str();
return true; return true;
} } catch (const Poco::Exception &E) {
catch(const Poco::Exception &E) std::cout << __func__ << ": new Configuration failed with " << E.displayText()
{ << std::endl;
std::cout << __func__ << ": new Configuration failed with " << E.displayText() << std::endl; }
} return false;
return false; }
}
bool Config::Valid() { bool Config::Valid() {
try { try {
Poco::JSON::Parser Parser; Poco::JSON::Parser Parser;
auto object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>(); auto object = Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
if(object->has("uuid")) if (object->has("uuid"))
return true; return true;
return false;
}
catch (...)
{
return false; return false;
} } catch (...) {
} return false;
}
}
Poco::JSON::Object::Ptr Config::to_json() { Poco::JSON::Object::Ptr Config::to_json() {
Poco::JSON::Parser Parser; Poco::JSON::Parser Parser;
return Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>(); return Parser.parse(Config_).extract<Poco::JSON::Object::Ptr>();
} }
std::string Config::Default() { std::string Config::Default() {
if(DefaultConfiguration_.empty()) if (DefaultConfiguration_.empty())
Init(); Init();
return DefaultConfiguration_; return DefaultConfiguration_;
} }
/* std::string Capabilities::Default() { /* std::string Capabilities::Default() {
return std::string(R"lit({"model":{"id":"linksys,ea8300","name":"Linksys EA8300 (Dallas)"}, return std::string(R"lit({"model":{"id":"linksys,ea8300","name":"Linksys EA8300
"network":{"lan":{"ifname":"eth0","protocol":"static"},"wan":{"ifname":"eth1","protocol":"dhcp"}}, (Dallas)"},
"switch":{"switch0":{"enable":true,"reset":true,"ports":[{"num":0,"device":"eth0","need_tag":false, "network":{"lan":{"ifname":"eth0","protocol":"static"},"wan":{"ifname":"eth1","protocol":"dhcp"}},
"want_untag":true},{"num":1,"role":"lan"},{"num":2,"role":"lan"},{"num":3,"role":"lan"},{"num":4,"role":"lan"}], "switch":{"switch0":{"enable":true,"reset":true,"ports":[{"num":0,"device":"eth0","need_tag":false,
"roles":[{"role":"lan","ports":"1 2 3 4 0","device":"eth0"}]}}, "want_untag":true},{"num":1,"role":"lan"},{"num":2,"role":"lan"},{"num":3,"role":"lan"},{"num":4,"role":"lan"}],
"wifi":{"soc/40000000.pci/pci0000:00/0000:00:00.0/0000:01:00.0":{"band":["5u"],"ht_capa":6639, "roles":[{"role":"lan","ports":"1 2 3 4 0","device":"eth0"}]}},
"vht_capa":865696178,"htmode":["HT20","HT40","VHT20","VHT40","VHT80"],"tx_ant":3,"rx_ant":3, "wifi":{"soc/40000000.pci/pci0000:00/0000:00:00.0/0000:01:00.0":{"band":["5u"],"ht_capa":6639,
"channels":[100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165]}, "vht_capa":865696178,"htmode":["HT20","HT40","VHT20","VHT40","VHT80"],"tx_ant":3,"rx_ant":3,
"platform/soc/a000000.wifi":{"band":["2"],"ht_capa":6639,"vht_capa":865687986, "channels":[100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165]},
"htmode":["HT20","HT40","VHT20","VHT40","VHT80"],"tx_ant":3,"rx_ant":3,"channels":[1,2,3,4,5,6,7,8,9,10,11]}, "platform/soc/a000000.wifi":{"band":["2"],"ht_capa":6639,"vht_capa":865687986,
"platform/soc/a800000.wifi":{"band":["5l"],"ht_capa":6639,"vht_capa":865687986,"htmode":["HT20","HT40","VHT20","VHT40","VHT80"], "htmode":["HT20","HT40","VHT20","VHT40","VHT80"],"tx_ant":3,"rx_ant":3,"channels":[1,2,3,4,5,6,7,8,9,10,11]},
"tx_ant":3,"rx_ant":3,"channels":[36,40,44,48,52,56,60,64]}}})lit"); "platform/soc/a800000.wifi":{"band":["5l"],"ht_capa":6639,"vht_capa":865687986,"htmode":["HT20","HT40","VHT20","VHT40","VHT80"],
} "tx_ant":3,"rx_ant":3,"channels":[36,40,44,48,52,56,60,64]}}})lit");
*/ }
*/
Capabilities::Capabilities(const Poco::JSON::Object::Ptr &Caps) { Capabilities::Capabilities(const Poco::JSON::Object::Ptr &Caps) {
try { try {
if(Caps->has("compatible")) if (Caps->has("compatible"))
Compatible_ = Caps->get("compatible").toString(); Compatible_ = Caps->get("compatible").toString();
if(Caps->has("model")) if (Caps->has("model"))
Model_ = Caps->get("model").toString(); Model_ = Caps->get("model").toString();
if(Caps->has("platform")) if (Caps->has("platform"))
Platform_ = Caps->get("platform").toString(); Platform_ = Caps->get("platform").toString();
std::ostringstream OS; std::ostringstream OS;
Caps->stringify(OS); Caps->stringify(OS);
AsString_ = OS.str(); AsString_ = OS.str();
} } catch (const Poco::Exception &E) {
catch ( const Poco::Exception & E ) Daemon()->logger().log(E);
{ }
Daemon()->logger().log(E);
}
}
const std::string & Capabilities::Compatible() const {
return Compatible_;
} }
const std::string & Capabilities::Model() const { const std::string &Capabilities::Compatible() const { return Compatible_; }
return Model_;
}
const std::string & Capabilities::Platform() const { const std::string &Capabilities::Model() const { return Model_; }
return Platform_;
}
const std::string & Capabilities::AsString() const { const std::string &Capabilities::Platform() const { return Platform_; }
return AsString_;
}
} // namespace const std::string &Capabilities::AsString() const { return AsString_; }
} // namespace OpenWifi::Config

View File

@@ -8,58 +8,55 @@
#pragma once #pragma once
#include <string>
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include <string>
namespace OpenWifi::Config { namespace OpenWifi::Config {
class Config { class Config {
public: public:
explicit Config(const std::string &Config) explicit Config(const std::string &Config) : Config_(Config) {}
:Config_(Config) {
}
Config(); Config();
bool SetUUID(uint64_t UUID); bool SetUUID(uint64_t UUID);
[[nodiscard]] bool Valid(); [[nodiscard]] bool Valid();
[[nodiscard]] std::string get() { return Config_; }; [[nodiscard]] std::string get() { return Config_; };
[[nodiscard]] std::string Default(); [[nodiscard]] std::string Default();
[[nodiscard]] Poco::JSON::Object::Ptr to_json(); [[nodiscard]] Poco::JSON::Object::Ptr to_json();
private: private:
void Init(); void Init();
void SetBasicConfigFile(); void SetBasicConfigFile();
inline static std::string DefaultConfiguration_ = ""; inline static std::string DefaultConfiguration_ = "";
std::string Config_; std::string Config_;
}; };
class Capabilities { class Capabilities {
public: public:
explicit Capabilities(const Poco::JSON::Object::Ptr &Caps); explicit Capabilities(const Poco::JSON::Object::Ptr &Caps);
/* Capabilities() /* Capabilities()
{ {
Capabilities_ = Default(); Capabilities_ = Default();
} }
static std::string Default(); static std::string Default();
[[nodiscard]] const std::string & Get() const { return Capabilities_; }; [[nodiscard]] const std::string & Get() const { return Capabilities_; };
*/ */
[[nodiscard]] const std::string & Compatible() const; [[nodiscard]] const std::string &Compatible() const;
[[nodiscard]] const std::string & Model() const; [[nodiscard]] const std::string &Model() const;
[[nodiscard]] const std::string & Platform() const; [[nodiscard]] const std::string &Platform() const;
[[nodiscard]] const std::string & AsString() const; [[nodiscard]] const std::string &AsString() const;
private: private:
std::string Compatible_; std::string Compatible_;
std::string Model_; std::string Model_;
std::string Platform_; std::string Platform_;
std::string AsString_; std::string AsString_;
void Parse(); void Parse();
}; };
} // namespace
} // namespace OpenWifi::Config

View File

@@ -10,11 +10,11 @@
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "CommandManager.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "CommandManager.h"
#include "StorageService.h" #include "StorageService.h"
#include "framework/ow_constants.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/ow_constants.h"
#include "framework/utils.h" #include "framework/utils.h"
using namespace std::chrono_literals; using namespace std::chrono_literals;
@@ -35,43 +35,50 @@ namespace OpenWifi {
std::string SerialNumberStr = Utils::IntToSerialNumber(Resp->SerialNumber_); std::string SerialNumberStr = Utils::IntToSerialNumber(Resp->SerialNumber_);
if (!Payload->has(uCentralProtocol::ID)) { if (!Payload->has(uCentralProtocol::ID)) {
poco_error(Logger(), fmt::format("({}): Invalid RPC response.", SerialNumberStr)); poco_error(Logger(),
fmt::format("({}): Invalid RPC response.", SerialNumberStr));
} else { } else {
uint64_t ID = Payload->get(uCentralProtocol::ID); uint64_t ID = Payload->get(uCentralProtocol::ID);
poco_debug(Logger(),fmt::format("({}): Processing {} response.", SerialNumberStr, ID)); poco_debug(Logger(), fmt::format("({}): Processing {} response.",
SerialNumberStr, ID));
if (ID > 1) { if (ID > 1) {
std::lock_guard Lock(LocalMutex_); std::lock_guard Lock(LocalMutex_);
auto RPC = OutStandingRequests_.find(ID); auto RPC = OutStandingRequests_.find(ID);
if (RPC == OutStandingRequests_.end()) { if (RPC == OutStandingRequests_.end()) {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
poco_debug(Logger(), poco_debug(Logger(), fmt::format("({}): RPC {} cannot be found.",
fmt::format("({}): RPC {} cannot be found.", SerialNumberStr, ID)); SerialNumberStr, ID));
} else if(RPC->second.SerialNumber != Resp->SerialNumber_) { } else if (RPC->second.SerialNumber != Resp->SerialNumber_) {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
poco_debug(Logger(), poco_debug(
fmt::format("({}): RPC {} serial number mismatch {}!={}.", SerialNumberStr, ID, RPC->second.SerialNumber, Resp->SerialNumber_)); Logger(),
fmt::format("({}): RPC {} serial number mismatch {}!={}.",
SerialNumberStr, ID, RPC->second.SerialNumber,
Resp->SerialNumber_));
} else { } else {
std::shared_ptr<promise_type_t> TmpRpcEntry; std::shared_ptr<promise_type_t> TmpRpcEntry;
std::chrono::duration<double, std::milli> rpc_execution_time = std::chrono::duration<double, std::milli> rpc_execution_time =
std::chrono::high_resolution_clock::now() - std::chrono::high_resolution_clock::now() -
RPC->second.submitted; RPC->second.submitted;
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
poco_debug(Logger(), poco_debug(Logger(),
fmt::format("({}): Received RPC answer {}. Command={}", fmt::format("({}): Received RPC answer {}. Command={}",
SerialNumberStr, ID, APCommands::to_string(RPC->second.Command))); SerialNumberStr, ID,
if(RPC->second.Command==APCommands::Commands::script) { APCommands::to_string(RPC->second.Command)));
if (RPC->second.Command == APCommands::Commands::script) {
CompleteScriptCommand(RPC->second, Payload, rpc_execution_time); CompleteScriptCommand(RPC->second, Payload, rpc_execution_time);
} else if(RPC->second.Command!=APCommands::Commands::telemetry) { } else if (RPC->second.Command != APCommands::Commands::telemetry) {
CompleteTelemetryCommand(RPC->second, Payload, rpc_execution_time); CompleteTelemetryCommand(RPC->second, Payload,
rpc_execution_time);
} else { } else {
StorageService()->CommandCompleted( StorageService()->CommandCompleted(RPC->second.UUID, Payload,
RPC->second.UUID, Payload, rpc_execution_time, true); rpc_execution_time, true);
if (RPC->second.rpc_entry) { if (RPC->second.rpc_entry) {
TmpRpcEntry = RPC->second.rpc_entry; TmpRpcEntry = RPC->second.rpc_entry;
} }
RPC->second.State = 0 ; RPC->second.State = 0;
OutStandingRequests_.erase(ID); OutStandingRequests_.erase(ID);
if(TmpRpcEntry != nullptr) if (TmpRpcEntry != nullptr)
TmpRpcEntry->set_value(Payload); TmpRpcEntry->set_value(Payload);
} }
} }
@@ -81,14 +88,16 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_warning(Logger(),"Exception occurred during run."); poco_warning(Logger(), "Exception occurred during run.");
} }
NextMsg = ResponseQueue_.waitDequeueNotification(); NextMsg = ResponseQueue_.waitDequeueNotification();
} }
poco_information(Logger(),"RPC Command processor stopping."); poco_information(Logger(), "RPC Command processor stopping.");
} }
bool CommandManager::CompleteTelemetryCommand(CommandInfo &Command, [[maybe_unused]] const Poco::JSON::Object::Ptr &Payload, std::chrono::duration<double, std::milli> rpc_execution_time ) { bool CommandManager::CompleteTelemetryCommand(
CommandInfo &Command, [[maybe_unused]] const Poco::JSON::Object::Ptr &Payload,
std::chrono::duration<double, std::milli> rpc_execution_time) {
std::shared_ptr<promise_type_t> TmpRpcEntry; std::shared_ptr<promise_type_t> TmpRpcEntry;
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true); StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
@@ -96,23 +105,25 @@ namespace OpenWifi {
if (Command.rpc_entry) { if (Command.rpc_entry) {
TmpRpcEntry = Command.rpc_entry; TmpRpcEntry = Command.rpc_entry;
} }
Command.State = 0 ; Command.State = 0;
OutStandingRequests_.erase(Command.Id); OutStandingRequests_.erase(Command.Id);
if(TmpRpcEntry != nullptr) if (TmpRpcEntry != nullptr)
TmpRpcEntry->set_value(Payload); TmpRpcEntry->set_value(Payload);
return true; return true;
} }
bool CommandManager::CompleteScriptCommand(CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload, std::chrono::duration<double, std::milli> rpc_execution_time) { bool CommandManager::CompleteScriptCommand(
CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload,
std::chrono::duration<double, std::milli> rpc_execution_time) {
bool Reply = true; bool Reply = true;
std::shared_ptr<promise_type_t> TmpRpcEntry; std::shared_ptr<promise_type_t> TmpRpcEntry;
if (Command.rpc_entry) { if (Command.rpc_entry) {
TmpRpcEntry = Command.rpc_entry; TmpRpcEntry = Command.rpc_entry;
} }
// std::cout << __LINE__ << " State=" << Command.State << std::endl; // std::cout << __LINE__ << " State=" << Command.State << std::endl;
if(Command.State==2) { if (Command.State == 2) {
// look at the payload to see if we should continue or not... // look at the payload to see if we should continue or not...
if (Payload->has("result")) { if (Payload->has("result")) {
auto Result = Payload->getObject("result"); auto Result = Payload->getObject("result");
@@ -120,45 +131,47 @@ namespace OpenWifi {
auto Status = Result->getObject("status"); auto Status = Result->getObject("status");
std::uint64_t Error = Status->get("error"); std::uint64_t Error = Status->get("error");
if(Error==0) { if (Error == 0) {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true); StorageService()->CommandCompleted(Command.UUID, Payload,
Command.State = 1 ; rpc_execution_time, true);
Command.State = 1;
} else { } else {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true); StorageService()->CommandCompleted(Command.UUID, Payload,
rpc_execution_time, true);
std::string ErrorTxt = Status->get("result"); std::string ErrorTxt = Status->get("result");
StorageService()->CancelWaitFile(Command.UUID, ErrorTxt); StorageService()->CancelWaitFile(Command.UUID, ErrorTxt);
Command.State = 0 ; Command.State = 0;
} }
} else { } else {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
} }
} else { } else {
// std::cout << __LINE__ << std::endl; // std::cout << __LINE__ << std::endl;
Command.State=0; Command.State = 0;
} }
} else if (Command.State==1) { } else if (Command.State == 1) {
// std::cout << "Completing script 2 phase commit." << std::endl; // std::cout << "Completing script 2 phase commit." << std::endl;
StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true); StorageService()->CommandCompleted(Command.UUID, Payload, rpc_execution_time, true);
if(Command.Deferred) { if (Command.Deferred) {
Reply = false; Reply = false;
} }
Command.State=0; Command.State = 0;
} }
if(Command.State==0) { if (Command.State == 0) {
// std::cout << __LINE__ << " State=" << Command.State << std::endl; // std::cout << __LINE__ << " State=" << Command.State << std::endl;
OutStandingRequests_.erase(Command.Id); OutStandingRequests_.erase(Command.Id);
} }
if(Reply && TmpRpcEntry != nullptr) if (Reply && TmpRpcEntry != nullptr)
TmpRpcEntry->set_value(Payload); TmpRpcEntry->set_value(Payload);
return true; return true;
} }
int CommandManager::Start() { int CommandManager::Start() {
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
commandTimeOut_ = MicroServiceConfigGetInt("command.timeout", 4 * 60 * 60); commandTimeOut_ = MicroServiceConfigGetInt("command.timeout", 4 * 60 * 60);
commandRetry_ = MicroServiceConfigGetInt("command.retry", 120); commandRetry_ = MicroServiceConfigGetInt("command.retry", 120);
@@ -167,76 +180,81 @@ namespace OpenWifi {
ManagerThread.start(*this); ManagerThread.start(*this);
JanitorCallback_ = std::make_unique<Poco::TimerCallback<CommandManager>>(*this,&CommandManager::onJanitorTimer); JanitorCallback_ = std::make_unique<Poco::TimerCallback<CommandManager>>(
JanitorTimer_.setStartInterval( 10000 ); *this, &CommandManager::onJanitorTimer);
JanitorTimer_.setPeriodicInterval(janitorInterval_* 1000); // 1 hours JanitorTimer_.setStartInterval(10000);
JanitorTimer_.setPeriodicInterval(janitorInterval_ * 1000); // 1 hours
JanitorTimer_.start(*JanitorCallback_, MicroServiceTimerPool()); JanitorTimer_.start(*JanitorCallback_, MicroServiceTimerPool());
CommandRunnerCallback_ = std::make_unique<Poco::TimerCallback<CommandManager>>(*this,&CommandManager::onCommandRunnerTimer); CommandRunnerCallback_ = std::make_unique<Poco::TimerCallback<CommandManager>>(
CommandRunnerTimer_.setStartInterval( 10000 ); *this, &CommandManager::onCommandRunnerTimer);
CommandRunnerTimer_.setStartInterval(10000);
CommandRunnerTimer_.setPeriodicInterval(queueInterval_ * 1000); // 1 hours CommandRunnerTimer_.setPeriodicInterval(queueInterval_ * 1000); // 1 hours
CommandRunnerTimer_.start(*CommandRunnerCallback_, MicroServiceTimerPool()); CommandRunnerTimer_.start(*CommandRunnerCallback_, MicroServiceTimerPool());
return 0; return 0;
} }
void CommandManager::Stop() { void CommandManager::Stop() {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
Running_ = false; Running_ = false;
JanitorTimer_.stop(); JanitorTimer_.stop();
CommandRunnerTimer_.stop(); CommandRunnerTimer_.stop();
ResponseQueue_.wakeUpAll(); ResponseQueue_.wakeUpAll();
ManagerThread.wakeUp(); ManagerThread.wakeUp();
ManagerThread.join(); ManagerThread.join();
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
void CommandManager::WakeUp() { void CommandManager::WakeUp() {
poco_notice(Logger(),"Waking up..."); poco_notice(Logger(), "Waking up...");
ManagerThread.wakeUp(); ManagerThread.wakeUp();
} }
void CommandManager::onJanitorTimer([[maybe_unused]] Poco::Timer & timer) { void CommandManager::onJanitorTimer([[maybe_unused]] Poco::Timer &timer) {
std::lock_guard Lock(LocalMutex_); std::lock_guard Lock(LocalMutex_);
Utils::SetThreadName("cmd:janitor"); Utils::SetThreadName("cmd:janitor");
Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-JANITOR"); Poco::Logger &MyLogger = Poco::Logger::get("CMD-MGR-JANITOR");
std::string TimeOutError("No response."); std::string TimeOutError("No response.");
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
for(auto request=OutStandingRequests_.begin();request!=OutStandingRequests_.end();) { for (auto request = OutStandingRequests_.begin(); request != OutStandingRequests_.end();) {
std::chrono::duration<double, std::milli> delta = now - request->second.submitted; std::chrono::duration<double, std::milli> delta = now - request->second.submitted;
if(delta > 10min) { if (delta > 10min) {
// std::cout << __LINE__ << " -->> " << request->second.Id << std::endl; // std::cout << __LINE__ << " -->> " << request->second.Id <<
MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", //std::endl;
request->second.UUID, MyLogger.debug(fmt::format("{}: Command={} for {} Timed out.", request->second.UUID,
APCommands::to_string(request->second.Command), APCommands::to_string(request->second.Command),
Utils::IntToSerialNumber(request->second.SerialNumber))); Utils::IntToSerialNumber(request->second.SerialNumber)));
if( (request->second.Command == APCommands::Commands::script && request->second.Deferred) || if ((request->second.Command == APCommands::Commands::script &&
request->second.Deferred) ||
(request->second.Command == APCommands::Commands::trace)) { (request->second.Command == APCommands::Commands::trace)) {
StorageService()->CancelWaitFile(request->second.UUID, TimeOutError); StorageService()->CancelWaitFile(request->second.UUID, TimeOutError);
} }
StorageService()->SetCommandTimedOut(request->second.UUID); StorageService()->SetCommandTimedOut(request->second.UUID);
request = OutStandingRequests_.erase(request); request = OutStandingRequests_.erase(request);
} else { } else {
// std::cout << __LINE__ << " -->> " << request->second.Id << std::endl; // std::cout << __LINE__ << " -->> " << request->second.Id <<
//std::endl;
++request; ++request;
} }
} }
poco_information(MyLogger, poco_information(MyLogger,
fmt::format("Outstanding-requests {}", OutStandingRequests_.size())); fmt::format("Outstanding-requests {}", OutStandingRequests_.size()));
} }
bool CommandManager::IsCommandRunning(const std::string &C) { bool CommandManager::IsCommandRunning(const std::string &C) {
std::lock_guard Lock(LocalMutex_); std::lock_guard Lock(LocalMutex_);
return std::any_of(OutStandingRequests_.begin(),OutStandingRequests_.end(), return std::any_of(
[C](const std::pair<std::uint64_t , CommandInfo> &r) { return r.second.UUID==C;}); OutStandingRequests_.begin(), OutStandingRequests_.end(),
[C](const std::pair<std::uint64_t, CommandInfo> &r) { return r.second.UUID == C; });
} }
void CommandManager::onCommandRunnerTimer([[maybe_unused]] Poco::Timer &timer) { void CommandManager::onCommandRunnerTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("cmd:schdlr"); Utils::SetThreadName("cmd:schdlr");
Poco::Logger &MyLogger = Poco::Logger::get("CMD-MGR-SCHEDULER"); Poco::Logger &MyLogger = Poco::Logger::get("CMD-MGR-SCHEDULER");
poco_trace(MyLogger,"Scheduler starting."); poco_trace(MyLogger, "Scheduler starting.");
try { try {
@@ -245,28 +263,29 @@ namespace OpenWifi {
std::vector<GWObjects::CommandDetails> Commands; std::vector<GWObjects::CommandDetails> Commands;
if (StorageService()->GetReadyToExecuteCommands(0, 200, Commands)) { if (StorageService()->GetReadyToExecuteCommands(0, 200, Commands)) {
poco_trace(MyLogger,fmt::format("Scheduler about to process {} commands.", Commands.size())); poco_trace(MyLogger,
fmt::format("Scheduler about to process {} commands.", Commands.size()));
for (auto &Cmd : Commands) { for (auto &Cmd : Commands) {
if (!Running_) { if (!Running_) {
poco_warning(MyLogger,"Scheduler quitting because service is stopping."); poco_warning(MyLogger, "Scheduler quitting because service is stopping.");
break; break;
} }
poco_trace( poco_trace(MyLogger,
MyLogger, fmt::format("{}: Serial={} Command={} Starting processing.", fmt::format("{}: Serial={} Command={} Starting processing.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
try { try {
// Skip an already running command // Skip an already running command
if(IsCommandRunning(Cmd.UUID)) { if (IsCommandRunning(Cmd.UUID)) {
continue; continue;
} }
auto now = Utils::Now(); auto now = Utils::Now();
// 2 hour timeout for commands // 2 hour timeout for commands
if ((now - Cmd.Submitted) > commandTimeOut_) { if ((now - Cmd.Submitted) > commandTimeOut_) {
poco_information( poco_information(MyLogger,
MyLogger, fmt::format("{}: Serial={} Command={} has expired.", fmt::format("{}: Serial={} Command={} has expired.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
StorageService()->SetCommandTimedOut(Cmd.UUID); StorageService()->SetCommandTimedOut(Cmd.UUID);
continue; continue;
} }
@@ -275,53 +294,57 @@ namespace OpenWifi {
if (!AP_WS_Server()->Connected(SerialNumberInt)) { if (!AP_WS_Server()->Connected(SerialNumberInt)) {
poco_trace( poco_trace(
MyLogger, MyLogger,
fmt::format( fmt::format("{}: Serial={} Command={} Device is not connected.",
"{}: Serial={} Command={} Device is not connected.", Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
StorageService()->SetCommandLastTry(Cmd.UUID); StorageService()->SetCommandLastTry(Cmd.UUID);
continue; continue;
} }
std::string ExecutingUUID; std::string ExecutingUUID;
APCommands::Commands ExecutingCommand=APCommands::Commands::unknown; APCommands::Commands ExecutingCommand = APCommands::Commands::unknown;
if (CommandRunningForDevice(SerialNumberInt, if (CommandRunningForDevice(SerialNumberInt, ExecutingUUID,
ExecutingUUID, ExecutingCommand)) { ExecutingCommand)) {
poco_trace( poco_trace(
MyLogger, MyLogger,
fmt::format( fmt::format("{}: Serial={} Command={} Device is already busy "
"{}: Serial={} Command={} Device is already busy with command {} (Command={})." "with command {} (Command={}).",
, Cmd.UUID, Cmd.SerialNumber, Cmd.Command, ExecutingUUID, APCommands::to_string(ExecutingCommand))); Cmd.UUID, Cmd.SerialNumber, Cmd.Command, ExecutingUUID,
APCommands::to_string(ExecutingCommand)));
continue; continue;
} }
Poco::JSON::Parser P; Poco::JSON::Parser P;
bool Sent; bool Sent;
poco_information(MyLogger, fmt::format("{}: Serial={} Command={} Preparing execution.", poco_information(
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); MyLogger, fmt::format("{}: Serial={} Command={} Preparing execution.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>(); auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
auto Result = PostCommandDisk(Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()), Cmd.SerialNumber, Cmd.Command, auto Result = PostCommandDisk(
*Params, Cmd.UUID, Sent); Next_RPC_ID(), APCommands::to_apcommand(Cmd.Command.c_str()),
Cmd.SerialNumber, Cmd.Command, *Params, Cmd.UUID, Sent);
if (Sent) { if (Sent) {
StorageService()->SetCommandExecuted(Cmd.UUID); StorageService()->SetCommandExecuted(Cmd.UUID);
poco_debug(MyLogger, poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Sent.", fmt::format("{}: Serial={} Command={} Sent.", Cmd.UUID,
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); Cmd.SerialNumber, Cmd.Command));
} else { } else {
poco_debug(MyLogger, poco_debug(MyLogger,
fmt::format("{}: Serial={} Command={} Re-queued command.", fmt::format("{}: Serial={} Command={} Re-queued command.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
StorageService()->SetCommandLastTry(Cmd.UUID); StorageService()->SetCommandLastTry(Cmd.UUID);
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_debug(MyLogger, poco_debug(
fmt::format("{}: Serial={} Command={} Failed. Command marked as completed.", MyLogger,
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); fmt::format(
"{}: Serial={} Command={} Failed. Command marked as completed.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
MyLogger.log(E); MyLogger.log(E);
StorageService()->SetCommandExecuted(Cmd.UUID); StorageService()->SetCommandExecuted(Cmd.UUID);
} catch (...) { } catch (...) {
poco_debug(MyLogger, poco_debug(MyLogger, fmt::format("{}: Serial={} Command={} Hard failure. "
fmt::format("{}: Serial={} Command={} Hard failure. Command marked as completed.", "Command marked as completed.",
Cmd.UUID, Cmd.SerialNumber, Cmd.Command)); Cmd.UUID, Cmd.SerialNumber, Cmd.Command));
StorageService()->SetCommandExecuted(Cmd.UUID); StorageService()->SetCommandExecuted(Cmd.UUID);
} }
} }
@@ -329,36 +352,28 @@ namespace OpenWifi {
} catch (Poco::Exception &E) { } catch (Poco::Exception &E) {
MyLogger.log(E); MyLogger.log(E);
} catch (...) { } catch (...) {
poco_warning(MyLogger,"Exception during command processing."); poco_warning(MyLogger, "Exception during command processing.");
} }
poco_trace(MyLogger,"Scheduler done."); poco_trace(MyLogger, "Scheduler done.");
} }
std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand( std::shared_ptr<CommandManager::promise_type_t> CommandManager::PostCommand(
uint64_t RPC_ID, uint64_t RPC_ID, APCommands::Commands Command, const std::string &SerialNumber,
APCommands::Commands Command, const std::string &CommandStr, const Poco::JSON::Object &Params, const std::string &UUID,
const std::string &SerialNumber, bool oneway_rpc, [[maybe_unused]] bool disk_only, bool &Sent, bool rpc, bool Deferred) {
const std::string &CommandStr,
const Poco::JSON::Object &Params,
const std::string &UUID,
bool oneway_rpc,
[[maybe_unused]] bool disk_only,
bool & Sent,
bool rpc,
bool Deferred) {
auto SerialNumberInt = Utils::SerialNumberToInt(SerialNumber); auto SerialNumberInt = Utils::SerialNumberToInt(SerialNumber);
Sent=false; Sent = false;
std::stringstream ToSend; std::stringstream ToSend;
CommandInfo CInfo; CommandInfo CInfo;
CInfo.Id = oneway_rpc ? 1 : RPC_ID; CInfo.Id = oneway_rpc ? 1 : RPC_ID;
CInfo.SerialNumber = SerialNumberInt; CInfo.SerialNumber = SerialNumberInt;
CInfo.Command = Command; CInfo.Command = Command;
CInfo.Deferred = Deferred; CInfo.Deferred = Deferred;
CInfo.UUID = UUID; CInfo.UUID = UUID;
if(Command == APCommands::Commands::script && Deferred) { if (Command == APCommands::Commands::script && Deferred) {
CInfo.State = 2; CInfo.State = 2;
} else { } else {
CInfo.State = 1; CInfo.State = 1;
@@ -372,16 +387,17 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend); Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
CInfo.rpc_entry = rpc ? std::make_shared<CommandManager::promise_type_t>() : nullptr; CInfo.rpc_entry = rpc ? std::make_shared<CommandManager::promise_type_t>() : nullptr;
poco_debug(Logger(), fmt::format("{}: Sending command {} to {}. ID: {}", UUID, CommandStr, SerialNumber, RPC_ID)); poco_debug(Logger(), fmt::format("{}: Sending command {} to {}. ID: {}", UUID, CommandStr,
// Do not change the order. It is possible that an RPC completes before it is entered in the map. So we insert it SerialNumber, RPC_ID));
// first, even if we may need to remove it later upon failure. // Do not change the order. It is possible that an RPC completes before it is entered in
if(!oneway_rpc) { //the map. So we insert it first, even if we may need to remove it later upon failure.
if (!oneway_rpc) {
std::lock_guard M(Mutex_); std::lock_guard M(Mutex_);
OutStandingRequests_[RPC_ID] = CInfo; OutStandingRequests_[RPC_ID] = CInfo;
} }
if(AP_WS_Server()->SendFrame(SerialNumber, ToSend.str())) { if (AP_WS_Server()->SendFrame(SerialNumber, ToSend.str())) {
poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPC_ID)); poco_debug(Logger(), fmt::format("{}: Sent command. ID: {}", UUID, RPC_ID));
Sent=true; Sent = true;
return CInfo.rpc_entry; return CInfo.rpc_entry;
} else if (!oneway_rpc) { } else if (!oneway_rpc) {
std::lock_guard M(Mutex_); std::lock_guard M(Mutex_);
@@ -391,4 +407,4 @@ namespace OpenWifi {
poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPC_ID)); poco_warning(Logger(), fmt::format("{}: Failed to send command. ID: {}", UUID, RPC_ID));
return nullptr; return nullptr;
} }
} // namespace } // namespace OpenWifi

View File

@@ -9,242 +9,190 @@
#pragma once #pragma once
#include <chrono> #include <chrono>
#include <functional>
#include <future> #include <future>
#include <map> #include <map>
#include <utility>
#include <functional>
#include <shared_mutex> #include <shared_mutex>
#include <utility>
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Timer.h"
#include "Poco/Notification.h" #include "Poco/Notification.h"
#include "Poco/NotificationQueue.h" #include "Poco/NotificationQueue.h"
#include "Poco/Timer.h"
#include "framework/SubSystemServer.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "framework/SubSystemServer.h"
#include "RESTObjects/RESTAPI_GWobjects.h" #include "RESTObjects/RESTAPI_GWobjects.h"
namespace OpenWifi { namespace OpenWifi {
class RPCResponseNotification: public Poco::Notification { class RPCResponseNotification : public Poco::Notification {
public: public:
RPCResponseNotification(std::uint64_t ser, RPCResponseNotification(std::uint64_t ser, Poco::JSON::Object::Ptr pl)
Poco::JSON::Object::Ptr pl) : : SerialNumber_(ser), Payload_(std::move(pl)) {}
SerialNumber_(ser), std::uint64_t SerialNumber_;
Payload_(std::move(pl)) Poco::JSON::Object::Ptr Payload_;
{
}
std::uint64_t SerialNumber_;
Poco::JSON::Object::Ptr Payload_;
}; };
class CommandManager : public SubSystemServer, Poco::Runnable { class CommandManager : public SubSystemServer, Poco::Runnable {
public: public:
using objtype_t = Poco::JSON::Object::Ptr; using objtype_t = Poco::JSON::Object::Ptr;
using promise_type_t = std::promise<objtype_t>; using promise_type_t = std::promise<objtype_t>;
struct CommandInfo { struct CommandInfo {
std::uint64_t Id=0; std::uint64_t Id = 0;
std::uint64_t SerialNumber=0; std::uint64_t SerialNumber = 0;
APCommands::Commands Command; APCommands::Commands Command;
std::string UUID; std::string UUID;
std::uint64_t State=1; std::uint64_t State = 1;
std::chrono::time_point<std::chrono::high_resolution_clock> submitted = std::chrono::high_resolution_clock::now(); std::chrono::time_point<std::chrono::high_resolution_clock> submitted =
std::shared_ptr<promise_type_t> rpc_entry; std::chrono::high_resolution_clock::now();
bool Deferred=false; std::shared_ptr<promise_type_t> rpc_entry;
}; bool Deferred = false;
};
struct RPCResponse { struct RPCResponse {
std::uint64_t serialNumber; std::uint64_t serialNumber;
Poco::JSON::Object::Ptr payload; Poco::JSON::Object::Ptr payload;
explicit RPCResponse(std::uint64_t ser, Poco::JSON::Object::Ptr pl) explicit RPCResponse(std::uint64_t ser, Poco::JSON::Object::Ptr pl)
: : serialNumber(ser), payload(std::move(pl)) {}
serialNumber(ser), };
payload(std::move(pl)) {
}
};
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void WakeUp(); void WakeUp();
inline void PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj) { inline void PostCommandResult(const std::string &SerialNumber,
ResponseQueue_.enqueueNotification(new RPCResponseNotification(Utils::SerialNumberToInt(SerialNumber),std::move(Obj))); Poco::JSON::Object::Ptr Obj) {
} ResponseQueue_.enqueueNotification(new RPCResponseNotification(
Utils::SerialNumberToInt(SerialNumber), std::move(Obj)));
}
std::shared_ptr<promise_type_t> PostCommandOneWayDisk(uint64_t RPC_ID, std::shared_ptr<promise_type_t> PostCommandOneWayDisk(uint64_t RPC_ID,
APCommands::Commands Command, APCommands::Commands Command,
const std::string &SerialNumber, const std::string &SerialNumber,
const std::string &Method, const std::string &Method,
const Poco::JSON::Object &Params, const Poco::JSON::Object &Params,
const std::string &UUID, const std::string &UUID, bool &Sent) {
bool & Sent) { return PostCommand(RPC_ID, Command, SerialNumber, Method, Params, UUID, true, true,
return PostCommand(RPC_ID, Sent, false);
Command, }
SerialNumber,
Method,
Params,
UUID,
true, true, Sent , false);
}
std::shared_ptr<promise_type_t> PostCommandDisk( std::shared_ptr<promise_type_t>
uint64_t RPC_ID, PostCommandDisk(uint64_t RPC_ID, APCommands::Commands Command,
APCommands::Commands Command, const std::string &SerialNumber, const std::string &Method,
const std::string &SerialNumber, const Poco::JSON::Object &Params, const std::string &UUID, bool &Sent) {
const std::string &Method, return PostCommand(RPC_ID, Command, SerialNumber, Method, Params, UUID, false, true,
const Poco::JSON::Object &Params, Sent, false);
const std::string &UUID, }
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
Method,
Params,
UUID,
false, true, Sent,
false );
}
std::shared_ptr<promise_type_t> PostCommand( std::shared_ptr<promise_type_t>
uint64_t RPC_ID, PostCommand(uint64_t RPC_ID, APCommands::Commands Command, const std::string &SerialNumber,
APCommands::Commands Command, const std::string &Method, const Poco::JSON::Object &Params,
const std::string &SerialNumber, const std::string &UUID, bool &Sent, bool rpc, bool Deferred) {
const std::string &Method, return PostCommand(RPC_ID, Command, SerialNumber, Method, Params, UUID, false, false,
const Poco::JSON::Object &Params, Sent, rpc, Deferred);
const std::string &UUID, }
bool & Sent,
bool rpc,
bool Deferred) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
Method,
Params,
UUID,
false,
false, Sent,
rpc,
Deferred);
}
std::shared_ptr<promise_type_t> PostCommandOneWay( std::shared_ptr<promise_type_t>
uint64_t RPC_ID, PostCommandOneWay(uint64_t RPC_ID, APCommands::Commands Command,
APCommands::Commands Command, const std::string &SerialNumber, const std::string &Method,
const std::string &SerialNumber, const Poco::JSON::Object &Params, const std::string &UUID, bool &Sent) {
const std::string &Method, return PostCommand(RPC_ID, Command, SerialNumber, Method, Params, UUID, true, false,
const Poco::JSON::Object &Params, Sent, false);
const std::string &UUID, }
bool & Sent) {
return PostCommand(RPC_ID,
Command,
SerialNumber,
Method,
Params,
UUID,
true,
false, Sent,
false);
}
bool IsCommandRunning(const std::string &C); bool IsCommandRunning(const std::string &C);
void run() override; void run() override;
static auto instance() { static auto instance() {
static auto instance_ = new CommandManager; static auto instance_ = new CommandManager;
return instance_; return instance_;
} }
inline bool Running() const { return Running_; } inline bool Running() const { return Running_; }
void onJanitorTimer(Poco::Timer & timer); void onJanitorTimer(Poco::Timer &timer);
void onCommandRunnerTimer(Poco::Timer & timer); void onCommandRunnerTimer(Poco::Timer &timer);
inline uint64_t Next_RPC_ID() { return ++Id_; } inline uint64_t Next_RPC_ID() { return ++Id_; }
void RemovePendingCommand(std::uint64_t Id) { void RemovePendingCommand(std::uint64_t Id) {
std::unique_lock Lock(LocalMutex_); std::unique_lock Lock(LocalMutex_);
OutStandingRequests_.erase(Id); OutStandingRequests_.erase(Id);
} }
inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string & uuid, APCommands::Commands &command) { inline bool CommandRunningForDevice(std::uint64_t SerialNumber, std::string &uuid,
std::lock_guard Lock(LocalMutex_); APCommands::Commands &command) {
std::lock_guard Lock(LocalMutex_);
for(const auto &[Request,Command]:OutStandingRequests_) { for (const auto &[Request, Command] : OutStandingRequests_) {
if(Command.SerialNumber==SerialNumber) { if (Command.SerialNumber == SerialNumber) {
uuid = Command.UUID; uuid = Command.UUID;
command = Command.Command; command = Command.Command;
return true; return true;
}
}
return false;
}
inline void ClearQueue(std::uint64_t SerialNumber) {
std::lock_guard Lock(LocalMutex_);
for(auto Request = OutStandingRequests_.begin(); Request != OutStandingRequests_.end() ; ) {
if(Request->second.SerialNumber==SerialNumber)
Request = OutStandingRequests_.erase(Request);
else
++Request;
} }
} }
return false;
}
inline void RemoveCommand(const std::string &UUID) { inline void ClearQueue(std::uint64_t SerialNumber) {
std::lock_guard Lock(LocalMutex_); std::lock_guard Lock(LocalMutex_);
for(const auto &[Id,Cmd]:OutStandingRequests_) { for (auto Request = OutStandingRequests_.begin();
if(Cmd.UUID==UUID) { Request != OutStandingRequests_.end();) {
OutStandingRequests_.erase(Id); if (Request->second.SerialNumber == SerialNumber)
return; Request = OutStandingRequests_.erase(Request);
} else
++Request;
}
}
inline void RemoveCommand(const std::string &UUID) {
std::lock_guard Lock(LocalMutex_);
for (const auto &[Id, Cmd] : OutStandingRequests_) {
if (Cmd.UUID == UUID) {
OutStandingRequests_.erase(Id);
return;
} }
} }
}
inline auto CommandTimeout() const { return commandTimeOut_; } inline auto CommandTimeout() const { return commandTimeOut_; }
inline auto CommandRetry() const { return commandRetry_; } inline auto CommandRetry() const { return commandRetry_; }
private: private:
mutable std::recursive_mutex LocalMutex_; mutable std::recursive_mutex LocalMutex_;
std::atomic_bool Running_ = false; std::atomic_bool Running_ = false;
Poco::Thread ManagerThread; Poco::Thread ManagerThread;
std::atomic_uint64_t Id_=3; // do not start @1. We ignore ID=1 & 0 is illegal.. std::atomic_uint64_t Id_ = 3; // do not start @1. We ignore ID=1 & 0 is illegal..
std::map<std::uint64_t , CommandInfo> OutStandingRequests_; std::map<std::uint64_t, CommandInfo> OutStandingRequests_;
Poco::Timer JanitorTimer_; Poco::Timer JanitorTimer_;
std::unique_ptr<Poco::TimerCallback<CommandManager>> JanitorCallback_; std::unique_ptr<Poco::TimerCallback<CommandManager>> JanitorCallback_;
Poco::Timer CommandRunnerTimer_; Poco::Timer CommandRunnerTimer_;
std::unique_ptr<Poco::TimerCallback<CommandManager>> CommandRunnerCallback_; std::unique_ptr<Poco::TimerCallback<CommandManager>> CommandRunnerCallback_;
Poco::NotificationQueue ResponseQueue_; Poco::NotificationQueue ResponseQueue_;
std::uint64_t commandTimeOut_=0; std::uint64_t commandTimeOut_ = 0;
std::uint64_t commandRetry_=0; std::uint64_t commandRetry_ = 0;
std::uint64_t janitorInterval_=0; std::uint64_t janitorInterval_ = 0;
std::uint64_t queueInterval_=0; std::uint64_t queueInterval_ = 0;
std::shared_ptr<promise_type_t> PostCommand( std::shared_ptr<promise_type_t>
uint64_t RPCID, PostCommand(uint64_t RPCID, APCommands::Commands Command, const std::string &SerialNumber,
APCommands::Commands Command, const std::string &Method, const Poco::JSON::Object &Params,
const std::string &SerialNumber, const std::string &UUID, bool oneway_rpc, bool disk_only, bool &Sent,
const std::string &Method, bool rpc_call, bool Deferred = false);
const Poco::JSON::Object &Params,
const std::string &UUID,
bool oneway_rpc,
bool disk_only,
bool & Sent,
bool rpc_call,
bool Deferred=false);
bool CompleteScriptCommand(CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload, std::chrono::duration<double, std::milli> rpc_execution_time); bool CompleteScriptCommand(CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload,
bool CompleteTelemetryCommand(CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload, std::chrono::duration<double, std::milli> rpc_execution_time); std::chrono::duration<double, std::milli> rpc_execution_time);
bool CompleteTelemetryCommand(CommandInfo &Command, const Poco::JSON::Object::Ptr &Payload,
std::chrono::duration<double, std::milli> rpc_execution_time);
CommandManager() noexcept: CommandManager() noexcept
SubSystemServer("CommandManager", "CMD-MGR", "command.manager") { : SubSystemServer("CommandManager", "CMD-MGR", "command.manager") {}
}
}; };
inline auto CommandManager() { return CommandManager::instance(); } inline auto CommandManager() { return CommandManager::instance(); }
} // namespace } // namespace OpenWifi

View File

@@ -5,14 +5,13 @@
#pragma once #pragma once
#include <map> #include <map>
#include <string>
#include <mutex> #include <mutex>
#include <string>
namespace OpenWifi { namespace OpenWifi {
class ConfigurationCache { class ConfigurationCache {
public: public:
static ConfigurationCache &instance() {
static ConfigurationCache & instance() {
static ConfigurationCache instance; static ConfigurationCache instance;
return instance; return instance;
} }
@@ -20,30 +19,30 @@ namespace OpenWifi {
inline uint64_t CurrentConfig(uint64_t SerialNumber) { inline uint64_t CurrentConfig(uint64_t SerialNumber) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
const auto Hint = Cache_.find(SerialNumber); const auto Hint = Cache_.find(SerialNumber);
if(Hint==end(Cache_)) if (Hint == end(Cache_))
return 0; return 0;
return Hint->second; return Hint->second;
} }
inline void Add(uint64_t SerialNumber, uint64_t Id) { inline void Add(uint64_t SerialNumber, uint64_t Id) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Cache_[SerialNumber]=Id; Cache_[SerialNumber] = Id;
} }
private: private:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
std::map<uint64_t,uint64_t> Cache_; std::map<uint64_t, uint64_t> Cache_;
}; };
inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) { inline uint64_t GetCurrentConfigurationID(uint64_t SerialNumber) {
return ConfigurationCache::instance().CurrentConfig(SerialNumber); return ConfigurationCache::instance().CurrentConfig(SerialNumber);
} }
inline void SetCurrentConfigurationID(const std::string & SerialNumber, uint64_t ID) { inline void SetCurrentConfigurationID(const std::string &SerialNumber, uint64_t ID) {
return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID); return ConfigurationCache::instance().Add(Utils::SerialNumberToInt(SerialNumber), ID);
} }
inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) { inline void SetCurrentConfigurationID(uint64_t SerialNumber, uint64_t ID) {
return ConfigurationCache::instance().Add(SerialNumber, ID); return ConfigurationCache::instance().Add(SerialNumber, ID);
} }
} } // namespace OpenWifi

View File

@@ -6,11 +6,10 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Environment.h" #include "Poco/Environment.h"
#include "Poco/Net/SSLManager.h" #include "Poco/Net/SSLManager.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "CommandManager.h" #include "CommandManager.h"
@@ -19,107 +18,90 @@
#include "FindCountry.h" #include "FindCountry.h"
#include "OUIServer.h" #include "OUIServer.h"
#include "RADIUS_proxy_server.h" #include "RADIUS_proxy_server.h"
#include "ScriptManager.h"
#include "SerialNumberCache.h" #include "SerialNumberCache.h"
#include "SignatureMgr.h"
#include "StorageArchiver.h" #include "StorageArchiver.h"
#include "StorageService.h" #include "StorageService.h"
#include "TelemetryStream.h" #include "TelemetryStream.h"
#include "UI_GW_WebSocketNotifications.h"
#include "VenueBroadcaster.h" #include "VenueBroadcaster.h"
#include "framework/ConfigurationValidator.h" #include "framework/ConfigurationValidator.h"
#include "rttys/RTTYS_server.h"
#include "framework/UI_WebSocketClientServer.h" #include "framework/UI_WebSocketClientServer.h"
#include "UI_GW_WebSocketNotifications.h" #include "rttys/RTTYS_server.h"
#include "ScriptManager.h"
#include "SignatureMgr.h"
namespace OpenWifi { namespace OpenWifi {
class Daemon *Daemon::instance() { class Daemon *Daemon::instance() {
static Daemon instance(vDAEMON_PROPERTIES_FILENAME, static Daemon instance(
vDAEMON_ROOT_ENV_VAR, vDAEMON_PROPERTIES_FILENAME, vDAEMON_ROOT_ENV_VAR, vDAEMON_CONFIG_ENV_VAR,
vDAEMON_CONFIG_ENV_VAR, vDAEMON_APP_NAME, vDAEMON_BUS_TIMER,
vDAEMON_APP_NAME, SubSystemVec{StorageService(), SerialNumberCache(), ConfigurationValidator(),
vDAEMON_BUS_TIMER, UI_WebSocketClientServer(), OUIServer(), FindCountryFromIP(),
SubSystemVec{ CommandManager(), FileUploader(), StorageArchiver(), TelemetryStream(),
StorageService(), RTTYS_server(), RADIUS_proxy_server(), VenueBroadcaster(), ScriptManager(),
SerialNumberCache(), SignatureManager(), AP_WS_Server()});
ConfigurationValidator(), return &instance;
UI_WebSocketClientServer(),
OUIServer(),
FindCountryFromIP(),
CommandManager(),
FileUploader(),
StorageArchiver(),
TelemetryStream(),
RTTYS_server(),
RADIUS_proxy_server(),
VenueBroadcaster(),
ScriptManager(),
SignatureManager(),
AP_WS_Server()
});
return &instance;
} }
static const std::vector<std::pair<std::string,std::string>> DefaultDeviceTypes{ static const std::vector<std::pair<std::string, std::string>> DefaultDeviceTypes{
{"cig_wf160d","AP"}, {"cig_wf160d", "AP"},
{"cig_wf188","AP"}, {"cig_wf188", "AP"},
{"cig_wf188n","AP"}, {"cig_wf188n", "AP"},
{"cig_wf194c","AP"}, {"cig_wf194c", "AP"},
{"cig_wf194c4","AP"}, {"cig_wf194c4", "AP"},
{"edgecore_eap101","AP"}, {"edgecore_eap101", "AP"},
{"edgecore_eap102","AP"}, {"edgecore_eap102", "AP"},
{"edgecore_ecs4100-12ph","AP"}, {"edgecore_ecs4100-12ph", "AP"},
{"edgecore_ecw5211","AP"}, {"edgecore_ecw5211", "AP"},
{"edgecore_ecw5410","AP"}, {"edgecore_ecw5410", "AP"},
{"edgecore_oap100","AP"}, {"edgecore_oap100", "AP"},
{"edgecore_spw2ac1200","SWITCH"}, {"edgecore_spw2ac1200", "SWITCH"},
{"edgecore_spw2ac1200-lan-poe","SWITCH"}, {"edgecore_spw2ac1200-lan-poe", "SWITCH"},
{"edgecore_ssw2ac2600","SWITCH"}, {"edgecore_ssw2ac2600", "SWITCH"},
{"hfcl_ion4","AP"}, {"hfcl_ion4", "AP"},
{"indio_um-305ac","AP"}, {"indio_um-305ac", "AP"},
{"linksys_e8450-ubi","AP"}, {"linksys_e8450-ubi", "AP"},
{"linksys_ea6350","AP"}, {"linksys_ea6350", "AP"},
{"linksys_ea6350-v4","AP"}, {"linksys_ea6350-v4", "AP"},
{"linksys_ea8300","AP"}, {"linksys_ea8300", "AP"},
{"mikrotik_nand","AP"}, {"mikrotik_nand", "AP"},
{"tp-link_ec420-g1","AP"}, {"tp-link_ec420-g1", "AP"},
{"tplink_cpe210_v3","AP"}, {"tplink_cpe210_v3", "AP"},
{"tplink_cpe510_v3","AP"}, {"tplink_cpe510_v3", "AP"},
{"tplink_eap225_outdoor_v1","AP"}, {"tplink_eap225_outdoor_v1", "AP"},
{"tplink_ec420","AP"}, {"tplink_ec420", "AP"},
{"tplink_ex227","AP"}, {"tplink_ex227", "AP"},
{"tplink_ex228","AP"}, {"tplink_ex228", "AP"},
{"tplink_ex447","AP"}, {"tplink_ex447", "AP"},
{"wallys_dr40x9","AP"} {"wallys_dr40x9", "AP"}};
};
void Daemon::PostInitialization([[maybe_unused]] Poco::Util::Application &self) { void Daemon::PostInitialization([[maybe_unused]] Poco::Util::Application &self) {
AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false); AutoProvisioning_ = config().getBool("openwifi.autoprovisioning", false);
DeviceTypes_ = DefaultDeviceTypes; DeviceTypes_ = DefaultDeviceTypes;
WebSocketProcessor_ = std::make_unique<GwWebSocketClient>(logger()); WebSocketProcessor_ = std::make_unique<GwWebSocketClient>(logger());
} }
[[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const { [[nodiscard]] std::string Daemon::IdentifyDevice(const std::string &Id) const {
for(const auto &[DeviceType,Type]:DeviceTypes_) for (const auto &[DeviceType, Type] : DeviceTypes_) {
{ if (Id == DeviceType)
if(Id == DeviceType) return Type;
return Type; }
} return "AP";
return "AP"; }
}
void DaemonPostInitialization(Poco::Util::Application &self) { void DaemonPostInitialization(Poco::Util::Application &self) {
Daemon()->PostInitialization(self); Daemon()->PostInitialization(self);
GWWebSocketNotifications::Register(); GWWebSocketNotifications::Register();
} }
} } // namespace OpenWifi
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ExitCode; int ExitCode;
try { try {
Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr); Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr);
auto App = OpenWifi::Daemon::instance(); auto App = OpenWifi::Daemon::instance();
ExitCode = App->run(argc, argv); ExitCode = App->run(argc, argv);
Poco::Net::SSLManager::instance().shutdown(); Poco::Net::SSLManager::instance().shutdown();
} catch (Poco::Exception &exc) { } catch (Poco::Exception &exc) {
ExitCode = Poco::Util::Application::EXIT_SOFTWARE; ExitCode = Poco::Util::Application::EXIT_SOFTWARE;

View File

@@ -9,50 +9,47 @@
#pragma once #pragma once
#include <array> #include <array>
#include <iostream>
#include <cstdlib> #include <cstdlib>
#include <vector> #include <iostream>
#include <set> #include <set>
#include <vector>
#include "framework/MicroServiceNames.h"
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "framework/MicroServiceNames.h"
#include "Dashboard.h" #include "Dashboard.h"
#include "framework/OpenWifiTypes.h"
#include "GwWebSocketClient.h" #include "GwWebSocketClient.h"
#include "framework/OpenWifiTypes.h"
namespace OpenWifi { namespace OpenWifi {
[[maybe_unused]] static const char * vDAEMON_PROPERTIES_FILENAME = "owgw.properties"; [[maybe_unused]] static const char *vDAEMON_PROPERTIES_FILENAME = "owgw.properties";
[[maybe_unused]] static const char * vDAEMON_ROOT_ENV_VAR = "OWGW_ROOT"; [[maybe_unused]] static const char *vDAEMON_ROOT_ENV_VAR = "OWGW_ROOT";
[[maybe_unused]] static const char * vDAEMON_CONFIG_ENV_VAR = "OWGW_CONFIG"; [[maybe_unused]] static const char *vDAEMON_CONFIG_ENV_VAR = "OWGW_CONFIG";
[[maybe_unused]] static const char * vDAEMON_APP_NAME = uSERVICE_GATEWAY.c_str(); [[maybe_unused]] static const char *vDAEMON_APP_NAME = uSERVICE_GATEWAY.c_str();
[[maybe_unused]] static const uint64_t vDAEMON_BUS_TIMER = 10000; [[maybe_unused]] static const uint64_t vDAEMON_BUS_TIMER = 10000;
class Daemon : public MicroService { class Daemon : public MicroService {
public: public:
explicit Daemon(const std::string & PropFile, explicit Daemon(const std::string &PropFile, const std::string &RootEnv,
const std::string & RootEnv, const std::string &ConfigEnv, const std::string &AppName, uint64_t BusTimer,
const std::string & ConfigEnv, const SubSystemVec &SubSystems)
const std::string & AppName, : MicroService(PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems){};
uint64_t BusTimer,
const SubSystemVec & SubSystems) :
MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {};
bool AutoProvisioning() const { return AutoProvisioning_ ; } bool AutoProvisioning() const { return AutoProvisioning_; }
[[nodiscard]] std::string IdentifyDevice(const std::string & Compatible) const; [[nodiscard]] std::string IdentifyDevice(const std::string &Compatible) const;
static Daemon *instance(); static Daemon *instance();
inline DeviceDashboard & GetDashboard() { return DB_; } inline DeviceDashboard &GetDashboard() { return DB_; }
Poco::Logger & Log() { return Poco::Logger::get(AppName()); } Poco::Logger &Log() { return Poco::Logger::get(AppName()); }
void PostInitialization(Poco::Util::Application &self); void PostInitialization(Poco::Util::Application &self);
private:
bool AutoProvisioning_ = false;
std::vector<std::pair<std::string,std::string>> DeviceTypes_;
DeviceDashboard DB_;
std::unique_ptr<GwWebSocketClient> WebSocketProcessor_;
};
inline Daemon * Daemon() { return Daemon::instance(); } private:
bool AutoProvisioning_ = false;
std::vector<std::pair<std::string, std::string>> DeviceTypes_;
DeviceDashboard DB_;
std::unique_ptr<GwWebSocketClient> WebSocketProcessor_;
};
inline Daemon *Daemon() { return Daemon::instance(); }
void DaemonPostInitialization(Poco::Util::Application &self); void DaemonPostInitialization(Poco::Util::Application &self);
} } // namespace OpenWifi

View File

@@ -8,24 +8,24 @@
namespace OpenWifi { namespace OpenWifi {
bool DeviceDashboard::Get(GWObjects::Dashboard &D, Poco::Logger & Logger) { bool DeviceDashboard::Get(GWObjects::Dashboard &D, Poco::Logger &Logger) {
uint64_t Now = Utils::Now(); uint64_t Now = Utils::Now();
if(!ValidDashboard_ || LastRun_==0 || (Now-LastRun_)>120) { if (!ValidDashboard_ || LastRun_ == 0 || (Now - LastRun_) > 120) {
Generate(D, Logger); Generate(D, Logger);
} else { } else {
std::lock_guard G(DataMutex_); std::lock_guard G(DataMutex_);
D = DB_; D = DB_;
} }
return ValidDashboard_; return ValidDashboard_;
}; };
void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger & Logger ) { void DeviceDashboard::Generate(GWObjects::Dashboard &D, Poco::Logger &Logger) {
if (GeneratingDashboard_.load()) { if (GeneratingDashboard_.load()) {
// std::cout << "Trying to generate dashboard but already being generated" << std::endl; // std::cout << "Trying to generate dashboard but already being generated" << std::endl;
while(GeneratingDashboard_.load()) { while (GeneratingDashboard_.load()) {
Poco::Thread::trySleep(100); Poco::Thread::trySleep(100);
} }
std::lock_guard G(DataMutex_); std::lock_guard G(DataMutex_);
D = DB_; D = DB_;
} else { } else {
GeneratingDashboard_ = true; GeneratingDashboard_ = true;
@@ -33,19 +33,18 @@ namespace OpenWifi {
try { try {
// std::cout << "Generating dashboard." << std::endl; // std::cout << "Generating dashboard." << std::endl;
poco_information(Logger, "DASHBOARD: Generating a new dashboard."); poco_information(Logger, "DASHBOARD: Generating a new dashboard.");
GWObjects::Dashboard NewData; GWObjects::Dashboard NewData;
StorageService()->AnalyzeCommands(NewData.commands); StorageService()->AnalyzeCommands(NewData.commands);
StorageService()->AnalyzeDevices(NewData); StorageService()->AnalyzeDevices(NewData);
LastRun_ = Utils::Now(); LastRun_ = Utils::Now();
NewData.snapshot = LastRun_; NewData.snapshot = LastRun_;
D = NewData; D = NewData;
std::lock_guard G(DataMutex_); std::lock_guard G(DataMutex_);
DB_ = NewData; DB_ = NewData;
ValidDashboard_=true; ValidDashboard_ = true;
} catch(...) { } catch (...) {
} }
GeneratingDashboard_ = false; GeneratingDashboard_ = false;
} }
} }
} } // namespace OpenWifi

View File

@@ -6,22 +6,22 @@
#include <mutex> #include <mutex>
#include "Poco/Logger.h"
#include "RESTObjects//RESTAPI_GWobjects.h" #include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "Poco/Logger.h"
namespace OpenWifi { namespace OpenWifi {
class DeviceDashboard { class DeviceDashboard {
public: public:
bool Get(GWObjects::Dashboard &D, Poco::Logger & Logger); bool Get(GWObjects::Dashboard &D, Poco::Logger &Logger);
private: private:
std::mutex DataMutex_; std::mutex DataMutex_;
volatile std::atomic_bool GeneratingDashboard_=false; volatile std::atomic_bool GeneratingDashboard_ = false;
volatile bool ValidDashboard_=false; volatile bool ValidDashboard_ = false;
GWObjects::Dashboard DB_; GWObjects::Dashboard DB_;
uint64_t LastRun_=0; uint64_t LastRun_ = 0;
void Generate(GWObjects::Dashboard &D, Poco::Logger & Logger); void Generate(GWObjects::Dashboard &D, Poco::Logger &Logger);
}; };
} } // namespace OpenWifi

View File

@@ -8,16 +8,16 @@
#include <iostream> #include <iostream>
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/DynamicAny.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/CountingStream.h" #include "Poco/CountingStream.h"
#include "Poco/StreamCopier.h" #include "Poco/DynamicAny.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/StreamCopier.h"
#include "Poco/StringTokenizer.h" #include "Poco/StringTokenizer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
@@ -30,25 +30,25 @@
namespace OpenWifi { namespace OpenWifi {
static const std::string URI_BASE{"/v1/upload/"}; static const std::string URI_BASE{"/v1/upload/"};
int FileUploader::Start() { int FileUploader::Start() {
poco_notice(Logger(),"Starting."); poco_notice(Logger(), "Starting.");
Poco::File UploadsDir(MicroServiceConfigPath("openwifi.fileuploader.path","/tmp")); Poco::File UploadsDir(MicroServiceConfigPath("openwifi.fileuploader.path", "/tmp"));
Path_ = UploadsDir.path(); Path_ = UploadsDir.path();
if(!UploadsDir.exists()) { if (!UploadsDir.exists()) {
try { try {
UploadsDir.createDirectory(); UploadsDir.createDirectory();
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
Path_ = "/tmp"; Path_ = "/tmp";
} }
} }
for(const auto & Svr: ConfigServersList_) { for (const auto &Svr : ConfigServersList_) {
if(MicroServiceNoAPISecurity()) { if (MicroServiceNoAPISecurity()) {
poco_notice(Logger(), fmt::format("Starting: {}:{}",Svr.Address(),Svr.Port())); poco_notice(Logger(), fmt::format("Starting: {}:{}", Svr.Address(), Svr.Port()));
auto Sock{Svr.CreateSocket(Logger())}; auto Sock{Svr.CreateSocket(Logger())};
@@ -66,7 +66,7 @@ namespace OpenWifi {
} else { } else {
FullName_ = TmpName + URI_BASE; FullName_ = TmpName + URI_BASE;
} }
poco_information(Logger(),fmt::format("Uploader URI base is '{}'", FullName_)); poco_information(Logger(), fmt::format("Uploader URI base is '{}'", FullName_));
} }
auto NewServer = std::make_unique<Poco::Net::HTTPServer>( auto NewServer = std::make_unique<Poco::Net::HTTPServer>(
@@ -77,7 +77,7 @@ namespace OpenWifi {
} else { } else {
std::string l{"Starting: " + Svr.Address() + ":" + std::to_string(Svr.Port()) + std::string l{"Starting: " + Svr.Address() + ":" + std::to_string(Svr.Port()) +
" key:" + Svr.KeyFile() + " cert:" + Svr.CertFile()}; " key:" + Svr.KeyFile() + " cert:" + Svr.CertFile()};
poco_information(Logger(),l); poco_information(Logger(), l);
auto Sock{Svr.CreateSecureSocket(Logger())}; auto Sock{Svr.CreateSecureSocket(Logger())};
@@ -107,66 +107,62 @@ namespace OpenWifi {
NewServer->start(); NewServer->start();
Servers_.push_back(std::move(NewServer)); Servers_.push_back(std::move(NewServer));
} }
} }
MaxSize_ = 1000 * MicroServiceConfigGetInt("openwifi.fileuploader.maxsize", 10000); MaxSize_ = 1000 * MicroServiceConfigGetInt("openwifi.fileuploader.maxsize", 10000);
return 0; return 0;
} }
void FileUploader::reinitialize([[maybe_unused]] Poco::Util::Application &self) { void FileUploader::reinitialize([[maybe_unused]] Poco::Util::Application &self) {
MicroServiceLoadConfigurationFile(); MicroServiceLoadConfigurationFile();
poco_information(Logger(),"Reinitializing."); poco_information(Logger(), "Reinitializing.");
Stop(); Stop();
Start(); Start();
} }
const std::string & FileUploader::FullName() { const std::string &FileUploader::FullName() { return FullName_; }
return FullName_;
}
// if you pass in an empty UUID, it will just clean the list and not add it. // if you pass in an empty UUID, it will just clean the list and not add it.
bool FileUploader::AddUUID( const std::string & UUID, std::chrono::seconds WaitTimeInSeconds, const std::string &Type) { bool FileUploader::AddUUID(const std::string &UUID, std::chrono::seconds WaitTimeInSeconds,
std::lock_guard Guard(Mutex_); const std::string &Type) {
std::lock_guard Guard(Mutex_);
uint64_t now = Utils::Now(); uint64_t now = Utils::Now();
auto Func=[now](const UploadId &I) -> bool { auto Func = [now](const UploadId &I) -> bool { return (now > I.Expires); };
return (now > I.Expires); OutStandingUploads_.erase(
}; std::remove_if(OutStandingUploads_.begin(), OutStandingUploads_.end(), Func),
OutStandingUploads_.erase(std::remove_if(OutStandingUploads_.begin(),OutStandingUploads_.end(),Func),OutStandingUploads_.end()); OutStandingUploads_.end());
OutStandingUploads_.emplace_back(UploadId{UUID, now + WaitTimeInSeconds.count(), Type}); OutStandingUploads_.emplace_back(UploadId{UUID, now + WaitTimeInSeconds.count(), Type});
return true; return true;
} }
bool FileUploader::ValidRequest(const std::string &UUID) { bool FileUploader::ValidRequest(const std::string &UUID) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
auto Func = [UUID](const UploadId &P) -> bool { auto Func = [UUID](const UploadId &P) -> bool { return (P.UUID == UUID); };
return (P.UUID==UUID); return std::find_if(OutStandingUploads_.begin(), OutStandingUploads_.end(), Func) !=
}; end(OutStandingUploads_);
return std::find_if(OutStandingUploads_.begin(), OutStandingUploads_.end(), Func) != end(OutStandingUploads_); }
}
void FileUploader::RemoveRequest(const std::string &UUID) { void FileUploader::RemoveRequest(const std::string &UUID) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
auto Func = [UUID](const UploadId &P) -> bool { auto Func = [UUID](const UploadId &P) -> bool { return (P.UUID == UUID); };
return (P.UUID==UUID); OutStandingUploads_.erase(
}; std::remove_if(OutStandingUploads_.begin(), OutStandingUploads_.end(), Func),
OutStandingUploads_.erase(std::remove_if(OutStandingUploads_.begin(),OutStandingUploads_.end(),Func),OutStandingUploads_.end()); OutStandingUploads_.end());
} }
class FileUploaderPartHandler2 : public Poco::Net::PartHandler { class FileUploaderPartHandler2 : public Poco::Net::PartHandler {
public: public:
FileUploaderPartHandler2(std::string Id, Poco::Logger &Logger, std::stringstream & ofs) : FileUploaderPartHandler2(std::string Id, Poco::Logger &Logger, std::stringstream &ofs)
Id_(std::move(Id)), : Id_(std::move(Id)), Logger_(Logger), OutputStream_(ofs) {}
Logger_(Logger),
OutputStream_(ofs){
}
void handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream) { void handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream) {
FileType_ = Header.get(RESTAPI::Protocol::CONTENTTYPE, RESTAPI::Protocol::UNSPECIFIED); FileType_ = Header.get(RESTAPI::Protocol::CONTENTTYPE, RESTAPI::Protocol::UNSPECIFIED);
if (Header.has(RESTAPI::Protocol::CONTENTDISPOSITION)) { if (Header.has(RESTAPI::Protocol::CONTENTDISPOSITION)) {
std::string Disposition; std::string Disposition;
Poco::Net::NameValueCollection Parameters; Poco::Net::NameValueCollection Parameters;
Poco::Net::MessageHeader::splitParameters(Header[RESTAPI::Protocol::CONTENTDISPOSITION], Disposition, Parameters); Poco::Net::MessageHeader::splitParameters(
Header[RESTAPI::Protocol::CONTENTDISPOSITION], Disposition, Parameters);
Name_ = Parameters.get(RESTAPI::Protocol::NAME, RESTAPI::Protocol::UNNAMED); Name_ = Parameters.get(RESTAPI::Protocol::NAME, RESTAPI::Protocol::UNNAMED);
} }
Poco::CountingInputStream InputStream(Stream); Poco::CountingInputStream InputStream(Stream);
@@ -178,33 +174,30 @@ namespace OpenWifi {
[[nodiscard]] std::string &ContentType() { return FileType_; } [[nodiscard]] std::string &ContentType() { return FileType_; }
private: private:
uint64_t Length_ = 0; uint64_t Length_ = 0;
std::string FileType_; std::string FileType_;
std::string Name_; std::string Name_;
std::string Id_; std::string Id_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
std::stringstream &OutputStream_; std::stringstream &OutputStream_;
inline Poco::Logger & Logger() { return Logger_; }; inline Poco::Logger &Logger() { return Logger_; };
}; };
class FormRequestHandler: public Poco::Net::HTTPRequestHandler class FormRequestHandler : public Poco::Net::HTTPRequestHandler {
{ public:
public: explicit FormRequestHandler(std::string UUID, Poco::Logger &L, const std::string &Type)
explicit FormRequestHandler(std::string UUID, Poco::Logger & L, const std::string &Type): : UUID_(std::move(UUID)), Logger_(L), Type_(Type) {}
UUID_(std::move(UUID)),
Logger_(L),
Type_(Type)
{
}
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) final { void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) final {
Utils::SetThreadName("FileUploader"); Utils::SetThreadName("FileUploader");
const auto ContentType = Request.getContentType(); const auto ContentType = Request.getContentType();
const auto Tokens = Poco::StringTokenizer(ContentType,";",Poco::StringTokenizer::TOK_TRIM); const auto Tokens =
Poco::StringTokenizer(ContentType, ";", Poco::StringTokenizer::TOK_TRIM);
poco_debug(Logger(),fmt::format("{}: Preparing to upload trace file.",UUID_)); poco_debug(Logger(), fmt::format("{}: Preparing to upload trace file.", UUID_));
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
try { try {
@@ -229,8 +222,9 @@ namespace OpenWifi {
Poco::StreamCopier::copyStream(Reader.stream(), FileContent); Poco::StreamCopier::copyStream(Reader.stream(), FileContent);
Answer.set("filename", UUID_); Answer.set("filename", UUID_);
Answer.set("error", 0); Answer.set("error", 0);
poco_debug(Logger(),fmt::format("{}: File uploaded.", UUID_)); poco_debug(Logger(), fmt::format("{}: File uploaded.", UUID_));
StorageService()->AttachFileDataToCommand(UUID_, FileContent, Type_); StorageService()->AttachFileDataToCommand(UUID_, FileContent,
Type_);
std::ostream &ResponseStream = Response.send(); std::ostream &ResponseStream = Response.send();
Poco::JSON::Stringifier::stringify(Answer, ResponseStream); Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
return; return;
@@ -247,10 +241,10 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_debug(Logger(),"Exception while receiving trace file."); poco_debug(Logger(), "Exception while receiving trace file.");
} }
poco_debug(Logger(),fmt::format("{}: Failed to upload trace file.",UUID_)); poco_debug(Logger(), fmt::format("{}: Failed to upload trace file.", UUID_));
std::string Error{"Trace file rejected"}; std::string Error{"Trace file rejected"};
StorageService()->CancelWaitFile(UUID_, Error); StorageService()->CancelWaitFile(UUID_, Error);
Answer.set("filename", UUID_); Answer.set("filename", UUID_);
@@ -261,48 +255,50 @@ namespace OpenWifi {
Poco::JSON::Stringifier::stringify(Answer, ResponseStream); Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
} }
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
private: private:
std::string UUID_; std::string UUID_;
Poco::Logger & Logger_; Poco::Logger &Logger_;
std::string Type_; std::string Type_;
}; };
Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(
const Poco::Net::HTTPServerRequest &Request) {
poco_debug(Logger(),fmt::format("REQUEST({}): {} {}", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI())); poco_debug(Logger(), fmt::format("REQUEST({}): {} {}",
Utils::FormatIPv6(Request.clientAddress().toString()),
Request.getMethod(), Request.getURI()));
if(Request.getMethod()!=Poco::Net::HTTPRequest::HTTP_POST || if (Request.getMethod() != Poco::Net::HTTPRequest::HTTP_POST ||
Request.getURI().size()<(URI_BASE.size()+36)) { Request.getURI().size() < (URI_BASE.size() + 36)) {
poco_warning(Logger(),fmt::format("ILLEGAL-REQUEST({}): {} {}. Dropped.", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI())); poco_warning(Logger(),
fmt::format("ILLEGAL-REQUEST({}): {} {}. Dropped.",
Utils::FormatIPv6(Request.clientAddress().toString()),
Request.getMethod(), Request.getURI()));
return nullptr; return nullptr;
} }
// The UUID should be after the /v1/upload/ part... // The UUID should be after the /v1/upload/ part...
auto UUIDLocation = Request.getURI().find_first_of(URI_BASE); auto UUIDLocation = Request.getURI().find_first_of(URI_BASE);
if( UUIDLocation != std::string::npos ) if (UUIDLocation != std::string::npos) {
{ auto UUID = Request.getURI().substr(UUIDLocation + URI_BASE.size());
auto UUID = Request.getURI().substr(UUIDLocation+URI_BASE.size());
FileUploader::UploadId E; FileUploader::UploadId E;
if(FileUploader()->Find(UUID,E)) if (FileUploader()->Find(UUID, E)) {
{
FileUploader()->RemoveRequest(UUID); FileUploader()->RemoveRequest(UUID);
return new FormRequestHandler(UUID,Logger(),E.Type); return new FormRequestHandler(UUID, Logger(), E.Type);
} } else {
else poco_warning(Logger(), fmt::format("Unknown UUID={}", UUID));
{ }
poco_warning(Logger(),fmt::format("Unknown UUID={}",UUID)); }
} return nullptr;
} }
return nullptr;
}
bool FileUploader::Find(const std::string &UUID, UploadId &V) { bool FileUploader::Find(const std::string &UUID, UploadId &V) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
for(const auto &E:OutStandingUploads_) { for (const auto &E : OutStandingUploads_) {
if (E.UUID == UUID) { if (E.UUID == UUID) {
V = E; V = E;
return true; return true;
@@ -311,12 +307,12 @@ namespace OpenWifi {
return false; return false;
} }
void FileUploader::Stop() { void FileUploader::Stop() {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
for( const auto & svr : Servers_ ) for (const auto &svr : Servers_)
svr->stopAll(true); svr->stopAll(true);
Servers_.clear(); Servers_.clear();
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
} // Namespace } // namespace OpenWifi

View File

@@ -17,59 +17,55 @@
namespace OpenWifi { namespace OpenWifi {
class FileUploader : public SubSystemServer { class FileUploader : public SubSystemServer {
public: public:
struct UploadId { struct UploadId {
std::string UUID; std::string UUID;
std::uint64_t Expires; std::uint64_t Expires;
std::string Type; std::string Type;
}; };
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void reinitialize(Poco::Util::Application &self) override; void reinitialize(Poco::Util::Application &self) override;
const std::string & FullName(); const std::string &FullName();
bool AddUUID( const std::string & UUID, std::chrono::seconds WaitTimeInSecond, const std::string &Type); bool AddUUID(const std::string &UUID, std::chrono::seconds WaitTimeInSecond,
bool ValidRequest(const std::string & UUID); const std::string &Type);
bool ValidRequest(const std::string &UUID);
void RemoveRequest(const std::string &UUID); void RemoveRequest(const std::string &UUID);
const std::string & Path() { return Path_; }; const std::string &Path() { return Path_; };
static auto instance() { static auto instance() {
static auto instance_ = new FileUploader; static auto instance_ = new FileUploader;
return instance_; return instance_;
} }
[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; } [[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; }
bool Find(const std::string &UUID, UploadId &V); bool Find(const std::string &UUID, UploadId &V);
private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
std::string FullName_;
std::list<UploadId> OutStandingUploads_;
std::string Path_;
uint64_t MaxSize_=10000000;
explicit FileUploader() noexcept: private:
SubSystemServer("FileUploader", "FILE-UPLOAD", "openwifi.fileuploader") std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
{ std::string FullName_;
} std::list<UploadId> OutStandingUploads_;
}; std::string Path_;
uint64_t MaxSize_ = 10000000;
class FileUpLoaderRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { explicit FileUploader() noexcept
public: : SubSystemServer("FileUploader", "FILE-UPLOAD", "openwifi.fileuploader") {}
explicit FileUpLoaderRequestHandlerFactory(Poco::Logger &L) : };
Logger_(L) {
}
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override; class FileUpLoaderRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
inline Poco::Logger & Logger() { public:
return Logger_; explicit FileUpLoaderRequestHandlerFactory(Poco::Logger &L) : Logger_(L) {}
}
private: Poco::Net::HTTPRequestHandler *
Poco::Logger & Logger_; createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
}; inline Poco::Logger &Logger() { return Logger_; }
private:
Poco::Logger &Logger_;
};
inline auto FileUploader() { return FileUploader::instance(); } inline auto FileUploader() { return FileUploader::instance(); }
} // namespace } // namespace OpenWifi

View File

@@ -6,8 +6,8 @@
#include "Poco/Net/IPAddress.h" #include "Poco/Net/IPAddress.h"
#include "framework/SubSystemServer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/SubSystemServer.h"
#include "nlohmann/json.hpp" #include "nlohmann/json.hpp"
@@ -15,11 +15,10 @@ namespace OpenWifi {
class IPToCountryProvider { class IPToCountryProvider {
public: public:
virtual bool Init() = 0 ; virtual bool Init() = 0;
virtual Poco::URI URI(const std::string & IPAddress) = 0; virtual Poco::URI URI(const std::string &IPAddress) = 0;
virtual std::string Country( const std::string & Response ) = 0 ; virtual std::string Country(const std::string &Response) = 0;
virtual ~IPToCountryProvider() { virtual ~IPToCountryProvider(){};
};
}; };
class IPInfo : public IPToCountryProvider { class IPInfo : public IPToCountryProvider {
@@ -30,28 +29,26 @@ namespace OpenWifi {
return !Key_.empty(); return !Key_.empty();
} }
[[nodiscard]] inline Poco::URI URI(const std::string & IPAddress) override { [[nodiscard]] inline Poco::URI URI(const std::string &IPAddress) override {
Poco::URI U("https://ipinfo.io"); Poco::URI U("https://ipinfo.io");
U.setPath("/" + IPAddress); U.setPath("/" + IPAddress);
U.addQueryParameter("token",Key_); U.addQueryParameter("token", Key_);
return U; return U;
} }
inline std::string Country( const std::string & Response ) override { inline std::string Country(const std::string &Response) override {
try { try {
nlohmann::json IPInfo = nlohmann::json::parse(Response); nlohmann::json IPInfo = nlohmann::json::parse(Response);
if (IPInfo.contains("country") && IPInfo["country"].is_string()) { if (IPInfo.contains("country") && IPInfo["country"].is_string()) {
return IPInfo["country"]; return IPInfo["country"];
} }
} catch (...) { } catch (...) {
} }
return ""; return "";
} }
private: private:
std::string Key_; std::string Key_;
}; };
class IPData : public IPToCountryProvider { class IPData : public IPToCountryProvider {
@@ -62,24 +59,24 @@ namespace OpenWifi {
return !Key_.empty(); return !Key_.empty();
} }
[[nodiscard]] inline Poco::URI URI(const std::string & IPAddress) override { [[nodiscard]] inline Poco::URI URI(const std::string &IPAddress) override {
Poco::URI U("https://api.ipdata.co"); Poco::URI U("https://api.ipdata.co");
U.setPath("/" + IPAddress); U.setPath("/" + IPAddress);
U.addQueryParameter("api-key",Key_); U.addQueryParameter("api-key", Key_);
return U; return U;
} }
inline std::string Country( const std::string & Response ) override { inline std::string Country(const std::string &Response) override {
try { try {
nlohmann::json IPInfo = nlohmann::json::parse(Response); nlohmann::json IPInfo = nlohmann::json::parse(Response);
if (IPInfo.contains("country_code") && IPInfo["country_code"].is_string()) { if (IPInfo.contains("country_code") && IPInfo["country_code"].is_string()) {
return IPInfo["country_code"]; return IPInfo["country_code"];
} }
} catch (...) { } catch (...) {
} }
return ""; return "";
} }
private: private:
std::string Key_; std::string Key_;
}; };
@@ -92,33 +89,33 @@ namespace OpenWifi {
return !Key_.empty(); return !Key_.empty();
} }
[[nodiscard]] inline Poco::URI URI(const std::string & IPAddress) override { [[nodiscard]] inline Poco::URI URI(const std::string &IPAddress) override {
Poco::URI U("https://api.ip2location.com/v2"); Poco::URI U("https://api.ip2location.com/v2");
U.setPath("/"); U.setPath("/");
U.addQueryParameter("ip", IPAddress); U.addQueryParameter("ip", IPAddress);
U.addQueryParameter("package", "WS1"); U.addQueryParameter("package", "WS1");
U.addQueryParameter("key",Key_); U.addQueryParameter("key", Key_);
return U; return U;
} }
inline std::string Country( const std::string & Response ) override { inline std::string Country(const std::string &Response) override {
try { try {
nlohmann::json IPInfo = nlohmann::json::parse(Response); nlohmann::json IPInfo = nlohmann::json::parse(Response);
if (IPInfo.contains("country_code") && IPInfo["country_code"].is_string()) { if (IPInfo.contains("country_code") && IPInfo["country_code"].is_string()) {
return IPInfo["country_code"]; return IPInfo["country_code"];
} }
} catch (...) { } catch (...) {
} }
return ""; return "";
} }
private: private:
std::string Key_; std::string Key_;
}; };
template<typename BaseClass, typename T, typename... Args> template <typename BaseClass, typename T, typename... Args>
std::unique_ptr<BaseClass> IPLocationProvider(const std::string & RequestProvider ) { std::unique_ptr<BaseClass> IPLocationProvider(const std::string &RequestProvider) {
if(T::Name()==RequestProvider) { if (T::Name() == RequestProvider) {
return std::make_unique<T>(); return std::make_unique<T>();
} }
if constexpr (sizeof...(Args) == 0) { if constexpr (sizeof...(Args) == 0) {
@@ -136,11 +133,12 @@ namespace OpenWifi {
} }
inline int Start() final { inline int Start() final {
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
ProviderName_ = MicroServiceConfigGetString("iptocountry.provider",""); ProviderName_ = MicroServiceConfigGetString("iptocountry.provider", "");
if(!ProviderName_.empty()) { if (!ProviderName_.empty()) {
Provider_ = IPLocationProvider<IPToCountryProvider, IPInfo, IPData, IP2Location>(ProviderName_); Provider_ = IPLocationProvider<IPToCountryProvider, IPInfo, IPData, IP2Location>(
if(Provider_!= nullptr) { ProviderName_);
if (Provider_ != nullptr) {
Enabled_ = Provider_->Init(); Enabled_ = Provider_->Init();
} }
} }
@@ -149,28 +147,26 @@ namespace OpenWifi {
} }
inline void Stop() final { inline void Stop() final {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
// Nothing to do - just to provide the same look at the others. // Nothing to do - just to provide the same look at the others.
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
[[nodiscard]] static inline std::string ReformatAddress(const std::string & I ) [[nodiscard]] static inline std::string ReformatAddress(const std::string &I) {
{ if (I.substr(0, 7) == "::ffff:") {
if(I.substr(0,7) == "::ffff:") std::string ip = I.substr(7);
{
std::string ip = I.substr(7 );
return ip; return ip;
} }
return I; return I;
} }
inline std::string Get(const Poco::Net::IPAddress & IP) { inline std::string Get(const Poco::Net::IPAddress &IP) {
if (!Enabled_) if (!Enabled_)
return Default_; return Default_;
return Get(ReformatAddress(IP.toString())); return Get(ReformatAddress(IP.toString()));
} }
inline std::string Get(const std::string & IP) { inline std::string Get(const std::string &IP) {
if (!Enabled_) if (!Enabled_)
return Default_; return Default_;
try { try {
@@ -178,10 +174,10 @@ namespace OpenWifi {
std::string Response; std::string Response;
if (Utils::wgets(URL, Response)) { if (Utils::wgets(URL, Response)) {
auto Answer = Provider_->Country(Response); auto Answer = Provider_->Country(Response);
if(!Answer.empty()) if (!Answer.empty())
return Answer; return Answer;
} }
} catch(...) { } catch (...) {
} }
return Default_; return Default_;
} }
@@ -189,17 +185,14 @@ namespace OpenWifi {
inline auto Enabled() const { return Enabled_; } inline auto Enabled() const { return Enabled_; }
private: private:
bool Enabled_=false; bool Enabled_ = false;
std::string Default_; std::string Default_;
std::unique_ptr<IPToCountryProvider> Provider_; std::unique_ptr<IPToCountryProvider> Provider_;
std::string ProviderName_; std::string ProviderName_;
FindCountryFromIP() noexcept: FindCountryFromIP() noexcept : SubSystemServer("IpToCountry", "IPTOC-SVR", "iptocountry") {}
SubSystemServer("IpToCountry", "IPTOC-SVR", "iptocountry")
{
}
}; };
inline auto FindCountryFromIP() { return FindCountryFromIP::instance(); } inline auto FindCountryFromIP() { return FindCountryFromIP::instance(); }
} } // namespace OpenWifi

View File

@@ -7,7 +7,7 @@
namespace OpenWifi { namespace OpenWifi {
void GWKafkaEvents::Send() { void GWKafkaEvents::Send() {
if(KafkaManager()->Enabled()) { if (KafkaManager()->Enabled()) {
Poco::JSON::Object Event; Poco::JSON::Object Event;
Event.set("type", type_); Event.set("type", type_);
Event.set("timestamp", timestamp_); Event.set("timestamp", timestamp_);

View File

@@ -4,57 +4,53 @@
#pragma once #pragma once
#include <string>
#include <Poco/JSON/Object.h> #include <Poco/JSON/Object.h>
#include <framework/KafkaManager.h> #include <framework/KafkaManager.h>
#include <string>
namespace OpenWifi { namespace OpenWifi {
class GWKafkaEvents { class GWKafkaEvents {
public: public:
GWKafkaEvents(const std::string &serialNumber, const std::string &type, std::uint64_t timestamp) : GWKafkaEvents(const std::string &serialNumber, const std::string &type,
serialNumber_(serialNumber), std::uint64_t timestamp)
type_(type), : serialNumber_(serialNumber), type_(type), timestamp_(timestamp) {}
timestamp_(timestamp) {
}
inline void SetPayload(Poco::JSON::Object::Ptr payload) { inline void SetPayload(Poco::JSON::Object::Ptr payload) { payload_ = std::move(payload); }
payload_ = std::move(payload);
}
void Send(); void Send();
private: private:
std::string serialNumber_; std::string serialNumber_;
std::string type_; std::string type_;
std::uint64_t timestamp_=0; std::uint64_t timestamp_ = 0;
Poco::JSON::Object::Ptr payload_; Poco::JSON::Object::Ptr payload_;
}; };
class DeviceFirmwareChangeKafkaEvent : public GWKafkaEvents { class DeviceFirmwareChangeKafkaEvent : public GWKafkaEvents {
public: public:
DeviceFirmwareChangeKafkaEvent( const std::string &serialNumber, std::uint64_t timestamp, const std::string &oldFirmware, const std::string &newFirmware) : DeviceFirmwareChangeKafkaEvent(const std::string &serialNumber, std::uint64_t timestamp,
GWKafkaEvents(serialNumber,"unit.firmware_change", timestamp), const std::string &oldFirmware,
oldFirmware_(oldFirmware), const std::string &newFirmware)
newFirmware_(newFirmware) { : GWKafkaEvents(serialNumber, "unit.firmware_change", timestamp),
} oldFirmware_(oldFirmware), newFirmware_(newFirmware) {}
~DeviceFirmwareChangeKafkaEvent() { ~DeviceFirmwareChangeKafkaEvent() {
Poco::JSON::Object::Ptr payload = new Poco::JSON::Object; Poco::JSON::Object::Ptr payload = new Poco::JSON::Object;
payload->set("oldFirmware", oldFirmware_); payload->set("oldFirmware", oldFirmware_);
payload->set("newFirmware",newFirmware_); payload->set("newFirmware", newFirmware_);
SetPayload(payload); SetPayload(payload);
Send(); Send();
} }
private: private:
std::string oldFirmware_, newFirmware_; std::string oldFirmware_, newFirmware_;
}; };
class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents { class DeviceConfigurationChangeKafkaEvent : public GWKafkaEvents {
public: public:
DeviceConfigurationChangeKafkaEvent( const std::string &serialNumber, std::uint64_t timestamp, const std::string config) : DeviceConfigurationChangeKafkaEvent(const std::string &serialNumber,
GWKafkaEvents(serialNumber,"unit.configuration_change", timestamp), std::uint64_t timestamp, const std::string config)
config_(config) { : GWKafkaEvents(serialNumber, "unit.configuration_change", timestamp), config_(config) {
} }
~DeviceConfigurationChangeKafkaEvent() { ~DeviceConfigurationChangeKafkaEvent() {
@@ -70,11 +66,12 @@ namespace OpenWifi {
class DeviceBlacklistedKafkaEvent : public GWKafkaEvents { class DeviceBlacklistedKafkaEvent : public GWKafkaEvents {
public: public:
explicit DeviceBlacklistedKafkaEvent( const std::string &serialNumber, std::uint64_t timestamp, const std::string &reason, const std::string &author, std::uint64_t created, std::string &IP) : explicit DeviceBlacklistedKafkaEvent(const std::string &serialNumber,
GWKafkaEvents(serialNumber,"blacklisted_device", timestamp), std::uint64_t timestamp, const std::string &reason,
reason_(reason), author_(author), created_(created), IP_(IP) const std::string &author, std::uint64_t created,
{ std::string &IP)
} : GWKafkaEvents(serialNumber, "blacklisted_device", timestamp), reason_(reason),
author_(author), created_(created), IP_(IP) {}
~DeviceBlacklistedKafkaEvent() { ~DeviceBlacklistedKafkaEvent() {
Poco::JSON::Object::Ptr payload = new Poco::JSON::Object; Poco::JSON::Object::Ptr payload = new Poco::JSON::Object;
@@ -87,11 +84,9 @@ namespace OpenWifi {
} }
private: private:
std::string reason_,author_; std::string reason_, author_;
std::uint64_t created_; std::uint64_t created_;
std::string IP_; std::string IP_;
}; };
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -7,23 +7,22 @@
namespace OpenWifi { namespace OpenWifi {
GwWebSocketClient::GwWebSocketClient(Poco::Logger &Logger): GwWebSocketClient::GwWebSocketClient(Poco::Logger &Logger) : Logger_(Logger) {
Logger_(Logger){
UI_WebSocketClientServer()->SetProcessor(this); UI_WebSocketClientServer()->SetProcessor(this);
} }
GwWebSocketClient::~GwWebSocketClient() { GwWebSocketClient::~GwWebSocketClient() { UI_WebSocketClientServer()->SetProcessor(nullptr); }
UI_WebSocketClientServer()->SetProcessor(nullptr);
}
void GwWebSocketClient::Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done, [[maybe_unused]] const SecurityObjects::UserInfo &UserInfo) { void GwWebSocketClient::Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer,
bool &Done,
[[maybe_unused]] const SecurityObjects::UserInfo &UserInfo) {
try { try {
if (O->has("command")) { if (O->has("command")) {
auto Command = O->get("command").toString(); auto Command = O->get("command").toString();
if (Command == "serial_number_search" && O->has("serial_prefix")) { if (Command == "serial_number_search" && O->has("serial_prefix")) {
ws_command_serial_number_search(O,Done,Answer); ws_command_serial_number_search(O, Done, Answer);
} else if (Command=="exit") { } else if (Command == "exit") {
ws_command_exit(O,Done,Answer); ws_command_exit(O, Done, Answer);
} else { } else {
ws_command_invalid(O, Done, Answer); ws_command_invalid(O, Done, Answer);
} }
@@ -34,7 +33,7 @@ namespace OpenWifi {
} }
void GwWebSocketClient::ws_command_serial_number_search(const Poco::JSON::Object::Ptr &O, void GwWebSocketClient::ws_command_serial_number_search(const Poco::JSON::Object::Ptr &O,
bool &Done, std::string &Answer) { bool &Done, std::string &Answer) {
Done = false; Done = false;
auto Prefix = O->get("serial_prefix").toString(); auto Prefix = O->get("serial_prefix").toString();
if (!Prefix.empty() && Prefix.length() < 13) { if (!Prefix.empty() && Prefix.length() < 13) {
@@ -51,13 +50,15 @@ namespace OpenWifi {
} }
} }
void GwWebSocketClient::ws_command_exit([[maybe_unused]] const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { void GwWebSocketClient::ws_command_exit([[maybe_unused]] const Poco::JSON::Object::Ptr &O,
bool &Done, std::string &Answer) {
Done = true; Done = true;
Answer = R"lit({ "closing" : "Goodbye! Aurevoir! Hasta la vista!" })lit"; Answer = R"lit({ "closing" : "Goodbye! Aurevoir! Hasta la vista!" })lit";
} }
void GwWebSocketClient::ws_command_invalid([[maybe_unused]] const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { void GwWebSocketClient::ws_command_invalid([[maybe_unused]] const Poco::JSON::Object::Ptr &O,
bool &Done, std::string &Answer) {
Done = false; Done = false;
Answer = std::string{R"lit({ "error" : "invalid command" })lit"}; Answer = std::string{R"lit({ "error" : "invalid command" })lit"};
} }
} } // namespace OpenWifi

View File

@@ -11,13 +11,15 @@ namespace OpenWifi {
public: public:
explicit GwWebSocketClient(Poco::Logger &Logger); explicit GwWebSocketClient(Poco::Logger &Logger);
virtual ~GwWebSocketClient(); virtual ~GwWebSocketClient();
virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done, const SecurityObjects::UserInfo &UserInfo); virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done,
void ws_command_serial_number_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); const SecurityObjects::UserInfo &UserInfo);
void ws_command_exit( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); void ws_command_serial_number_search(const Poco::JSON::Object::Ptr &O, bool &Done,
void ws_command_invalid( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); std::string &Answer);
void ws_command_exit(const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer);
void ws_command_invalid(const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer);
private: private:
Poco::Logger & Logger_; Poco::Logger &Logger_;
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
}; };
} } // namespace OpenWifi

View File

@@ -1,15 +1,15 @@
// //
// Created by stephane bourque on 2021-06-17. // Created by stephane bourque on 2021-06-17.
// //
#include <thread>
#include <fstream> #include <fstream>
#include <thread>
#include <vector> #include <vector>
#include "Poco/File.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/StringTokenizer.h" #include "Poco/StringTokenizer.h"
#include "Poco/URIStreamOpener.h" #include "Poco/URIStreamOpener.h"
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/utils.h" #include "framework/utils.h"
@@ -22,25 +22,25 @@ namespace OpenWifi {
int OUIServer::Start() { int OUIServer::Start() {
Running_ = true; Running_ = true;
LatestOUIFileName_ = MicroServiceDataDirectory() + "/newOUIFile.txt"; LatestOUIFileName_ = MicroServiceDataDirectory() + "/newOUIFile.txt";
CurrentOUIFileName_ = MicroServiceDataDirectory() + "/current_oui.txt"; CurrentOUIFileName_ = MicroServiceDataDirectory() + "/current_oui.txt";
bool Recovered = false; bool Recovered = false;
Poco::File OuiFile(CurrentOUIFileName_); Poco::File OuiFile(CurrentOUIFileName_);
if(OuiFile.exists()) { if (OuiFile.exists()) {
std::unique_lock Lock(LocalMutex_); std::unique_lock Lock(LocalMutex_);
Recovered = ProcessFile(CurrentOUIFileName_,OUIs_); Recovered = ProcessFile(CurrentOUIFileName_, OUIs_);
if(Recovered) { if (Recovered) {
poco_notice(Logger(), poco_notice(Logger(),
fmt::format("Recovered last OUI file - {}", CurrentOUIFileName_)); fmt::format("Recovered last OUI file - {}", CurrentOUIFileName_));
} }
} else { } else {
poco_notice(Logger(), poco_notice(Logger(), fmt::format("No existing OUIFile.", CurrentOUIFileName_));
fmt::format("No existing OUIFile.", CurrentOUIFileName_));
} }
UpdaterCallBack_ = std::make_unique<Poco::TimerCallback<OUIServer>>(*this, &OUIServer::onTimer); UpdaterCallBack_ =
if(Recovered) { std::make_unique<Poco::TimerCallback<OUIServer>>(*this, &OUIServer::onTimer);
if (Recovered) {
Timer_.setStartInterval(60 * 60 * 1000); // first run in 1 hour Timer_.setStartInterval(60 * 60 * 1000); // first run in 1 hour
} else { } else {
Timer_.setStartInterval(30 * 1000); // first run in 5 minutes Timer_.setStartInterval(30 * 1000); // first run in 5 minutes
@@ -51,15 +51,15 @@ namespace OpenWifi {
} }
void OUIServer::Stop() { void OUIServer::Stop() {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
Running_=false; Running_ = false;
Timer_.stop(); Timer_.stop();
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
void OUIServer::reinitialize([[maybe_unused]] Poco::Util::Application &self) { void OUIServer::reinitialize([[maybe_unused]] Poco::Util::Application &self) {
MicroServiceLoadConfigurationFile(); MicroServiceLoadConfigurationFile();
poco_information(Logger(),"Reinitializing."); poco_information(Logger(), "Reinitializing.");
Stop(); Stop();
Start(); Start();
} }
@@ -67,14 +67,18 @@ namespace OpenWifi {
bool OUIServer::GetFile(const std::string &FileName) { bool OUIServer::GetFile(const std::string &FileName) {
try { try {
LastUpdate_ = Utils::Now(); LastUpdate_ = Utils::Now();
poco_information(Logger(), fmt::format("Start: Retrieving OUI file: {}",MicroServiceConfigGetString("oui.download.uri",""))); poco_information(Logger(),
std::unique_ptr<std::istream> pStr( fmt::format("Start: Retrieving OUI file: {}",
Poco::URIStreamOpener::defaultOpener().open(MicroServiceConfigGetString("oui.download.uri",""))); MicroServiceConfigGetString("oui.download.uri", "")));
std::unique_ptr<std::istream> pStr(Poco::URIStreamOpener::defaultOpener().open(
MicroServiceConfigGetString("oui.download.uri", "")));
std::ofstream OS; std::ofstream OS;
OS.open(FileName); OS.open(FileName);
Poco::StreamCopier::copyStream(*pStr, OS); Poco::StreamCopier::copyStream(*pStr, OS);
OS.close(); OS.close();
poco_information(Logger(), fmt::format("Done: Retrieving OUI file: {}",MicroServiceConfigGetString("oui.download.uri",""))); poco_information(Logger(),
fmt::format("Done: Retrieving OUI file: {}",
MicroServiceConfigGetString("oui.download.uri", "")));
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
@@ -82,13 +86,13 @@ namespace OpenWifi {
return false; return false;
} }
bool OUIServer::ProcessFile( const std::string &FileName, OUIMap &Map) { bool OUIServer::ProcessFile(const std::string &FileName, OUIMap &Map) {
try { try {
std::ifstream Input; std::ifstream Input;
Input.open(FileName, std::ios::binary); Input.open(FileName, std::ios::binary);
while (!Input.eof()) { while (!Input.eof()) {
if(!Running_) if (!Running_)
return false; return false;
char buf[1024]; char buf[1024];
Input.getline(buf, sizeof(buf)); Input.getline(buf, sizeof(buf));
@@ -112,67 +116,68 @@ namespace OpenWifi {
} }
} }
return true; return true;
} catch ( const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} }
return false; return false;
} }
void OUIServer::onTimer([[maybe_unused]] Poco::Timer & timer) { void OUIServer::onTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("ouisvr-timer"); Utils::SetThreadName("ouisvr-timer");
if(Updating_) if (Updating_)
return; return;
Updating_ = true; Updating_ = true;
poco_information(Logger(),"Starting to process OUI file..."); poco_information(Logger(), "Starting to process OUI file...");
// fetch data from server, if not available, just use the file we already have. // fetch data from server, if not available, just use the file we already have.
Poco::File Current(CurrentOUIFileName_); Poco::File Current(CurrentOUIFileName_);
if(Current.exists()) { if (Current.exists()) {
if((Utils::Now()-Current.getLastModified().epochTime()) < (7*24*60*60)) { if ((Utils::Now() - Current.getLastModified().epochTime()) < (7 * 24 * 60 * 60)) {
if(!Initialized_) { if (!Initialized_) {
if(ProcessFile(CurrentOUIFileName_, OUIs_)) { if (ProcessFile(CurrentOUIFileName_, OUIs_)) {
Initialized_ = true; Initialized_ = true;
Updating_=false; Updating_ = false;
poco_information(Logger(), "Using cached file."); poco_information(Logger(), "Using cached file.");
return; return;
} }
} else { } else {
Updating_=false; Updating_ = false;
return; return;
} }
} }
} }
OUIMap TmpOUIs; OUIMap TmpOUIs;
if(GetFile(LatestOUIFileName_) && ProcessFile(LatestOUIFileName_, TmpOUIs)) { if (GetFile(LatestOUIFileName_) && ProcessFile(LatestOUIFileName_, TmpOUIs)) {
std::unique_lock G(LocalMutex_); std::unique_lock G(LocalMutex_);
OUIs_ = std::move(TmpOUIs); OUIs_ = std::move(TmpOUIs);
LastUpdate_ = Utils::Now(); LastUpdate_ = Utils::Now();
Poco::File F1(CurrentOUIFileName_); Poco::File F1(CurrentOUIFileName_);
if(F1.exists()) if (F1.exists())
F1.remove(); F1.remove();
Poco::File F2(LatestOUIFileName_); Poco::File F2(LatestOUIFileName_);
F2.renameTo(CurrentOUIFileName_); F2.renameTo(CurrentOUIFileName_);
poco_information(Logger(), fmt::format("New OUI file {} downloaded.",LatestOUIFileName_)); poco_information(Logger(),
} else if(OUIs_.empty()) { fmt::format("New OUI file {} downloaded.", LatestOUIFileName_));
if(ProcessFile(CurrentOUIFileName_, TmpOUIs)) { } else if (OUIs_.empty()) {
if (ProcessFile(CurrentOUIFileName_, TmpOUIs)) {
LastUpdate_ = Utils::Now(); LastUpdate_ = Utils::Now();
std::unique_lock G(LocalMutex_); std::unique_lock G(LocalMutex_);
OUIs_ = std::move(TmpOUIs); OUIs_ = std::move(TmpOUIs);
} }
} }
Initialized_=true; Initialized_ = true;
Updating_ = false; Updating_ = false;
poco_information(Logger(),"Done processing OUI file..."); poco_information(Logger(), "Done processing OUI file...");
} }
std::string OUIServer::GetManufacturer(const std::string &MAC) { std::string OUIServer::GetManufacturer(const std::string &MAC) {
std::shared_lock Lock(LocalMutex_); std::shared_lock Lock(LocalMutex_);
auto Manufacturer = OUIs_.find(Utils::SerialNumberToOUI(MAC)); auto Manufacturer = OUIs_.find(Utils::SerialNumberToOUI(MAC));
if(Manufacturer != OUIs_.end()) if (Manufacturer != OUIs_.end())
return Manufacturer->second; return Manufacturer->second;
return ""; return "";
} }
}; }; // namespace OpenWifi

View File

@@ -14,18 +14,17 @@ namespace OpenWifi {
class OUIServer : public SubSystemServer { class OUIServer : public SubSystemServer {
public: public:
typedef std::map<uint64_t, std::string> OUIMap;
typedef std::map<uint64_t,std::string> OUIMap;
static auto instance() { static auto instance() {
static auto instance_ = new OUIServer; static auto instance_ = new OUIServer;
return instance_; return instance_;
} }
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void onTimer(Poco::Timer & timer); void onTimer(Poco::Timer &timer);
void reinitialize(Poco::Util::Application &self) override; void reinitialize(Poco::Util::Application &self) override;
[[nodiscard]] std::string GetManufacturer(const std::string &MAC); [[nodiscard]] std::string GetManufacturer(const std::string &MAC);
@@ -33,23 +32,19 @@ namespace OpenWifi {
[[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map); [[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map);
private: private:
std::shared_mutex LocalMutex_; std::shared_mutex LocalMutex_;
uint64_t LastUpdate_ = 0 ; uint64_t LastUpdate_ = 0;
bool Initialized_ = false; bool Initialized_ = false;
OUIMap OUIs_; OUIMap OUIs_;
volatile std::atomic_bool Updating_=false; volatile std::atomic_bool Updating_ = false;
volatile std::atomic_bool Running_=false; volatile std::atomic_bool Running_ = false;
Poco::Timer Timer_; Poco::Timer Timer_;
std::unique_ptr<Poco::TimerCallback<OUIServer>> UpdaterCallBack_; std::unique_ptr<Poco::TimerCallback<OUIServer>> UpdaterCallBack_;
std::string LatestOUIFileName_,CurrentOUIFileName_; std::string LatestOUIFileName_, CurrentOUIFileName_;
OUIServer() noexcept: OUIServer() noexcept : SubSystemServer("OUIServer", "OUI-SVR", "ouiserver") {}
SubSystemServer("OUIServer", "OUI-SVR", "ouiserver")
{
}
}; };
inline auto OUIServer() { return OUIServer::instance(); } inline auto OUIServer() { return OUIServer::instance(); }
} } // namespace OpenWifi

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,85 +4,108 @@
#include "Poco/JSON/Parser.h" #include "Poco/JSON/Parser.h"
#include "RADIUS_proxy_server.h"
#include "RADIUS_helpers.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "RADIUS_helpers.h"
#include "RADIUS_proxy_server.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
namespace OpenWifi { namespace OpenWifi {
const int SMALLEST_RADIUS_PACKET = 20+19+4; const int SMALLEST_RADIUS_PACKET = 20 + 19 + 4;
const int DEFAULT_RADIUS_AUTHENTICATION_PORT = 1812; const int DEFAULT_RADIUS_AUTHENTICATION_PORT = 1812;
const int DEFAULT_RADIUS_ACCOUNTING_PORT = 1813; const int DEFAULT_RADIUS_ACCOUNTING_PORT = 1813;
const int DEFAULT_RADIUS_CoA_PORT = 3799; const int DEFAULT_RADIUS_CoA_PORT = 3799;
int RADIUS_proxy_server::Start() { int RADIUS_proxy_server::Start() {
ConfigFilename_ = MicroServiceDataDirectory()+"/radius_pool_config.json"; ConfigFilename_ = MicroServiceDataDirectory() + "/radius_pool_config.json";
Poco::File Config(ConfigFilename_); Poco::File Config(ConfigFilename_);
Enabled_ = MicroServiceConfigGetBool("radius.proxy.enable",false); Enabled_ = MicroServiceConfigGetBool("radius.proxy.enable", false);
if(!Enabled_ && !Config.exists()) { if (!Enabled_ && !Config.exists()) {
StopRADSECServers(); StopRADSECServers();
return 0; return 0;
} }
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
Enabled_ = true; Enabled_ = true;
Poco::Net::SocketAddress AuthSockAddrV4(Poco::Net::AddressFamily::IPv4, Poco::Net::SocketAddress AuthSockAddrV4(
MicroServiceConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT)); Poco::Net::AddressFamily::IPv4,
AuthenticationSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4,true,true); MicroServiceConfigGetInt("radius.proxy.authentication.port",
Poco::Net::SocketAddress AuthSockAddrV6(Poco::Net::AddressFamily::IPv6, DEFAULT_RADIUS_AUTHENTICATION_PORT));
MicroServiceConfigGetInt("radius.proxy.authentication.port",DEFAULT_RADIUS_AUTHENTICATION_PORT)); AuthenticationSocketV4_ =
AuthenticationSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6,true,true); std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV4, true, true);
Poco::Net::SocketAddress AuthSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.authentication.port",
DEFAULT_RADIUS_AUTHENTICATION_PORT));
AuthenticationSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AuthSockAddrV6, true, true);
Poco::Net::SocketAddress AcctSockAddrV4(Poco::Net::AddressFamily::IPv4, Poco::Net::SocketAddress AcctSockAddrV4(
MicroServiceConfigGetInt("radius.proxy.accounting.port",DEFAULT_RADIUS_ACCOUNTING_PORT)); Poco::Net::AddressFamily::IPv4,
AccountingSocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4,true,true); MicroServiceConfigGetInt("radius.proxy.accounting.port",
Poco::Net::SocketAddress AcctSockAddrV6(Poco::Net::AddressFamily::IPv6, DEFAULT_RADIUS_ACCOUNTING_PORT));
MicroServiceConfigGetInt("radius.proxy.accounting.port",DEFAULT_RADIUS_ACCOUNTING_PORT)); AccountingSocketV4_ =
AccountingSocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6,true,true); std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV4, true, true);
Poco::Net::SocketAddress AcctSockAddrV6(
Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.accounting.port",
DEFAULT_RADIUS_ACCOUNTING_PORT));
AccountingSocketV6_ =
std::make_unique<Poco::Net::DatagramSocket>(AcctSockAddrV6, true, true);
Poco::Net::SocketAddress CoASockAddrV4(Poco::Net::AddressFamily::IPv4, Poco::Net::SocketAddress CoASockAddrV4(
MicroServiceConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT)); Poco::Net::AddressFamily::IPv4,
CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4,true,true); MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
Poco::Net::SocketAddress CoASockAddrV6(Poco::Net::AddressFamily::IPv6, CoASocketV4_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV4, true, true);
MicroServiceConfigGetInt("radius.proxy.coa.port",DEFAULT_RADIUS_CoA_PORT)); Poco::Net::SocketAddress CoASockAddrV6(
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6,true,true); Poco::Net::AddressFamily::IPv6,
MicroServiceConfigGetInt("radius.proxy.coa.port", DEFAULT_RADIUS_CoA_PORT));
CoASocketV6_ = std::make_unique<Poco::Net::DatagramSocket>(CoASockAddrV6, true, true);
RadiusReactor_.reset(); RadiusReactor_.reset();
RadiusReactor_ = std::make_unique<Poco::Net::SocketReactor>(); RadiusReactor_ = std::make_unique<Poco::Net::SocketReactor>();
RadiusReactor_->addEventHandler(*AuthenticationSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_->addEventHandler(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *AuthenticationSocketV4_,
RadiusReactor_->addEventHandler(*AuthenticationSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable)); *this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->addEventHandler(
*AuthenticationSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAuthenticationSocketReadable));
RadiusReactor_->addEventHandler(*AccountingSocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_->addEventHandler(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *AccountingSocketV4_,
RadiusReactor_->addEventHandler(*AccountingSocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable)); *this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->addEventHandler(
*AccountingSocketV6_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnAccountingSocketReadable));
RadiusReactor_->addEventHandler(
RadiusReactor_->addEventHandler(*CoASocketV4_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( *CoASocketV4_, Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable)); *this, &RADIUS_proxy_server::OnCoASocketReadable));
RadiusReactor_->addEventHandler(*CoASocketV6_,Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( RadiusReactor_->addEventHandler(
*this, &RADIUS_proxy_server::OnCoASocketReadable)); *CoASocketV6_, Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
*this, &RADIUS_proxy_server::OnCoASocketReadable));
ParseConfig(); ParseConfig();
StartRADSECServers(); StartRADSECServers();
RadiusReactorThread_.start(*RadiusReactor_); RadiusReactorThread_.start(*RadiusReactor_);
Utils::SetThreadName(RadiusReactorThread_,"rad:reactor"); Utils::SetThreadName(RadiusReactorThread_, "rad:reactor");
Running_ = true; Running_ = true;
return 0; return 0;
} }
void RADIUS_proxy_server::Stop() { void RADIUS_proxy_server::Stop() {
if(Enabled_ && Running_) { if (Enabled_ && Running_) {
poco_information(Logger(),"Stopping..."); poco_information(Logger(), "Stopping...");
RadiusReactor_->removeEventHandler( RadiusReactor_->removeEventHandler(
*AuthenticationSocketV4_, *AuthenticationSocketV4_,
Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>( Poco::NObserver<RADIUS_proxy_server, Poco::Net::ReadableNotification>(
@@ -127,96 +150,112 @@ namespace OpenWifi {
StopRADSECServers(); StopRADSECServers();
RadiusReactor_->stop(); RadiusReactor_->stop();
RadiusReactorThread_.join(); RadiusReactorThread_.join();
Running_=false; Running_ = false;
poco_information(Logger(),"Stopped..."); poco_information(Logger(), "Stopped...");
} }
} }
void RADIUS_proxy_server::StartRADSECServers() { void RADIUS_proxy_server::StartRADSECServers() {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
for(const auto &pool:PoolList_.pools) { for (const auto &pool : PoolList_.pools) {
for(const auto &entry:pool.authConfig.servers) { for (const auto &entry : pool.authConfig.servers) {
if(entry.radsec) { if (entry.radsec) {
RADSECservers_[ Poco::Net::SocketAddress(entry.ip,0) ] = std::make_unique<RADSEC_server>(*RadiusReactor_,entry); RADSECservers_[Poco::Net::SocketAddress(entry.ip, 0)] =
std::make_unique<RADSEC_server>(*RadiusReactor_, entry);
} }
} }
} }
} }
void RADIUS_proxy_server::StopRADSECServers() { void RADIUS_proxy_server::StopRADSECServers() {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
RADSECservers_.clear(); RADSECservers_.clear();
} }
void RADIUS_proxy_server::OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { void RADIUS_proxy_server::OnAccountingSocketReadable(
Poco::Net::SocketAddress Sender; const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
RADIUS::RadiusPacket P; Poco::Net::SocketAddress Sender;
RADIUS::RadiusPacket P;
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
poco_warning(Logger(),"Accounting: bad packet received."); poco_warning(Logger(), "Accounting: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(SerialNumber.empty()) { if (SerialNumber.empty()) {
poco_warning(Logger(),"Accounting: missing serial number."); poco_warning(Logger(), "Accounting: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
poco_debug(Logger(), fmt::format("Accounting Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_debug(
AP_WS_Server()->SendRadiusAccountingData(SerialNumber,P.Buffer(),P.Size()); Logger(),
fmt::format(
"Accounting Packet received for {}, CalledStationID: {}, CallingStationID:{}",
SerialNumber, CalledStationID, CallingStationID));
AP_WS_Server()->SendRadiusAccountingData(SerialNumber, P.Buffer(), P.Size());
} }
void RADIUS_proxy_server::OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { void RADIUS_proxy_server::OnAuthenticationSocketReadable(
Poco::Net::SocketAddress Sender; const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
RADIUS::RadiusPacket P; Poco::Net::SocketAddress Sender;
RADIUS::RadiusPacket P;
auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
poco_warning(Logger(),"Authentication: bad packet received."); poco_warning(Logger(), "Authentication: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(SerialNumber.empty()) { if (SerialNumber.empty()) {
poco_warning(Logger(),"Authentication: missing serial number."); poco_warning(Logger(), "Authentication: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
poco_debug(Logger(), fmt::format("Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_debug(
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber,P.Buffer(),P.Size()); Logger(),
fmt::format(
"Authentication Packet received for {}, CalledStationID: {}, CallingStationID:{}",
SerialNumber, CalledStationID, CallingStationID));
AP_WS_Server()->SendRadiusAuthenticationData(SerialNumber, P.Buffer(), P.Size());
} }
void RADIUS_proxy_server::OnCoASocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { void RADIUS_proxy_server::OnCoASocketReadable(
Poco::Net::SocketAddress Sender; const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
RADIUS::RadiusPacket P; Poco::Net::SocketAddress Sender;
RADIUS::RadiusPacket P;
auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(),P.BufferLen()); auto ReceiveSize = pNf.get()->socket().impl()->receiveBytes(P.Buffer(), P.BufferLen());
if(ReceiveSize<SMALLEST_RADIUS_PACKET) { if (ReceiveSize < SMALLEST_RADIUS_PACKET) {
poco_warning(Logger(),"CoA/DM: bad packet received."); poco_warning(Logger(), "CoA/DM: bad packet received.");
return; return;
} }
P.Evaluate(ReceiveSize); P.Evaluate(ReceiveSize);
auto SerialNumber = P.ExtractSerialNumberTIP(); auto SerialNumber = P.ExtractSerialNumberTIP();
if(SerialNumber.empty()) { if (SerialNumber.empty()) {
poco_warning(Logger(),"CoA/DM: missing serial number."); poco_warning(Logger(), "CoA/DM: missing serial number.");
return; return;
} }
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
poco_debug(Logger(), fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",SerialNumber, CalledStationID, CallingStationID)); poco_debug(
AP_WS_Server()->SendRadiusCoAData(SerialNumber,P.Buffer(),P.Size()); Logger(),
fmt::format("CoA Packet received for {}, CalledStationID: {}, CallingStationID:{}",
SerialNumber, CalledStationID, CallingStationID));
AP_WS_Server()->SendRadiusCoAData(SerialNumber, P.Buffer(), P.Size());
} }
void RADIUS_proxy_server::SendAccountingData(const std::string &serialNumber, const char *buffer, std::size_t size) { void RADIUS_proxy_server::SendAccountingData(const std::string &serialNumber,
const char *buffer, std::size_t size) {
if(!Continue()) if (!Continue())
return; return;
try { try {
@@ -257,41 +296,46 @@ namespace OpenWifi {
fmt::format("{}: Could not send Accounting packet packet to {}.", fmt::format("{}: Could not send Accounting packet packet to {}.",
serialNumber, Destination)); serialNumber, Destination));
else else
poco_debug(Logger(), fmt::format("{}: Sending Accounting Packet to {}, CalledStationID: {}, CallingStationID:{}", poco_debug(Logger(), fmt::format("{}: Sending Accounting Packet to {}, "
"CalledStationID: {}, CallingStationID:{}",
serialNumber, FinalDestination.toString(), serialNumber, FinalDestination.toString(),
CalledStationID, CallingStationID)); CalledStationID, CallingStationID));
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_warning(Logger(),fmt::format("Bad RADIUS ACCT Packet from {}. Dropped.",serialNumber)); poco_warning(Logger(),
fmt::format("Bad RADIUS ACCT Packet from {}. Dropped.", serialNumber));
} }
} }
bool RADIUS_proxy_server::SendData( Poco::Net::DatagramSocket & Sock, const unsigned char *buf , std::size_t size, const Poco::Net::SocketAddress &S) { bool RADIUS_proxy_server::SendData(Poco::Net::DatagramSocket &Sock, const unsigned char *buf,
return Sock.sendTo(buf, size, S)==(int)size; std::size_t size, const Poco::Net::SocketAddress &S) {
return Sock.sendTo(buf, size, S) == (int)size;
} }
void RADIUS_proxy_server::SendAuthenticationData(const std::string &serialNumber, const char *buffer, std::size_t size) { void RADIUS_proxy_server::SendAuthenticationData(const std::string &serialNumber,
const char *buffer, std::size_t size) {
if(!Continue()) if (!Continue())
return; return;
try { try {
RADIUS::RadiusPacket P((unsigned char *)buffer,size); RADIUS::RadiusPacket P((unsigned char *)buffer, size);
auto Destination = P.ExtractProxyStateDestination(); auto Destination = P.ExtractProxyStateDestination();
auto CallingStationID = P.ExtractCallingStationID(); auto CallingStationID = P.ExtractCallingStationID();
auto CalledStationID = P.ExtractCalledStationID(); auto CalledStationID = P.ExtractCalledStationID();
Poco::Net::SocketAddress Dst(Destination); Poco::Net::SocketAddress Dst(Destination);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
bool UseRADSEC = false; bool UseRADSEC = false;
auto FinalDestination = Route(radius_type::auth, Dst, P, UseRADSEC); auto FinalDestination = Route(radius_type::auth, Dst, P, UseRADSEC);
if(UseRADSEC) { if (UseRADSEC) {
Poco::Net::SocketAddress RSP(FinalDestination.host(),0); Poco::Net::SocketAddress RSP(FinalDestination.host(), 0);
auto DestinationServer = RADSECservers_.find(RSP); auto DestinationServer = RADSECservers_.find(RSP);
if(DestinationServer!=end(RADSECservers_)) { if (DestinationServer != end(RADSECservers_)) {
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer, size); DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer,
size);
} }
} else { } else {
if ((Dst.family() == Poco::Net::SocketAddress::IPv4 && if ((Dst.family() == Poco::Net::SocketAddress::IPv4 &&
@@ -300,66 +344,74 @@ namespace OpenWifi {
AuthenticationSocketV6_ == nullptr)) { AuthenticationSocketV6_ == nullptr)) {
poco_debug( poco_debug(
Logger(), Logger(),
fmt::format("AUTH: Trying to use RADIUS GW PROXY but not configured. Device={}", fmt::format(
serialNumber)); "AUTH: Trying to use RADIUS GW PROXY but not configured. Device={}",
serialNumber));
return; return;
} }
auto AllSent = auto AllSent = SendData(Dst.family() == Poco::Net::SocketAddress::IPv4
SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *AuthenticationSocketV4_ ? *AuthenticationSocketV4_
: *AuthenticationSocketV6_, : *AuthenticationSocketV6_,
(const unsigned char *)buffer, size, FinalDestination); (const unsigned char *)buffer, size, FinalDestination);
if (!AllSent) if (!AllSent)
poco_error(Logger(), poco_error(Logger(),
fmt::format("{}: Could not send Authentication packet packet to {}.", fmt::format("{}: Could not send Authentication packet packet to {}.",
serialNumber, Destination)); serialNumber, Destination));
else else
poco_debug(Logger(), fmt::format("{}: Sending Authentication Packet to {}, CalledStationID: {}, CallingStationID:{}", poco_debug(Logger(), fmt::format("{}: Sending Authentication Packet to {}, "
"CalledStationID: {}, CallingStationID:{}",
serialNumber, FinalDestination.toString(), serialNumber, FinalDestination.toString(),
CalledStationID, CallingStationID)); CalledStationID, CallingStationID));
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_warning(Logger(),fmt::format("Bad RADIUS AUTH Packet from {}. Dropped.",serialNumber)); poco_warning(Logger(),
fmt::format("Bad RADIUS AUTH Packet from {}. Dropped.", serialNumber));
} }
} }
void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size) { void RADIUS_proxy_server::SendCoAData(const std::string &serialNumber, const char *buffer,
std::size_t size) {
if(!Continue()) if (!Continue())
return; return;
try { try {
RADIUS::RadiusPacket P((unsigned char *)buffer,size); RADIUS::RadiusPacket P((unsigned char *)buffer, size);
auto Destination = P.ExtractProxyStateDestination(); auto Destination = P.ExtractProxyStateDestination();
if(Destination.empty()) { if (Destination.empty()) {
Destination = "0.0.0.0:0"; Destination = "0.0.0.0:0";
} }
Poco::Net::SocketAddress Dst(Destination); Poco::Net::SocketAddress Dst(Destination);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
bool UseRADSEC = false; bool UseRADSEC = false;
auto FinalDestination = Route(radius_type::coa, Dst, P, UseRADSEC); auto FinalDestination = Route(radius_type::coa, Dst, P, UseRADSEC);
if(UseRADSEC) { if (UseRADSEC) {
Poco::Net::SocketAddress RSP(FinalDestination.host(),0); Poco::Net::SocketAddress RSP(FinalDestination.host(), 0);
auto DestinationServer = RADSECservers_.find(RSP); auto DestinationServer = RADSECservers_.find(RSP);
if(DestinationServer!=end(RADSECservers_)) { if (DestinationServer != end(RADSECservers_)) {
DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer, size); DestinationServer->second->SendData(serialNumber, (const unsigned char *)buffer,
size);
} }
} else { } else {
if( (Dst.family() == Poco::Net::SocketAddress::IPv4 && CoASocketV4_== nullptr) || if ((Dst.family() == Poco::Net::SocketAddress::IPv4 && CoASocketV4_ == nullptr) ||
(Dst.family() == Poco::Net::SocketAddress::IPv6 && CoASocketV6_== nullptr)) { (Dst.family() == Poco::Net::SocketAddress::IPv6 && CoASocketV6_ == nullptr)) {
poco_debug(Logger(),fmt::format("CoA: Trying to use RADIUS GW PROXY but not configured. Device={}",serialNumber)); poco_debug(
Logger(),
fmt::format(
"CoA: Trying to use RADIUS GW PROXY but not configured. Device={}",
serialNumber));
return; return;
} }
auto AllSent = SendData(Dst.family() == Poco::Net::SocketAddress::IPv4 ? *CoASocketV4_ auto AllSent = SendData(
: *CoASocketV6_, Dst.family() == Poco::Net::SocketAddress::IPv4 ? *CoASocketV4_ : *CoASocketV6_,
(const unsigned char *)buffer, size, FinalDestination); (const unsigned char *)buffer, size, FinalDestination);
if (!AllSent) if (!AllSent)
poco_error(Logger(),fmt::format("{}: Could not send CoA packet packet to {}.", poco_error(Logger(), fmt::format("{}: Could not send CoA packet packet to {}.",
serialNumber, Destination)); serialNumber, Destination));
else else
poco_debug(Logger(), fmt::format("{}: Sending CoA Packet to {}", serialNumber, poco_debug(Logger(), fmt::format("{}: Sending CoA Packet to {}", serialNumber,
FinalDestination.toString())); FinalDestination.toString()));
@@ -367,39 +419,42 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_warning(Logger(),fmt::format("Bad RADIUS CoA/DM Packet from {}. Dropped.",serialNumber)); poco_warning(Logger(),
fmt::format("Bad RADIUS CoA/DM Packet from {}. Dropped.", serialNumber));
} }
} }
void RADIUS_proxy_server::ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault) { void RADIUS_proxy_server::ParseServerList(const GWObjects::RadiusProxyServerConfig &Config,
uint64_t TotalV4=0, TotalV6=0; std::vector<Destination> &V4,
std::vector<Destination> &V6, bool setAsDefault) {
uint64_t TotalV4 = 0, TotalV6 = 0;
for(const auto &server:Config.servers) { for (const auto &server : Config.servers) {
Poco::Net::IPAddress a; Poco::Net::IPAddress a;
if(!Poco::Net::IPAddress::tryParse(server.ip,a)) { if (!Poco::Net::IPAddress::tryParse(server.ip, a)) {
poco_error(Logger(),fmt::format("RADIUS-PARSE Config: server address {} is nto a valid address in v4 or v6. Entry skipped.",server.ip)); poco_error(Logger(), fmt::format("RADIUS-PARSE Config: server address {} is nto a "
"valid address in v4 or v6. Entry skipped.",
server.ip));
continue; continue;
} }
auto S = Poco::Net::SocketAddress(fmt::format("{}:{}",server.ip,server.port)); auto S = Poco::Net::SocketAddress(fmt::format("{}:{}", server.ip, server.port));
Destination D{ Destination D{.Addr = S,
.Addr = S, .state = 0,
.state = 0, .step = 0,
.step = 0, .weight = server.weight,
.weight = server.weight, .available = true,
.available = true, .strategy = Config.strategy,
.strategy = Config.strategy, .monitor = Config.monitor,
.monitor = Config. monitor, .monitorMethod = Config.monitorMethod,
.monitorMethod = Config.monitorMethod, .methodParameters = Config.methodParameters,
.methodParameters = Config.methodParameters, .useAsDefault = setAsDefault,
.useAsDefault = setAsDefault, .useRADSEC = server.radsec,
.useRADSEC = server.radsec, .realms = server.radsecRealms};
.realms = server.radsecRealms
};
if(setAsDefault && D.useRADSEC) if (setAsDefault && D.useRADSEC)
DefaultIsRADSEC_ = true; DefaultIsRADSEC_ = true;
if(S.family()==Poco::Net::IPAddress::IPv4) { if (S.family() == Poco::Net::IPAddress::IPv4) {
TotalV4 += server.weight; TotalV4 += server.weight;
V4.push_back(D); V4.push_back(D);
} else { } else {
@@ -408,16 +463,16 @@ namespace OpenWifi {
} }
} }
for(auto &i:V4) { for (auto &i : V4) {
if(TotalV4==0) { if (TotalV4 == 0) {
i.step = 1000; i.step = 1000;
} else { } else {
i.step = 1000 - ((1000 * i.weight) / TotalV4); i.step = 1000 - ((1000 * i.weight) / TotalV4);
} }
} }
for(auto &i:V6) { for (auto &i : V6) {
if(TotalV6==0) { if (TotalV6 == 0) {
i.step = 1000; i.step = 1000;
} else { } else {
i.step = 1000 - ((1000 * i.weight) / TotalV6); i.step = 1000 - ((1000 * i.weight) / TotalV6);
@@ -428,59 +483,68 @@ namespace OpenWifi {
void RADIUS_proxy_server::ParseConfig() { void RADIUS_proxy_server::ParseConfig() {
try { try {
Poco::File F(ConfigFilename_); Poco::File F(ConfigFilename_);
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if(F.exists()) { if (F.exists()) {
std::ifstream ifs(ConfigFilename_,std::ios_base::binary); std::ifstream ifs(ConfigFilename_, std::ios_base::binary);
Poco::JSON::Parser P; Poco::JSON::Parser P;
auto RawConfig = P.parse(ifs).extract<Poco::JSON::Object::Ptr>(); auto RawConfig = P.parse(ifs).extract<Poco::JSON::Object::Ptr>();
GWObjects::RadiusProxyPoolList RPC; GWObjects::RadiusProxyPoolList RPC;
if(RPC.from_json(RawConfig)) { if (RPC.from_json(RawConfig)) {
ResetConfig(); ResetConfig();
PoolList_ = RPC; PoolList_ = RPC;
for(const auto &pool:RPC.pools) { for (const auto &pool : RPC.pools) {
RadiusPool NewPool; RadiusPool NewPool;
ParseServerList(pool.authConfig, NewPool.AuthV4, NewPool.AuthV6, pool.useByDefault); ParseServerList(pool.authConfig, NewPool.AuthV4, NewPool.AuthV6,
ParseServerList(pool.acctConfig, NewPool.AcctV4, NewPool.AcctV6, pool.useByDefault); pool.useByDefault);
ParseServerList(pool.coaConfig, NewPool.CoaV4, NewPool.CoaV6, pool.useByDefault); ParseServerList(pool.acctConfig, NewPool.AcctV4, NewPool.AcctV6,
pool.useByDefault);
ParseServerList(pool.coaConfig, NewPool.CoaV4, NewPool.CoaV6,
pool.useByDefault);
Pools_.push_back(NewPool); Pools_.push_back(NewPool);
} }
} else { } else {
poco_warning(Logger(),fmt::format("Configuration file '{}' is bad.",ConfigFilename_)); poco_warning(Logger(),
fmt::format("Configuration file '{}' is bad.", ConfigFilename_));
} }
} else { } else {
poco_warning(Logger(),fmt::format("No configuration file '{}' exists.",ConfigFilename_)); poco_warning(Logger(),
fmt::format("No configuration file '{}' exists.", ConfigFilename_));
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_error(Logger(),fmt::format("Error while parsing configuration file '{}'",ConfigFilename_)); poco_error(Logger(),
fmt::format("Error while parsing configuration file '{}'", ConfigFilename_));
} }
} }
static bool RealmMatch(const std::string &user_realm, const std::string & realm) { static bool RealmMatch(const std::string &user_realm, const std::string &realm) {
if(realm.find_first_of('*') == std::string::npos) if (realm.find_first_of('*') == std::string::npos)
return user_realm == realm; return user_realm == realm;
return realm.find(user_realm) != std::string::npos; return realm.find(user_realm) != std::string::npos;
} }
Poco::Net::SocketAddress RADIUS_proxy_server::DefaultRoute(radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC) { Poco::Net::SocketAddress
bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4; RADIUS_proxy_server::DefaultRoute(radius_type rtype,
const Poco::Net::SocketAddress &RequestedAddress,
const RADIUS::RadiusPacket &P, bool &UseRADSEC) {
bool IsV4 = RequestedAddress.family() == Poco::Net::SocketAddress::IPv4;
// find the realm... // find the realm...
auto UserName = P.UserName(); auto UserName = P.UserName();
if(!UserName.empty()) { if (!UserName.empty()) {
auto UserTokens = Poco::StringTokenizer(UserName, "@"); auto UserTokens = Poco::StringTokenizer(UserName, "@");
auto UserRealm = ((UserTokens.count() > 1) ? UserTokens[1] : UserName); auto UserRealm = ((UserTokens.count() > 1) ? UserTokens[1] : UserName);
Poco::toLowerInPlace(UserRealm); Poco::toLowerInPlace(UserRealm);
for(const auto &pool:Pools_) { for (const auto &pool : Pools_) {
for(const auto &server:pool.AuthV4) { for (const auto &server : pool.AuthV4) {
if(!server.realms.empty()) { if (!server.realms.empty()) {
for(const auto &realm:server.realms) { for (const auto &realm : server.realms) {
if (RealmMatch(UserRealm,realm)) { if (RealmMatch(UserRealm, realm)) {
std::cout << "Realm match..." << std::endl; std::cout << "Realm match..." << std::endl;
UseRADSEC = true; UseRADSEC = true;
return server.Addr; return server.Addr;
@@ -491,58 +555,65 @@ namespace OpenWifi {
} }
} }
if(DefaultIsRADSEC_) { if (DefaultIsRADSEC_) {
UseRADSEC = true; UseRADSEC = true;
return (IsV4 ? Pools_[DefaultPoolIndex_].AuthV4[0].Addr : Pools_[DefaultPoolIndex_].AuthV6[0].Addr ); return (IsV4 ? Pools_[DefaultPoolIndex_].AuthV4[0].Addr
: Pools_[DefaultPoolIndex_].AuthV6[0].Addr);
} }
switch(rtype) { switch (rtype) {
case radius_type::auth: { case radius_type::auth: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AuthV4 return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AuthV4
: Pools_[DefaultPoolIndex_].AuthV6, : Pools_[DefaultPoolIndex_].AuthV6,
RequestedAddress); RequestedAddress);
} }
case radius_type::acct: case radius_type::acct:
default: { default: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AcctV4 return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].AcctV4
: Pools_[DefaultPoolIndex_].AcctV6, : Pools_[DefaultPoolIndex_].AcctV6,
RequestedAddress); RequestedAddress);
} }
case radius_type::coa: { case radius_type::coa: {
return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4 return ChooseAddress(IsV4 ? Pools_[DefaultPoolIndex_].CoaV4
: Pools_[DefaultPoolIndex_].CoaV6, : Pools_[DefaultPoolIndex_].CoaV6,
RequestedAddress); RequestedAddress);
} }
} }
} }
Poco::Net::SocketAddress RADIUS_proxy_server::Route([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC) { Poco::Net::SocketAddress
std::lock_guard G(Mutex_); RADIUS_proxy_server::Route([[maybe_unused]] radius_type rtype,
const Poco::Net::SocketAddress &RequestedAddress,
const RADIUS::RadiusPacket &P, bool &UseRADSEC) {
std::lock_guard G(Mutex_);
if(Pools_.empty()) { if (Pools_.empty()) {
UseRADSEC = false; UseRADSEC = false;
return RequestedAddress; return RequestedAddress;
} }
bool IsV4 = RequestedAddress.family()==Poco::Net::SocketAddress::IPv4; bool IsV4 = RequestedAddress.family() == Poco::Net::SocketAddress::IPv4;
bool useDefault; bool useDefault;
useDefault = IsV4 ? RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv4) : RequestedAddress.host() == Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv6) ; useDefault = IsV4 ? RequestedAddress.host() ==
Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv4)
: RequestedAddress.host() ==
Poco::Net::IPAddress::wildcard(Poco::Net::IPAddress::IPv6);
if(useDefault) { if (useDefault) {
return DefaultRoute(rtype, RequestedAddress, P, UseRADSEC); return DefaultRoute(rtype, RequestedAddress, P, UseRADSEC);
} }
auto isAddressInPool = [&](const std::vector<Destination> & D, bool &UseRADSEC) -> bool { auto isAddressInPool = [&](const std::vector<Destination> &D, bool &UseRADSEC) -> bool {
for(const auto &entry:D) for (const auto &entry : D)
if(entry.Addr.host()==RequestedAddress.host()) { if (entry.Addr.host() == RequestedAddress.host()) {
UseRADSEC = entry.useRADSEC; UseRADSEC = entry.useRADSEC;
return true; return true;
} }
return false; return false;
}; };
for(auto &i:Pools_) { for (auto &i : Pools_) {
switch(rtype) { switch (rtype) {
case radius_type::coa: { case radius_type::coa: {
if (isAddressInPool((IsV4 ? i.CoaV4 : i.CoaV6), UseRADSEC)) { if (isAddressInPool((IsV4 ? i.CoaV4 : i.CoaV6), UseRADSEC)) {
return ChooseAddress(IsV4 ? i.CoaV4 : i.CoaV6, RequestedAddress); return ChooseAddress(IsV4 ? i.CoaV4 : i.CoaV6, RequestedAddress);
@@ -565,9 +636,11 @@ namespace OpenWifi {
return RequestedAddress; return RequestedAddress;
} }
Poco::Net::SocketAddress RADIUS_proxy_server::ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress) { Poco::Net::SocketAddress
RADIUS_proxy_server::ChooseAddress(std::vector<Destination> &Pool,
const Poco::Net::SocketAddress &OriginalAddress) {
if(Pool.size()==1) { if (Pool.size() == 1) {
return Pool[0].Addr; return Pool[0].Addr;
} }
@@ -628,12 +701,12 @@ namespace OpenWifi {
} }
void RADIUS_proxy_server::SetConfig(const GWObjects::RadiusProxyPoolList &C) { void RADIUS_proxy_server::SetConfig(const GWObjects::RadiusProxyPoolList &C) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Poco::JSON::Object Disk; Poco::JSON::Object Disk;
C.to_json(Disk); C.to_json(Disk);
std::ofstream ofs(ConfigFilename_, std::ios_base::trunc | std::ios_base::binary ); std::ofstream ofs(ConfigFilename_, std::ios_base::trunc | std::ios_base::binary);
Disk.stringify(ofs); Disk.stringify(ofs);
ofs.close(); ofs.close();
@@ -646,27 +719,26 @@ namespace OpenWifi {
void RADIUS_proxy_server::ResetConfig() { void RADIUS_proxy_server::ResetConfig() {
PoolList_.pools.clear(); PoolList_.pools.clear();
Pools_.clear(); Pools_.clear();
DefaultPoolIndex_=0; DefaultPoolIndex_ = 0;
DefaultIsRADSEC_=false; DefaultIsRADSEC_ = false;
} }
void RADIUS_proxy_server::DeleteConfig() { void RADIUS_proxy_server::DeleteConfig() {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
try { try {
Poco::File F(ConfigFilename_); Poco::File F(ConfigFilename_);
if (F.exists()) if (F.exists())
F.remove(); F.remove();
} catch (...) { } catch (...) {
} }
Stop(); Stop();
ResetConfig(); ResetConfig();
} }
void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) { void RADIUS_proxy_server::GetConfig(GWObjects::RadiusProxyPoolList &C) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
C = PoolList_; C = PoolList_;
} }
} } // namespace OpenWifi

View File

@@ -15,15 +15,12 @@
namespace OpenWifi { namespace OpenWifi {
enum class radius_type { enum class radius_type { auth, acct, coa };
auth, acct, coa
};
class RADIUS_proxy_server : public SubSystemServer { class RADIUS_proxy_server : public SubSystemServer {
public: public:
inline static auto instance() { inline static auto instance() {
static auto instance_= new RADIUS_proxy_server; static auto instance_ = new RADIUS_proxy_server;
return instance_; return instance_;
} }
@@ -31,12 +28,15 @@ namespace OpenWifi {
void Stop() final; void Stop() final;
inline bool Enabled() const { return Enabled_; } inline bool Enabled() const { return Enabled_; }
void OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf); void OnAccountingSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf); void
void OnCoASocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf); OnAuthenticationSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void OnCoASocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
void SendAccountingData(const std::string &serialNumber, const char *buffer, std::size_t size); void SendAccountingData(const std::string &serialNumber, const char *buffer,
void SendAuthenticationData(const std::string &serialNumber, const char *buffer, std::size_t size); std::size_t size);
void SendAuthenticationData(const std::string &serialNumber, const char *buffer,
std::size_t size);
void SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size); void SendCoAData(const std::string &serialNumber, const char *buffer, std::size_t size);
void SetConfig(const GWObjects::RadiusProxyPoolList &C); void SetConfig(const GWObjects::RadiusProxyPoolList &C);
@@ -47,70 +47,73 @@ namespace OpenWifi {
void StopRADSECServers(); void StopRADSECServers();
struct Destination { struct Destination {
Poco::Net::SocketAddress Addr; Poco::Net::SocketAddress Addr;
uint64_t state = 0; uint64_t state = 0;
uint64_t step = 0; uint64_t step = 0;
uint64_t weight=0; uint64_t weight = 0;
bool available = true; bool available = true;
std::string strategy; std::string strategy;
bool monitor=false; bool monitor = false;
std::string monitorMethod; std::string monitorMethod;
std::vector<std::string> methodParameters; std::vector<std::string> methodParameters;
bool useAsDefault=false; bool useAsDefault = false;
bool useRADSEC=false; bool useRADSEC = false;
std::vector<std::string> realms; std::vector<std::string> realms;
}; };
inline bool Continue() const { inline bool Continue() const { return Running_ && Enabled_ && !Pools_.empty(); }
return Running_ && Enabled_ && !Pools_.empty();
}
private: private:
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_; std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_; std::unique_ptr<Poco::Net::DatagramSocket> AccountingSocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV4_; std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_; std::unique_ptr<Poco::Net::DatagramSocket> AuthenticationSocketV6_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_; std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV4_;
std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_; std::unique_ptr<Poco::Net::DatagramSocket> CoASocketV6_;
std::unique_ptr<Poco::Net::SocketReactor> RadiusReactor_; std::unique_ptr<Poco::Net::SocketReactor> RadiusReactor_;
Poco::Thread RadiusReactorThread_; Poco::Thread RadiusReactorThread_;
GWObjects::RadiusProxyPoolList PoolList_; GWObjects::RadiusProxyPoolList PoolList_;
std::string ConfigFilename_; std::string ConfigFilename_;
std::map<Poco::Net::SocketAddress, std::unique_ptr<RADSEC_server>> RADSECservers_; std::map<Poco::Net::SocketAddress, std::unique_ptr<RADSEC_server>> RADSECservers_;
struct RadiusPool { struct RadiusPool {
std::vector<Destination> AuthV4; std::vector<Destination> AuthV4;
std::vector<Destination> AuthV6; std::vector<Destination> AuthV6;
std::vector<Destination> AcctV4; std::vector<Destination> AcctV4;
std::vector<Destination> AcctV6; std::vector<Destination> AcctV6;
std::vector<Destination> CoaV4; std::vector<Destination> CoaV4;
std::vector<Destination> CoaV6; std::vector<Destination> CoaV6;
}; };
std::vector<RadiusPool> Pools_; std::vector<RadiusPool> Pools_;
uint DefaultPoolIndex_=0; uint DefaultPoolIndex_ = 0;
bool Enabled_=false; bool Enabled_ = false;
bool DefaultIsRADSEC_=false; bool DefaultIsRADSEC_ = false;
std::atomic_bool Running_=false; std::atomic_bool Running_ = false;
RADIUS_proxy_server() noexcept: RADIUS_proxy_server() noexcept
SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy") : SubSystemServer("RADIUS-PROXY", "RADIUS-PROXY", "radius.proxy") {}
{
}
static bool SendData( Poco::Net::DatagramSocket & Sock, const unsigned char *buf , std::size_t size, const Poco::Net::SocketAddress &S); static bool SendData(Poco::Net::DatagramSocket &Sock, const unsigned char *buf,
std::size_t size, const Poco::Net::SocketAddress &S);
void ParseConfig(); void ParseConfig();
void ResetConfig(); void ResetConfig();
Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A, const RADIUS::RadiusPacket &P, bool &UseRADSEC); Poco::Net::SocketAddress Route(radius_type rtype, const Poco::Net::SocketAddress &A,
void ParseServerList(const GWObjects::RadiusProxyServerConfig & Config, std::vector<Destination> &V4, std::vector<Destination> &V6, bool setAsDefault); const RADIUS::RadiusPacket &P, bool &UseRADSEC);
static Poco::Net::SocketAddress ChooseAddress(std::vector<Destination> &Pool, const Poco::Net::SocketAddress & OriginalAddress); void ParseServerList(const GWObjects::RadiusProxyServerConfig &Config,
Poco::Net::SocketAddress DefaultRoute([[maybe_unused]] radius_type rtype, const Poco::Net::SocketAddress &RequestedAddress, const RADIUS::RadiusPacket &P, bool &UseRADSEC); std::vector<Destination> &V4, std::vector<Destination> &V6,
bool setAsDefault);
static Poco::Net::SocketAddress
ChooseAddress(std::vector<Destination> &Pool,
const Poco::Net::SocketAddress &OriginalAddress);
Poco::Net::SocketAddress DefaultRoute([[maybe_unused]] radius_type rtype,
const Poco::Net::SocketAddress &RequestedAddress,
const RADIUS::RadiusPacket &P, bool &UseRADSEC);
}; };
inline auto RADIUS_proxy_server() { return RADIUS_proxy_server::instance(); } inline auto RADIUS_proxy_server() { return RADIUS_proxy_server::instance(); }
} } // namespace OpenWifi

View File

@@ -4,42 +4,37 @@
#pragma once #pragma once
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include "RESTObjects/RESTAPI_GWobjects.h" #include "RESTObjects/RESTAPI_GWobjects.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/Context.h"
#include "Poco/Crypto/X509Certificate.h" #include "Poco/Crypto/X509Certificate.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/TemporaryFile.h" #include "Poco/TemporaryFile.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "RADIUS_helpers.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "RADIUS_helpers.h"
namespace OpenWifi { namespace OpenWifi {
class RADSEC_server : public Poco::Runnable { class RADSEC_server : public Poco::Runnable {
public: public:
RADSEC_server(Poco::Net::SocketReactor & R, GWObjects::RadiusProxyServerEntry E) : RADSEC_server(Poco::Net::SocketReactor &R, GWObjects::RadiusProxyServerEntry E)
Reactor_(R), : Reactor_(R), Server_(std::move(E)),
Server_(std::move(E)), Logger_(Poco::Logger::get(
Logger_(Poco::Logger::get(fmt::format("RADSEC: {}@{}:{}", fmt::format("RADSEC: {}@{}:{}", Server_.name, Server_.ip, Server_.port))) {
Server_.name ,
Server_.ip,
Server_.port))) {
Start(); Start();
} }
~RADSEC_server() { ~RADSEC_server() { Stop(); }
Stop();
}
inline int Start() { inline int Start() {
ReconnectThread_.start(*this); ReconnectThread_.start(*this);
@@ -55,17 +50,17 @@ namespace OpenWifi {
inline void run() final { inline void run() final {
Poco::Thread::trySleep(3000); Poco::Thread::trySleep(3000);
std::uint64_t LastStatus=0 ; std::uint64_t LastStatus = 0;
auto RadSecKeepAlive = MicroServiceConfigGetInt("radsec.keepalive",120); auto RadSecKeepAlive = MicroServiceConfigGetInt("radsec.keepalive", 120);
while(TryAgain_) { while (TryAgain_) {
if(!Connected_) { if (!Connected_) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
LastStatus = Utils::Now() ; LastStatus = Utils::Now();
Connect(); Connect();
} else if( (Utils::Now() - LastStatus) > RadSecKeepAlive) { } else if ((Utils::Now() - LastStatus) > RadSecKeepAlive) {
RADIUS::RadiusOutputPacket P(Server_.radsecSecret); RADIUS::RadiusOutputPacket P(Server_.radsecSecret);
P.MakeStatusMessage(); P.MakeStatusMessage();
poco_information(Logger_,"Keep-Alive message."); poco_information(Logger_, "Keep-Alive message.");
Socket_->sendBytes(P.Data(), P.Len()); Socket_->sendBytes(P.Data(), P.Len());
LastStatus = Utils::Now(); LastStatus = Utils::Now();
} }
@@ -73,7 +68,8 @@ namespace OpenWifi {
} }
} }
inline bool SendData(const std::string &serial_number, const unsigned char *buffer, int length) { inline bool SendData(const std::string &serial_number, const unsigned char *buffer,
int length) {
try { try {
if (Connected_) { if (Connected_) {
RADIUS::RadiusPacket P(buffer, length); RADIUS::RadiusPacket P(buffer, length);
@@ -93,21 +89,22 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
} catch (...) { } catch (...) {
poco_warning(Logger_,"Exception occurred: while sending data."); poco_warning(Logger_, "Exception occurred: while sending data.");
} }
return false; return false;
} }
inline void onData([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { inline void
onData([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
unsigned char Buffer[4096]; unsigned char Buffer[4096];
try { try {
auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer,sizeof(Buffer)); auto NumberOfReceivedBytes = Socket_->receiveBytes(Buffer, sizeof(Buffer));
if(NumberOfReceivedBytes>=20) { if (NumberOfReceivedBytes >= 20) {
RADIUS::RadiusPacket P(Buffer,NumberOfReceivedBytes); RADIUS::RadiusPacket P(Buffer, NumberOfReceivedBytes);
if (P.IsAuthentication()) { if (P.IsAuthentication()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(!SerialNumber.empty()) { if (!SerialNumber.empty()) {
poco_debug(Logger_, poco_debug(Logger_,
fmt::format("{}: {} Received {} bytes.", SerialNumber, fmt::format("{}: {} Received {} bytes.", SerialNumber,
P.PacketType(), NumberOfReceivedBytes)); P.PacketType(), NumberOfReceivedBytes));
@@ -118,7 +115,7 @@ namespace OpenWifi {
} }
} else if (P.IsAccounting()) { } else if (P.IsAccounting()) {
auto SerialNumber = P.ExtractSerialNumberFromProxyState(); auto SerialNumber = P.ExtractSerialNumberFromProxyState();
if(!SerialNumber.empty()) { if (!SerialNumber.empty()) {
poco_debug(Logger_, poco_debug(Logger_,
fmt::format("{}: {} Received {} bytes.", SerialNumber, fmt::format("{}: {} Received {} bytes.", SerialNumber,
P.PacketType(), NumberOfReceivedBytes)); P.PacketType(), NumberOfReceivedBytes));
@@ -129,20 +126,22 @@ namespace OpenWifi {
} }
} else if (P.IsAuthority()) { } else if (P.IsAuthority()) {
auto SerialNumber = P.ExtractSerialNumberTIP(); auto SerialNumber = P.ExtractSerialNumberTIP();
if(!SerialNumber.empty()) { if (!SerialNumber.empty()) {
poco_debug(Logger_, poco_debug(Logger_,
fmt::format("{}: {} Received {} bytes.", SerialNumber, fmt::format("{}: {} Received {} bytes.", SerialNumber,
P.PacketType(), NumberOfReceivedBytes)); P.PacketType(), NumberOfReceivedBytes));
AP_WS_Server()->SendRadiusCoAData(SerialNumber, Buffer, AP_WS_Server()->SendRadiusCoAData(SerialNumber, Buffer,
NumberOfReceivedBytes); NumberOfReceivedBytes);
} else { } else {
poco_debug(Logger_, "CoA/DM packet dropped."); poco_debug(Logger_, "CoA/DM packet dropped.");
} }
} else { } else {
poco_warning(Logger_,fmt::format("Unknown packet: Type: {} (type={}) Length={}", P.PacketType(), P.PacketTypeInt(), P.BufferLen())); poco_warning(Logger_,
fmt::format("Unknown packet: Type: {} (type={}) Length={}",
P.PacketType(), P.PacketTypeInt(), P.BufferLen()));
} }
} else { } else {
poco_warning(Logger_,"Invalid packet received. Resetting the connection."); poco_warning(Logger_, "Invalid packet received. Resetting the connection.");
Disconnect(); Disconnect();
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
@@ -150,47 +149,49 @@ namespace OpenWifi {
Disconnect(); Disconnect();
} catch (...) { } catch (...) {
Disconnect(); Disconnect();
poco_warning(Logger_,"Exception occurred. Resetting the connection."); poco_warning(Logger_, "Exception occurred. Resetting the connection.");
} }
} }
inline void onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) { inline void
poco_warning(Logger_,"Socker error. Terminating connection."); onError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
poco_warning(Logger_, "Socker error. Terminating connection.");
Disconnect(); Disconnect();
} }
inline void onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) { inline void
poco_warning(Logger_,"Socker socket shutdown. Terminating connection."); onShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
poco_warning(Logger_, "Socker socket shutdown. Terminating connection.");
Disconnect(); Disconnect();
} }
inline bool Connect() { inline bool Connect() {
if(TryAgain_) { if (TryAgain_) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
Poco::TemporaryFile CertFile_(MicroServiceDataDirectory()); Poco::TemporaryFile CertFile_(MicroServiceDataDirectory());
Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory()); Poco::TemporaryFile KeyFile_(MicroServiceDataDirectory());
std::vector<std::unique_ptr<Poco::TemporaryFile>> CaCertFiles_; std::vector<std::unique_ptr<Poco::TemporaryFile>> CaCertFiles_;
DecodeFile(CertFile_.path(), Server_.radsecCert); DecodeFile(CertFile_.path(), Server_.radsecCert);
DecodeFile(KeyFile_.path(), Server_.radsecKey); DecodeFile(KeyFile_.path(), Server_.radsecKey);
for(auto &cert:Server_.radsecCacerts) { for (auto &cert : Server_.radsecCacerts) {
CaCertFiles_.emplace_back(std::make_unique<Poco::TemporaryFile>(MicroServiceDataDirectory())); CaCertFiles_.emplace_back(
DecodeFile(CaCertFiles_[CaCertFiles_.size()-1]->path(), cert); std::make_unique<Poco::TemporaryFile>(MicroServiceDataDirectory()));
DecodeFile(CaCertFiles_[CaCertFiles_.size() - 1]->path(), cert);
} }
Poco::Net::Context::Ptr SecureContext = Poco::AutoPtr<Poco::Net::Context>( Poco::Net::Context::Ptr SecureContext =
new Poco::Net::Context(Poco::Net::Context::TLS_CLIENT_USE, Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(
KeyFile_.path(), Poco::Net::Context::TLS_CLIENT_USE, KeyFile_.path(), CertFile_.path(), ""));
CertFile_.path(),"")); if (Server_.allowSelfSigned) {
if(Server_.allowSelfSigned) {
SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE); SecureContext->setSecurityLevel(Poco::Net::Context::SECURITY_LEVEL_NONE);
SecureContext->enableExtendedCertificateVerification(false); SecureContext->enableExtendedCertificateVerification(false);
} }
for(const auto &ca:CaCertFiles_) { for (const auto &ca : CaCertFiles_) {
Poco::Crypto::X509Certificate cert(ca->path()); Poco::Crypto::X509Certificate cert(ca->path());
SecureContext->addCertificateAuthority(cert); SecureContext->addCertificateAuthority(cert);
} }
@@ -203,49 +204,48 @@ namespace OpenWifi {
Socket_->connect(Destination, Poco::Timespan(100, 0)); Socket_->connect(Destination, Poco::Timespan(100, 0));
Socket_->completeHandshake(); Socket_->completeHandshake();
if(!Server_.allowSelfSigned) { if (!Server_.allowSelfSigned) {
Socket_->verifyPeerCertificate(); Socket_->verifyPeerCertificate();
} }
if(Socket_->havePeerCertificate()) { if (Socket_->havePeerCertificate()) {
Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(Socket_->peerCertificate()); Peer_Cert_ = std::make_unique<Poco::Crypto::X509Certificate>(
Socket_->peerCertificate());
} }
Socket_->setBlocking(false); Socket_->setBlocking(false);
Socket_->setNoDelay(true); Socket_->setNoDelay(true);
Socket_->setKeepAlive(true); Socket_->setKeepAlive(true);
Socket_->setReceiveTimeout(Poco::Timespan(1 * 60 * 60,0)); Socket_->setReceiveTimeout(Poco::Timespan(1 * 60 * 60, 0));
Reactor_.addEventHandler( Reactor_.addEventHandler(
*Socket_, *Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>(
Poco::NObserver<RADSEC_server, Poco::Net::ReadableNotification>( *this, &RADSEC_server::onData));
*this, &RADSEC_server::onData));
Reactor_.addEventHandler( Reactor_.addEventHandler(
*Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ErrorNotification>( *Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ErrorNotification>(
*this, &RADSEC_server::onError)); *this, &RADSEC_server::onError));
Reactor_.addEventHandler( Reactor_.addEventHandler(
*Socket_, *Socket_, Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>(
Poco::NObserver<RADSEC_server, Poco::Net::ShutdownNotification>( *this, &RADSEC_server::onShutdown));
*this, &RADSEC_server::onShutdown));
Connected_ = true; Connected_ = true;
poco_information(Logger_,fmt::format("Connected. CN={}",CommonName())); poco_information(Logger_, fmt::format("Connected. CN={}", CommonName()));
return true; return true;
} catch (const Poco::Net::NetException &E) { } catch (const Poco::Net::NetException &E) {
poco_information(Logger_,"Could not connect."); poco_information(Logger_, "Could not connect.");
Logger_.log(E); Logger_.log(E);
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
poco_information(Logger_,"Could not connect."); poco_information(Logger_, "Could not connect.");
Logger_.log(E); Logger_.log(E);
} catch (...) { } catch (...) {
poco_information(Logger_,"Could not connect."); poco_information(Logger_, "Could not connect.");
} }
} }
return false; return false;
} }
inline void Disconnect() { inline void Disconnect() {
if(Connected_) { if (Connected_) {
std::lock_guard G(LocalMutex_); std::lock_guard G(LocalMutex_);
Reactor_.removeEventHandler( Reactor_.removeEventHandler(
@@ -260,44 +260,45 @@ namespace OpenWifi {
Socket_->close(); Socket_->close();
Connected_ = false; Connected_ = false;
} }
poco_information(Logger_,"Disconnecting."); poco_information(Logger_, "Disconnecting.");
} }
static void DecodeFile(const std::string &filename, const std::string &s) { static void DecodeFile(const std::string &filename, const std::string &s) {
std::ofstream sec_file(filename,std::ios_base::out|std::ios_base::trunc|std::ios_base::binary); std::ofstream sec_file(filename, std::ios_base::out | std::ios_base::trunc |
std::ios_base::binary);
std::stringstream is(s); std::stringstream is(s);
Poco::Base64Decoder ds(is); Poco::Base64Decoder ds(is);
Poco::StreamCopier::copyStream(ds,sec_file); Poco::StreamCopier::copyStream(ds, sec_file);
sec_file.close(); sec_file.close();
} }
[[nodiscard]] inline std::string CommonName() { [[nodiscard]] inline std::string CommonName() {
if(Peer_Cert_) if (Peer_Cert_)
return Peer_Cert_->commonName(); return Peer_Cert_->commonName();
return ""; return "";
} }
[[nodiscard]] inline std::string IssuerName() { [[nodiscard]] inline std::string IssuerName() {
if(Peer_Cert_) if (Peer_Cert_)
return Peer_Cert_->issuerName(); return Peer_Cert_->issuerName();
return ""; return "";
} }
[[nodiscard]] inline std::string SubjectName() { [[nodiscard]] inline std::string SubjectName() {
if(Peer_Cert_) if (Peer_Cert_)
return Peer_Cert_->subjectName(); return Peer_Cert_->subjectName();
return ""; return "";
} }
private: private:
std::recursive_mutex LocalMutex_; std::recursive_mutex LocalMutex_;
Poco::Net::SocketReactor &Reactor_; Poco::Net::SocketReactor &Reactor_;
GWObjects::RadiusProxyServerEntry Server_; GWObjects::RadiusProxyServerEntry Server_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
std::unique_ptr<Poco::Net::SecureStreamSocket> Socket_; std::unique_ptr<Poco::Net::SecureStreamSocket> Socket_;
Poco::Thread ReconnectThread_; Poco::Thread ReconnectThread_;
std::unique_ptr<Poco::Crypto::X509Certificate> Peer_Cert_; std::unique_ptr<Poco::Crypto::X509Certificate> Peer_Cert_;
volatile bool Connected_=false; volatile bool Connected_ = false;
volatile bool TryAgain_=true; volatile bool TryAgain_ = true;
}; };
} } // namespace OpenWifi

View File

@@ -4,26 +4,26 @@
#include "SDKcalls.h" #include "SDKcalls.h"
#include "framework/OpenAPIRequests.h"
#include "framework/MicroServiceNames.h" #include "framework/MicroServiceNames.h"
#include "framework/OpenAPIRequests.h"
namespace OpenWifi { namespace OpenWifi {
bool SDKCalls::GetProvisioningConfiguration(const std::string &SerialNumber, std::string & Config) { bool SDKCalls::GetProvisioningConfiguration(const std::string &SerialNumber,
std::string &Config) {
Types::StringPairVec QD { {"config","true"}}; Types::StringPairVec QD{{"config", "true"}};
OpenAPIRequestGet API(uSERVICE_PROVISIONING, OpenAPIRequestGet API(uSERVICE_PROVISIONING, "/api/v1/inventory/" + SerialNumber, QD,
"/api/v1/inventory/" + SerialNumber, 20000);
QD,20000);
Poco::JSON::Object::Ptr ResponseObject; Poco::JSON::Object::Ptr ResponseObject;
if(API.Do(ResponseObject)==Poco::Net::HTTPResponse::HTTP_OK) { if (API.Do(ResponseObject) == Poco::Net::HTTPResponse::HTTP_OK) {
if(ResponseObject->has("config")) { if (ResponseObject->has("config")) {
Config = ResponseObject->get("config").toString(); Config = ResponseObject->get("config").toString();
return true; return true;
} }
} }
return false; return false;
} }
} } // namespace OpenWifi

View File

@@ -9,8 +9,9 @@
namespace OpenWifi { namespace OpenWifi {
class SDKCalls { class SDKCalls {
public: public:
static bool GetProvisioningConfiguration(const std::string & SerialNumber, std::string & Config); static bool GetProvisioningConfiguration(const std::string &SerialNumber,
std::string &Config);
private: private:
}; };
} } // namespace OpenWifi

View File

@@ -3,21 +3,22 @@
// //
#include "ScriptManager.h" #include "ScriptManager.h"
#include "Poco/JSON/Parser.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include <fstream> #include <fstream>
#include "Poco/JSON/Parser.h"
namespace OpenWifi { namespace OpenWifi {
int ScriptManager::Start() { int ScriptManager::Start() {
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
ScriptDir_ = MicroServiceConfigPath("script.manager.directory", MicroServiceDataDirectory() + "/included_scripts" ); ScriptDir_ = MicroServiceConfigPath("script.manager.directory",
MicroServiceDataDirectory() + "/included_scripts");
return 0; return 0;
} }
void ScriptManager::Stop() { void ScriptManager::Stop() {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -19,16 +19,12 @@ namespace OpenWifi {
void Stop(); void Stop();
private: private:
std::string ScriptDir_; std::string ScriptDir_;
explicit ScriptManager() noexcept:
SubSystemServer("ScriptManager", "SCRIPT-MGR", "script.manager")
{
}
explicit ScriptManager() noexcept
: SubSystemServer("ScriptManager", "SCRIPT-MGR", "script.manager") {}
}; };
inline auto ScriptManager() { return ScriptManager::instance(); } inline auto ScriptManager() { return ScriptManager::instance(); }
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -11,23 +11,23 @@
namespace OpenWifi { namespace OpenWifi {
int SerialNumberCache::Start() { int SerialNumberCache::Start() {
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
StorageService()->UpdateSerialNumberCache(); StorageService()->UpdateSerialNumberCache();
return 0; return 0;
} }
void SerialNumberCache::Stop() { void SerialNumberCache::Stop() {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
SNs_.clear(); SNs_.clear();
Reverse_SNs_.clear(); Reverse_SNs_.clear();
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
void SerialNumberCache::AddSerialNumber(const std::string &S) { void SerialNumberCache::AddSerialNumber(const std::string &S) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
uint64_t SN = std::stoull(S, nullptr, 16); uint64_t SN = std::stoull(S, nullptr, 16);
if(std::find(std::begin(SNs_),std::end(SNs_),SN) == std::end(SNs_)) { if (std::find(std::begin(SNs_), std::end(SNs_), SN) == std::end(SNs_)) {
auto insert_point = std::lower_bound(SNs_.begin(), SNs_.end(), SN); auto insert_point = std::lower_bound(SNs_.begin(), SNs_.end(), SN);
SNs_.insert(insert_point, SN); SNs_.insert(insert_point, SN);
@@ -39,17 +39,17 @@ namespace OpenWifi {
} }
void SerialNumberCache::DeleteSerialNumber(const std::string &S) { void SerialNumberCache::DeleteSerialNumber(const std::string &S) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
uint64_t SN = std::stoull(S,nullptr,16); uint64_t SN = std::stoull(S, nullptr, 16);
auto It = std::find(SNs_.begin(),SNs_.end(),SN); auto It = std::find(SNs_.begin(), SNs_.end(), SN);
if(It != SNs_.end()) { if (It != SNs_.end()) {
SNs_.erase(It); SNs_.erase(It);
auto R = ReverseSerialNumber(S); auto R = ReverseSerialNumber(S);
uint64_t RSN = std::stoull(R, nullptr, 16); uint64_t RSN = std::stoull(R, nullptr, 16);
auto RIt = std::find(Reverse_SNs_.begin(),Reverse_SNs_.end(),RSN); auto RIt = std::find(Reverse_SNs_.begin(), Reverse_SNs_.end(), RSN);
if(RIt != Reverse_SNs_.end()) { if (RIt != Reverse_SNs_.end()) {
Reverse_SNs_.erase(RIt); Reverse_SNs_.erase(RIt);
} }
} }
@@ -60,13 +60,15 @@ namespace OpenWifi {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
Res = (Res << 4) + (N & 0x000000000000000f); Res = (Res << 4) + (N & 0x000000000000000f);
N >>= 4; N >>= 4;
} }
Res >>= 16; Res >>= 16;
return Res; return Res;
} }
void SerialNumberCache::ReturnNumbers(const std::string &S, uint HowMany, const std::vector<uint64_t> &SNArr, std::vector<uint64_t> &A, bool ReverseResult) { void SerialNumberCache::ReturnNumbers(const std::string &S, uint HowMany,
const std::vector<uint64_t> &SNArr,
std::vector<uint64_t> &A, bool ReverseResult) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
if (S.length() == 12) { if (S.length() == 12) {
@@ -82,9 +84,10 @@ namespace OpenWifi {
auto LB = std::lower_bound(SNArr.begin(), SNArr.end(), SN); auto LB = std::lower_bound(SNArr.begin(), SNArr.end(), SN);
if (LB != SNArr.end()) { if (LB != SNArr.end()) {
for (; LB != SNArr.end() && HowMany; ++LB, --HowMany) { for (; LB != SNArr.end() && HowMany; ++LB, --HowMany) {
if(ReverseResult) { if (ReverseResult) {
const auto TSN = ReverseSerialNumber(Utils::IntToSerialNumber(Reverse(*LB))); const auto TSN =
if (S == TSN.substr(0,S.size())) { ReverseSerialNumber(Utils::IntToSerialNumber(Reverse(*LB)));
if (S == TSN.substr(0, S.size())) {
A.emplace_back(Reverse(*LB)); A.emplace_back(Reverse(*LB));
} else { } else {
break; break;
@@ -102,18 +105,19 @@ namespace OpenWifi {
} }
} }
void SerialNumberCache::FindNumbers(const std::string &S, uint HowMany, std::vector<uint64_t> &A) { void SerialNumberCache::FindNumbers(const std::string &S, uint HowMany,
if(S.empty()) std::vector<uint64_t> &A) {
if (S.empty())
return; return;
if (S[0] == '*') { if (S[0] == '*') {
std::string Reversed; std::string Reversed;
std::copy(rbegin(S), rend(S)-1, std::back_inserter(Reversed)); std::copy(rbegin(S), rend(S) - 1, std::back_inserter(Reversed));
if(Reversed.empty()) if (Reversed.empty())
return; return;
return ReturnNumbers(Reversed, HowMany, Reverse_SNs_, A, true); return ReturnNumbers(Reversed, HowMany, Reverse_SNs_, A, true);
} else { } else {
return ReturnNumbers(S, HowMany, SNs_, A, false); return ReturnNumbers(S, HowMany, SNs_, A, false);
} }
} }
} } // namespace OpenWifi

View File

@@ -8,10 +8,9 @@
namespace OpenWifi { namespace OpenWifi {
class SerialNumberCache : public SubSystemServer { class SerialNumberCache : public SubSystemServer {
public: public:
static auto instance() { static auto instance() {
static auto instance_ = new SerialNumberCache; static auto instance_ = new SerialNumberCache;
return instance_; return instance_;
} }
@@ -21,29 +20,29 @@ namespace OpenWifi {
void DeleteSerialNumber(const std::string &SerialNumber); void DeleteSerialNumber(const std::string &SerialNumber);
void FindNumbers(const std::string &SerialNumber, uint HowMany, std::vector<uint64_t> &A); void FindNumbers(const std::string &SerialNumber, uint HowMany, std::vector<uint64_t> &A);
inline bool NumberExists(uint64_t SerialNumber) { inline bool NumberExists(uint64_t SerialNumber) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
return std::find(SNs_.begin(),SNs_.end(),SerialNumber)!=SNs_.end(); return std::find(SNs_.begin(), SNs_.end(), SerialNumber) != SNs_.end();
} }
static inline std::string ReverseSerialNumber(const std::string &S) { static inline std::string ReverseSerialNumber(const std::string &S) {
std::string ReversedString; std::string ReversedString;
std::copy(rbegin(S),rend(S),std::back_inserter(ReversedString)); std::copy(rbegin(S), rend(S), std::back_inserter(ReversedString));
return ReversedString; return ReversedString;
} }
private: private:
std::vector<uint64_t> SNs_; std::vector<uint64_t> SNs_;
std::vector<uint64_t> Reverse_SNs_; std::vector<uint64_t> Reverse_SNs_;
void ReturnNumbers(const std::string &S, uint HowMany, const std::vector<uint64_t> & SNArr, std::vector<uint64_t> &A, bool ReverseResult); void ReturnNumbers(const std::string &S, uint HowMany, const std::vector<uint64_t> &SNArr,
std::vector<uint64_t> &A, bool ReverseResult);
SerialNumberCache() noexcept: SerialNumberCache() noexcept
SubSystemServer("SerialNumberCache", "SNCACHE-SVR", "serialcache") : SubSystemServer("SerialNumberCache", "SNCACHE-SVR", "serialcache") {
{ SNs_.reserve(2000);
SNs_.reserve(2000); }
}
}; };
inline auto SerialNumberCache() { return SerialNumberCache::instance(); } inline auto SerialNumberCache() { return SerialNumberCache::instance(); }
} // namespace OpenWiFi } // namespace OpenWifi

View File

@@ -1,7 +0,0 @@
//
// Created by stephane bourque on 2022-11-22.
//
#include "SignatureMgr.h"
namespace OpenWifi {} // namespace OpenWifi

View File

@@ -7,18 +7,18 @@
#include <fstream> #include <fstream>
#include <shared_mutex> #include <shared_mutex>
#include "framework/SubSystemServer.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/SubSystemServer.h"
#include "framework/utils.h" #include "framework/utils.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "Poco/DigestStream.h"
#include "Poco/DigestEngine.h"
#include "Poco/Crypto/RSADigestEngine.h" #include "Poco/Crypto/RSADigestEngine.h"
#include "Poco/StreamCopier.h" #include "Poco/DigestEngine.h"
#include "Poco/DigestStream.h"
#include "Poco/File.h" #include "Poco/File.h"
#include "Poco/StreamCopier.h"
#include "Poco/StringTokenizer.h" #include "Poco/StringTokenizer.h"
#include "Poco/TemporaryFile.h" #include "Poco/TemporaryFile.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "fmt/format.h" #include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
@@ -31,61 +31,66 @@ namespace OpenWifi {
} }
struct SignatureCacheEntry { struct SignatureCacheEntry {
std::string vendor_uri_hash; std::string vendor_uri_hash;
std::string signature; std::string signature;
}; };
inline int Start() final { inline int Start() final {
poco_notice(Logger(),"Starting..."); poco_notice(Logger(), "Starting...");
std::shared_lock L(KeyMutex_); std::shared_lock L(KeyMutex_);
CacheFilename_ = MicroServiceDataDirectory() + "/signature_cache"; CacheFilename_ = MicroServiceDataDirectory() + "/signature_cache";
Poco::File CacheFile(CacheFilename_); Poco::File CacheFile(CacheFilename_);
if(CacheFile.exists()) { if (CacheFile.exists()) {
std::fstream CacheFileContent(CacheFilename_, std::ios_base::in); std::fstream CacheFileContent(CacheFilename_, std::ios_base::in);
std::string line; std::string line;
while(std::getline(CacheFileContent, line)) { while (std::getline(CacheFileContent, line)) {
auto Tokens = Poco::StringTokenizer(line,":"); auto Tokens = Poco::StringTokenizer(line, ":");
if(Tokens.count()==2) { if (Tokens.count() == 2) {
SignatureCache_[Tokens[0]] = Tokens[1]; SignatureCache_[Tokens[0]] = Tokens[1];
} }
} }
} }
poco_information(Logger(),fmt::format("Found {} entries in signature cache.", SignatureCache_.size())); poco_information(Logger(), fmt::format("Found {} entries in signature cache.",
SignatureCache_.size()));
// read all the key vendors. // read all the key vendors.
// signature.manager.0.key.public // signature.manager.0.key.public
// signature.manager.0.key.private // signature.manager.0.key.private
// signature.manager.0.vendor // signature.manager.0.vendor
int i=0; int i = 0;
while(true) { while (true) {
auto Vendor = MicroServiceConfigGetString("signature.manager." + std::to_string(i) + ".vendor",""); auto Vendor = MicroServiceConfigGetString(
auto PrivateKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.private",""); "signature.manager." + std::to_string(i) + ".vendor", "");
auto PublicKey = MicroServiceConfigPath("signature.manager." + std::to_string(i) + ".key.public",""); auto PrivateKey = MicroServiceConfigPath(
if(Vendor.empty() || PrivateKey.empty() || PublicKey.empty()) { "signature.manager." + std::to_string(i) + ".key.private", "");
auto PublicKey = MicroServiceConfigPath(
"signature.manager." + std::to_string(i) + ".key.public", "");
if (Vendor.empty() || PrivateKey.empty() || PublicKey.empty()) {
break; break;
} }
Poco::File PubKey(PublicKey), PrivKey(PrivateKey); Poco::File PubKey(PublicKey), PrivKey(PrivateKey);
if(PubKey.exists() && PrivKey.exists()) { if (PubKey.exists() && PrivKey.exists()) {
Keys_[Vendor] = Poco::SharedPtr<Poco::Crypto::RSAKey>( Keys_[Vendor] = Poco::SharedPtr<Poco::Crypto::RSAKey>(
new Poco::Crypto::RSAKey(PublicKey, PrivateKey, "")); new Poco::Crypto::RSAKey(PublicKey, PrivateKey, ""));
} }
++i; ++i;
} }
poco_information(Logger(),fmt::format("{} signatures in dictionary.", Keys_.size())); poco_information(Logger(), fmt::format("{} signatures in dictionary.", Keys_.size()));
return 0; return 0;
} }
inline void Stop() final { inline void Stop() final {
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const std::string &Data) const { inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions,
const std::string &Data) const {
std::shared_lock L(KeyMutex_); std::shared_lock L(KeyMutex_);
try { try {
if (Restrictions.key_info.algo == "static") { if (Restrictions.key_info.algo == "static") {
@@ -93,7 +98,8 @@ namespace OpenWifi {
} }
auto Vendor = Keys_.find(Restrictions.key_info.vendor); auto Vendor = Keys_.find(Restrictions.key_info.vendor);
if (Vendor == Keys_.end()) { if (Vendor == Keys_.end()) {
poco_error( Logger(), fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor)); poco_error(Logger(),
fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor));
return ""; return "";
} }
@@ -112,7 +118,8 @@ namespace OpenWifi {
return ""; return "";
} }
inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions, const Poco::URI &uri) { inline std::string Sign(const GWObjects::DeviceRestrictions &Restrictions,
const Poco::URI &uri) {
std::shared_lock L(KeyMutex_); std::shared_lock L(KeyMutex_);
try { try {
if (Restrictions.key_info.algo == "static") { if (Restrictions.key_info.algo == "static") {
@@ -121,13 +128,15 @@ namespace OpenWifi {
auto Vendor = Keys_.find(Restrictions.key_info.vendor); auto Vendor = Keys_.find(Restrictions.key_info.vendor);
if (Vendor == Keys_.end()) { if (Vendor == Keys_.end()) {
poco_error( Logger(), fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor)); poco_error(Logger(),
fmt::format("{}: vendor unknown.", Restrictions.key_info.vendor));
return ""; return "";
} }
if (Restrictions.key_info.algo == "dgst-sha256") { if (Restrictions.key_info.algo == "dgst-sha256") {
auto FileHash = auto FileHash =
Utils::ComputeHash(Restrictions.key_info.vendor, Restrictions.key_info.algo, uri.getPathAndQuery()); Utils::ComputeHash(Restrictions.key_info.vendor, Restrictions.key_info.algo,
uri.getPathAndQuery());
auto CacheEntry = SignatureCache_.find(FileHash); auto CacheEntry = SignatureCache_.find(FileHash);
if (CacheEntry != end(SignatureCache_)) { if (CacheEntry != end(SignatureCache_)) {
return CacheEntry->second; return CacheEntry->second;
@@ -141,7 +150,8 @@ namespace OpenWifi {
std::ios_base::in | std::ios_base::binary); std::ios_base::in | std::ios_base::binary);
Poco::StreamCopier::copyStream(ifs, ofs); Poco::StreamCopier::copyStream(ifs, ofs);
ofs.flush(); ofs.flush();
auto Signature = Utils::base64encode((const unsigned char *)R.signature().data(),R.signature().size()); auto Signature = Utils::base64encode(
(const unsigned char *)R.signature().data(), R.signature().size());
SignatureCache_[FileHash] = Signature; SignatureCache_[FileHash] = Signature;
SaveCache(); SaveCache();
return Signature; return Signature;
@@ -154,9 +164,9 @@ namespace OpenWifi {
} }
void SaveCache() { void SaveCache() {
std::ofstream ofs(CacheFilename_, std::ios_base::trunc | std::ios_base::out); std::ofstream ofs(CacheFilename_, std::ios_base::trunc | std::ios_base::out);
for(const auto &[hash,signature]:SignatureCache_) { for (const auto &[hash, signature] : SignatureCache_) {
ofs << hash << ":" << signature << std::endl; ofs << hash << ":" << signature << std::endl;
} }
} }
@@ -164,13 +174,12 @@ namespace OpenWifi {
private: private:
mutable std::shared_mutex KeyMutex_; mutable std::shared_mutex KeyMutex_;
std::map<std::string, Poco::SharedPtr<Poco::Crypto::RSAKey>> Keys_; std::map<std::string, Poco::SharedPtr<Poco::Crypto::RSAKey>> Keys_;
std::map<std::string,std::string> SignatureCache_; std::map<std::string, std::string> SignatureCache_;
std::string CacheFilename_; std::string CacheFilename_;
explicit SignatureManager() noexcept explicit SignatureManager() noexcept
: SubSystemServer("SignatureManager", "SIGNATURE-MGR", "signature.manager") {} : SubSystemServer("SignatureManager", "SIGNATURE-MGR", "signature.manager") {}
}; };
inline auto SignatureManager() { return SignatureManager::instance(); } inline auto SignatureManager() { return SignatureManager::instance(); }
} } // namespace OpenWifi

View File

@@ -8,60 +8,62 @@
namespace OpenWifi::StateUtils { namespace OpenWifi::StateUtils {
static int ChannelToBand(uint64_t C) { static int ChannelToBand(uint64_t C) {
if(C>=1 && C<=16) return 2; if (C >= 1 && C <= 16)
return 2;
return 5; return 5;
} }
static int BandToInt(const std::string &band) { static int BandToInt(const std::string &band) {
if(band=="2G") return 2; if (band == "2G")
if(band=="5G") return 5; return 2;
if(band=="6G") return 6; if (band == "5G")
return 5;
if (band == "6G")
return 6;
return 2; return 2;
} }
bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, bool ComputeAssociations(const Poco::JSON::Object::Ptr RawObject, uint64_t &Radios_2G,
uint64_t &Radios_2G,
uint64_t &Radios_5G, uint64_t &Radios_6G) { uint64_t &Radios_5G, uint64_t &Radios_6G) {
Radios_2G = 0 ; Radios_2G = 0;
Radios_5G = 0; Radios_5G = 0;
Radios_6G = 0; Radios_6G = 0;
if(RawObject->isArray("radios") && RawObject->isArray("interfaces")) { if (RawObject->isArray("radios") && RawObject->isArray("interfaces")) {
auto RA = RawObject->getArray("radios"); auto RA = RawObject->getArray("radios");
// map of phy to 2g/5g // map of phy to 2g/5g
std::map<std::string,int> RadioPHYs; std::map<std::string, int> RadioPHYs;
// parse radios and get the phy out with the band // parse radios and get the phy out with the band
bool UseBandInfo = false; bool UseBandInfo = false;
for(auto const &i:*RA) { for (auto const &i : *RA) {
// Poco::JSON::Parser p2; // Poco::JSON::Parser p2;
auto RadioObj = i.extract<Poco::JSON::Object::Ptr>(); auto RadioObj = i.extract<Poco::JSON::Object::Ptr>();
if(RadioObj->has("band")) { if (RadioObj->has("band")) {
// std::cout << "Use band info" << std::endl; // std::cout << "Use band info" << std::endl;
UseBandInfo = true ; UseBandInfo = true;
} else if(RadioObj->has("phy") && RadioObj->has("channel")) { } else if (RadioObj->has("phy") && RadioObj->has("channel")) {
if(RadioObj->isArray("channel")) { if (RadioObj->isArray("channel")) {
auto ChannelArray = RadioObj->getArray("channel"); auto ChannelArray = RadioObj->getArray("channel");
if(ChannelArray->size()) { if (ChannelArray->size()) {
RadioPHYs[RadioObj->get("phy")] = RadioPHYs[RadioObj->get("phy")] =
ChannelToBand( ChannelArray->getElement<uint64_t>(0) ); ChannelToBand(ChannelArray->getElement<uint64_t>(0));
} }
} else { } else {
RadioPHYs[RadioObj->get("phy")] = RadioPHYs[RadioObj->get("phy")] = ChannelToBand(RadioObj->get("channel"));
ChannelToBand(RadioObj->get("channel"));
} }
} }
} }
auto InterfaceArray = RawObject->getArray("interfaces"); auto InterfaceArray = RawObject->getArray("interfaces");
for(auto const &interface:*InterfaceArray) { for (auto const &interface : *InterfaceArray) {
auto InterfaceObj = interface.extract<Poco::JSON::Object::Ptr>(); auto InterfaceObj = interface.extract<Poco::JSON::Object::Ptr>();
if(InterfaceObj->isArray("ssids")) { if (InterfaceObj->isArray("ssids")) {
auto SSIDArray = InterfaceObj->getArray("ssids"); auto SSIDArray = InterfaceObj->getArray("ssids");
for(const auto &ssid:*SSIDArray) { for (const auto &ssid : *SSIDArray) {
auto SSID_info = ssid.extract<Poco::JSON::Object::Ptr>(); auto SSID_info = ssid.extract<Poco::JSON::Object::Ptr>();
if(SSID_info->isArray("associations") && SSID_info->has("phy")) { if (SSID_info->isArray("associations") && SSID_info->has("phy")) {
int Radio = 2; int Radio = 2;
if(UseBandInfo) { if (UseBandInfo) {
Radio = BandToInt(SSID_info->get("band")); Radio = BandToInt(SSID_info->get("band"));
} else { } else {
auto PHY = SSID_info->get("phy"); auto PHY = SSID_info->get("phy");
@@ -70,19 +72,27 @@ namespace OpenWifi::StateUtils {
Radio = Rit->second; Radio = Rit->second;
} }
auto AssocA = SSID_info->getArray("associations"); auto AssocA = SSID_info->getArray("associations");
switch(Radio) { switch (Radio) {
case 2: Radios_2G += AssocA->size(); break; case 2:
case 5: Radios_5G += AssocA->size(); break; Radios_2G += AssocA->size();
case 6: Radios_6G += AssocA->size(); break; break;
default: Radios_2G += AssocA->size(); break; case 5:
Radios_5G += AssocA->size();
break;
case 6:
Radios_6G += AssocA->size();
break;
default:
Radios_2G += AssocA->size();
break;
} }
} }
} }
} }
} }
// std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl; // std::cout << Radios_2G << " " << Radios_5G << " " << Radios_6G << std::endl;
return true; return true;
} }
return false; return false;
} }
} } // namespace OpenWifi::StateUtils

View File

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

View File

@@ -8,42 +8,37 @@
#include "StorageService.h" #include "StorageService.h"
#include "framework/AppServiceRegistry.h" #include "framework/AppServiceRegistry.h"
#include "framework/utils.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/utils.h"
#include "fmt/format.h" #include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer){ void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("strg-archiver"); Utils::SetThreadName("strg-archiver");
auto now = Utils::Now(); auto now = Utils::Now();
for(const auto &[DBName, Keep]:DBs_) { for (const auto &[DBName, Keep] : DBs_) {
if (!Poco::icompare(DBName, "healthchecks")) { if (!Poco::icompare(DBName, "healthchecks")) {
poco_information(Logger(),"Archiving HealthChecks..."); poco_information(Logger(), "Archiving HealthChecks...");
StorageService()->RemoveHealthChecksRecordsOlderThan( StorageService()->RemoveHealthChecksRecordsOlderThan(now - (Keep * 24 * 60 * 60));
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "statistics")) { } else if (!Poco::icompare(DBName, "statistics")) {
poco_information(Logger(),"Archiving Statistics..."); poco_information(Logger(), "Archiving Statistics...");
StorageService()->RemoveStatisticsRecordsOlderThan( StorageService()->RemoveStatisticsRecordsOlderThan(now - (Keep * 24 * 60 * 60));
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "devicelogs")) { } else if (!Poco::icompare(DBName, "devicelogs")) {
poco_information(Logger(),"Archiving Device Logs..."); poco_information(Logger(), "Archiving Device Logs...");
StorageService()->RemoveDeviceLogsRecordsOlderThan( StorageService()->RemoveDeviceLogsRecordsOlderThan(now - (Keep * 24 * 60 * 60));
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "commandlist")) { } else if (!Poco::icompare(DBName, "commandlist")) {
poco_information(Logger(),"Archiving Command History..."); poco_information(Logger(), "Archiving Command History...");
StorageService()->RemoveCommandListRecordsOlderThan( StorageService()->RemoveCommandListRecordsOlderThan(now - (Keep * 24 * 60 * 60));
now - (Keep * 24 * 60 * 60));
} else if (!Poco::icompare(DBName, "fileuploads")) { } else if (!Poco::icompare(DBName, "fileuploads")) {
poco_information(Logger(),"Archiving Upload files..."); poco_information(Logger(), "Archiving Upload files...");
StorageService()->RemoveUploadedFilesRecordsOlderThan( StorageService()->RemoveUploadedFilesRecordsOlderThan(now - (Keep * 24 * 60 * 60));
now - (Keep * 24 * 60 * 60));
} else { } else {
poco_information(Logger(),fmt::format("Cannot archive DB '{}'", DBName)); poco_information(Logger(), fmt::format("Cannot archive DB '{}'", DBName));
} }
} }
AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) now); AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t)now);
} }
static auto CalculateDelta(std::uint64_t H, std::uint64_t M) { static auto CalculateDelta(std::uint64_t H, std::uint64_t M) {
@@ -51,56 +46,58 @@ namespace OpenWifi {
Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), (int)H, (int)M, 0); Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), (int)H, (int)M, 0);
std::uint64_t delta = 0; std::uint64_t delta = 0;
if ((dt.hour() < (int)H) || (dt.hour()==(int)H && dt.minute()<(int)M)) { if ((dt.hour() < (int)H) || (dt.hour() == (int)H && dt.minute() < (int)M)) {
delta = scheduled.timestamp().epochTime() - dt.timestamp().epochTime(); delta = scheduled.timestamp().epochTime() - dt.timestamp().epochTime();
} else { } else {
delta = (24*60*60) - (dt.timestamp().epochTime() - scheduled.timestamp().epochTime()); delta =
(24 * 60 * 60) - (dt.timestamp().epochTime() - scheduled.timestamp().epochTime());
} }
return delta; return delta;
} }
int StorageArchiver::Start() { int StorageArchiver::Start() {
Enabled_ = MicroServiceConfigGetBool("archiver.enabled",false); Enabled_ = MicroServiceConfigGetBool("archiver.enabled", false);
if(!Enabled_) { if (!Enabled_) {
poco_information(Logger(),"Archiver is disabled."); poco_information(Logger(), "Archiver is disabled.");
return 0; return 0;
} }
Archiver_ = std::make_unique<Archiver>(Logger()); Archiver_ = std::make_unique<Archiver>(Logger());
ArchiverCallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(*Archiver_,&Archiver::onTimer); ArchiverCallback_ =
std::make_unique<Poco::TimerCallback<Archiver>>(*Archiver_, &Archiver::onTimer);
auto Schedule = MicroServiceConfigGetString("archiver.schedule","03:00"); auto Schedule = MicroServiceConfigGetString("archiver.schedule", "03:00");
auto S = Poco::StringTokenizer(Schedule,":"); auto S = Poco::StringTokenizer(Schedule, ":");
std::uint64_t RunAtHour_, RunAtMin_; std::uint64_t RunAtHour_, RunAtMin_;
if(S.count()!=2) { if (S.count() != 2) {
RunAtHour_ = 3 ; RunAtHour_ = 3;
RunAtMin_ = 0; RunAtMin_ = 0;
} else { } else {
RunAtHour_ = std::strtoull(S[0].c_str(), nullptr, 10); RunAtHour_ = std::strtoull(S[0].c_str(), nullptr, 10);
RunAtMin_ = std::strtoull(S[1].c_str(), nullptr, 10); RunAtMin_ = std::strtoull(S[1].c_str(), nullptr, 10);
} }
for(int i=0;i<20;i++) { for (int i = 0; i < 20; i++) {
std::string key = "archiver.db." + std::to_string(i) + ".name"; std::string key = "archiver.db." + std::to_string(i) + ".name";
auto DBName = MicroServiceConfigGetString(key,""); auto DBName = MicroServiceConfigGetString(key, "");
if(!DBName.empty()) { if (!DBName.empty()) {
for(auto const &DB:AllInternalDBNames) { for (auto const &DB : AllInternalDBNames) {
if(Poco::icompare(DBName,DB)==0) { if (Poco::icompare(DBName, DB) == 0) {
std::string Key = "archiver.db." + std::to_string(i) + ".keep"; std::string Key = "archiver.db." + std::to_string(i) + ".keep";
auto Keep = MicroServiceConfigGetInt(Key,7); auto Keep = MicroServiceConfigGetInt(Key, 7);
Archiver_->AddDb(DB, Keep); Archiver_->AddDb(DB, Keep);
} }
} }
} }
} }
int NextRun = CalculateDelta(RunAtHour_,RunAtMin_); int NextRun = CalculateDelta(RunAtHour_, RunAtMin_);
poco_information(Logger(),fmt::format("Next run in {} seconds.",NextRun)); poco_information(Logger(), fmt::format("Next run in {} seconds.", NextRun));
Timer_.setStartInterval( NextRun * 1000); Timer_.setStartInterval(NextRun * 1000);
Timer_.setPeriodicInterval(24 * 60 * 60 * 1000); // 1 hours Timer_.setPeriodicInterval(24 * 60 * 60 * 1000); // 1 hours
Timer_.start(*ArchiverCallback_, MicroServiceTimerPool()); Timer_.start(*ArchiverCallback_, MicroServiceTimerPool());
@@ -108,11 +105,11 @@ namespace OpenWifi {
} }
void StorageArchiver::Stop() { void StorageArchiver::Stop() {
poco_information(Logger(),"Stopping..."); poco_information(Logger(), "Stopping...");
if(Enabled_) { if (Enabled_) {
Timer_.stop(); Timer_.stop();
} }
poco_information(Logger(),"Stopped..."); poco_information(Logger(), "Stopped...");
} }
}; }; // namespace OpenWifi

View File

@@ -13,52 +13,50 @@
namespace OpenWifi { namespace OpenWifi {
static const std::list<std::string> AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist", "fileuploads"}; static const std::list<std::string> AllInternalDBNames{
"healthchecks", "statistics", "devicelogs", "commandlist", "fileuploads"};
class Archiver { class Archiver {
public: public:
explicit Archiver(Poco::Logger &Logger) : Logger_(Logger) {
explicit Archiver(Poco::Logger &Logger): for (const auto &db : AllInternalDBNames) {
Logger_(Logger) { DBs_[db] = 7;
for(const auto &db:AllInternalDBNames) {
DBs_[db] = 7 ;
} }
} }
void onTimer(Poco::Timer & timer); void onTimer(Poco::Timer &timer);
inline void AddDb(const std::string &dbname, std::uint64_t retain) { inline void AddDb(const std::string &dbname, std::uint64_t retain) {
DBs_[dbname] = retain; DBs_[dbname] = retain;
} }
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
private:
Poco::Logger &Logger_;
std::map<std::string,std::uint64_t> DBs_;
};
class StorageArchiver : public SubSystemServer { private:
Poco::Logger &Logger_;
std::map<std::string, std::uint64_t> DBs_;
};
public: class StorageArchiver : public SubSystemServer {
static auto instance() {
static auto instance_ = new StorageArchiver;
return instance_;
}
int Start() override; public:
void Stop() override; static auto instance() {
inline bool Enabled() const { return Enabled_; } static auto instance_ = new StorageArchiver;
return instance_;
}
private: int Start() override;
std::atomic_bool Enabled_ = false; void Stop() override;
Poco::Timer Timer_; inline bool Enabled() const { return Enabled_; }
std::unique_ptr<Archiver> Archiver_;
std::unique_ptr<Poco::TimerCallback<Archiver>> ArchiverCallback_;
StorageArchiver() noexcept: private:
SubSystemServer("StorageArchiver", "STORAGE-ARCHIVE", "archiver") std::atomic_bool Enabled_ = false;
{ Poco::Timer Timer_;
} std::unique_ptr<Archiver> Archiver_;
}; std::unique_ptr<Poco::TimerCallback<Archiver>> ArchiverCallback_;
inline auto StorageArchiver() { return StorageArchiver::instance(); } StorageArchiver() noexcept
: SubSystemServer("StorageArchiver", "STORAGE-ARCHIVE", "archiver") {}
};
} // namespace inline auto StorageArchiver() { return StorageArchiver::instance(); }
} // namespace OpenWifi

View File

@@ -10,25 +10,26 @@
namespace OpenWifi { namespace OpenWifi {
int Storage::Start() { int Storage::Start() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
StorageClass::Start(); StorageClass::Start();
Create_Tables(); Create_Tables();
InitializeBlackListCache(); InitializeBlackListCache();
ScriptDB_ = std::make_unique<OpenWifi::ScriptDB>("Scripts", "scr", dbType_,*Pool_, Logger()); ScriptDB_ =
std::make_unique<OpenWifi::ScriptDB>("Scripts", "scr", dbType_, *Pool_, Logger());
ScriptDB_->Create(); ScriptDB_->Create();
ScriptDB_->Initialize(); ScriptDB_->Initialize();
return 0; return 0;
} }
void Storage::Stop() { void Storage::Stop() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
poco_notice(Logger(),"Stopping..."); poco_notice(Logger(), "Stopping...");
StorageClass::Stop(); StorageClass::Stop();
poco_notice(Logger(),"Stopped..."); poco_notice(Logger(), "Stopped...");
} }
} } // namespace OpenWifi
// namespace // namespace

View File

@@ -8,63 +8,69 @@
#pragma once #pragma once
#include "framework/StorageClass.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "Poco/Net/IPAddress.h"
#include "CentralConfig.h" #include "CentralConfig.h"
#include "Poco/Net/IPAddress.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/StorageClass.h"
#include "storage/storage_scripts.h" #include "storage/storage_scripts.h"
namespace OpenWifi { namespace OpenWifi {
class Storage : public StorageClass { class Storage : public StorageClass {
public:
public:
enum class CommandExecutionType { enum class CommandExecutionType {
COMMAND_PENDING, COMMAND_PENDING,
COMMAND_EXECUTED, COMMAND_EXECUTED,
COMMAND_COMPLETED, COMMAND_COMPLETED,
COMMAND_TIMEDOUT, COMMAND_TIMEDOUT,
COMMAND_FAILED, COMMAND_FAILED,
COMMAND_EXPIRED, COMMAND_EXPIRED,
COMMAND_EXECUTING COMMAND_EXECUTING
}; };
inline OpenWifi::ScriptDB & ScriptDB() { return *ScriptDB_; } inline OpenWifi::ScriptDB &ScriptDB() { return *ScriptDB_; }
inline std::string to_string(const CommandExecutionType &C) { inline std::string to_string(const CommandExecutionType &C) {
switch(C) { switch (C) {
case CommandExecutionType::COMMAND_PENDING: return "pending"; case CommandExecutionType::COMMAND_PENDING:
case CommandExecutionType::COMMAND_EXECUTED: return "executed"; return "pending";
case CommandExecutionType::COMMAND_COMPLETED: return "completed"; case CommandExecutionType::COMMAND_EXECUTED:
case CommandExecutionType::COMMAND_TIMEDOUT: return "timedout"; return "executed";
case CommandExecutionType::COMMAND_FAILED: return "failed"; case CommandExecutionType::COMMAND_COMPLETED:
case CommandExecutionType::COMMAND_EXPIRED: return "expired"; return "completed";
case CommandExecutionType::COMMAND_EXECUTING: case CommandExecutionType::COMMAND_TIMEDOUT:
default: return "timedout";
return "executing"; case CommandExecutionType::COMMAND_FAILED:
return "failed";
case CommandExecutionType::COMMAND_EXPIRED:
return "expired";
case CommandExecutionType::COMMAND_EXECUTING:
default:
return "executing";
} }
} }
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(dbType_==sqlite) { if (dbType_ == sqlite) {
return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " "; return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " ";
} else if(dbType_==pgsql) { } else if (dbType_ == pgsql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) +
} else if(dbType_==mysql) { " ";
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; } else if (dbType_ == mysql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) +
" ";
} }
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
} }
inline std::string ConvertParams(const std::string & S) const { inline std::string ConvertParams(const std::string &S) const {
std::string R; std::string R;
R.reserve(S.size()*2+1); R.reserve(S.size() * 2 + 1);
if(dbType_==pgsql) { if (dbType_ == pgsql) {
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++));
} else { } else {
@@ -77,104 +83,136 @@ namespace OpenWifi {
return R; return R;
} }
static auto instance() { static auto instance() {
static auto instance_ = new Storage; static auto instance_ = new Storage;
return instance_; return instance_;
} }
// typedef std::map<std::string,std::string> DeviceCapabilitiesCache; // typedef std::map<std::string,std::string> DeviceCapabilitiesCache;
bool AddLog(const GWObjects::DeviceLog & Log); bool AddLog(const GWObjects::DeviceLog &Log);
bool AddStatisticsData(const GWObjects::Statistics & Stats); bool AddStatisticsData(const GWObjects::Statistics &Stats);
bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, bool GetStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::Statistics> &Stats); std::vector<GWObjects::Statistics> &Stats);
bool GetNumberOfStatisticsDataRecords(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, std::uint64_t &Count); bool GetNumberOfStatisticsDataRecords(std::string &SerialNumber, uint64_t FromDate,
bool DeleteStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate ); uint64_t ToDate, std::uint64_t &Count);
bool GetNewestStatisticsData(std::string &SerialNumber, uint64_t HowMany, std::vector<GWObjects::Statistics> &Stats); bool DeleteStatisticsData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate);
bool GetNewestStatisticsData(std::string &SerialNumber, uint64_t HowMany,
std::vector<GWObjects::Statistics> &Stats);
bool AddHealthCheckData(const GWObjects::HealthCheck &Check); bool AddHealthCheckData(const GWObjects::HealthCheck &Check);
bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, bool GetHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::HealthCheck> &Checks); std::vector<GWObjects::HealthCheck> &Checks);
bool DeleteHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate ); bool DeleteHealthCheckData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate);
bool GetNewestHealthCheckData(std::string &SerialNumber, uint64_t HowMany, bool GetNewestHealthCheckData(std::string &SerialNumber, uint64_t HowMany,
std::vector<GWObjects::HealthCheck> &Checks); std::vector<GWObjects::HealthCheck> &Checks);
bool UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration, uint64_t & NewUUID ); bool UpdateDeviceConfiguration(std::string &SerialNumber, std::string &Configuration,
uint64_t &NewUUID);
bool CreateDevice(GWObjects::Device &); bool CreateDevice(GWObjects::Device &);
bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps, std::string & Firmware, const Poco::Net::IPAddress & IPAddress); bool CreateDefaultDevice(std::string &SerialNumber, const Config::Capabilities &Caps,
std::string &Firmware, const Poco::Net::IPAddress &IPAddress);
bool GetDevice(std::string &SerialNumber, GWObjects::Device &); bool GetDevice(std::string &SerialNumber, GWObjects::Device &);
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices, const std::string & orderBy=""); bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<GWObjects::Device> &Devices,
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select, std::vector<GWObjects::Device> &Devices, const std::string & orderBy=""); const std::string &orderBy = "");
// bool GetDevices(uint64_t From, uint64_t HowMany, const std::string & Select,
//std::vector<GWObjects::Device> &Devices, const std::string & orderBy="");
bool DeleteDevice(std::string &SerialNumber); bool DeleteDevice(std::string &SerialNumber);
bool UpdateDevice(GWObjects::Device &); bool UpdateDevice(GWObjects::Device &);
bool DeviceExists(std::string & SerialNumber); bool DeviceExists(std::string &SerialNumber);
bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware); bool SetConnectInfo(std::string &SerialNumber, std::string &Firmware);
bool GetDeviceCount(uint64_t & Count); bool GetDeviceCount(uint64_t &Count);
bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany, std::vector<std::string> & SerialNumbers, const std::string & orderBy=""); bool GetDeviceSerialNumbers(uint64_t From, uint64_t HowMany,
bool GetDeviceFWUpdatePolicy(std::string & SerialNumber, std::string & Policy); std::vector<std::string> &SerialNumbers,
bool SetDevicePassword(std::string & SerialNumber, std::string & Password); const std::string &orderBy = "");
bool GetDeviceFWUpdatePolicy(std::string &SerialNumber, std::string &Policy);
bool SetDevicePassword(std::string &SerialNumber, std::string &Password);
bool UpdateSerialNumberCache(); bool UpdateSerialNumberCache();
static void GetDeviceDbFieldList( Types::StringVec & Fields); static void GetDeviceDbFieldList(Types::StringVec &Fields);
bool ExistingConfiguration(std::string &SerialNumber, uint64_t CurrentConfig, std::string &NewConfig, uint64_t &); bool ExistingConfiguration(std::string &SerialNumber, uint64_t CurrentConfig,
std::string &NewConfig, uint64_t &);
bool UpdateDeviceCapabilities(std::string &SerialNumber, const Config::Capabilities & Capabilities); bool UpdateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Capabilities);
bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &); bool GetDeviceCapabilities(std::string &SerialNumber, GWObjects::Capabilities &);
bool DeleteDeviceCapabilities(std::string & SerialNumber); bool DeleteDeviceCapabilities(std::string &SerialNumber);
bool CreateDeviceCapabilities(std::string & SerialNumber, const Config::Capabilities & Capabilities); bool CreateDeviceCapabilities(std::string &SerialNumber,
const Config::Capabilities &Capabilities);
bool InitCapabilitiesCache(); bool InitCapabilitiesCache();
bool GetLogData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, bool GetLogData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
std::vector<GWObjects::DeviceLog> &Stats, uint64_t Type); uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::DeviceLog> &Stats,
bool DeleteLogData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Type); uint64_t Type);
bool GetNewestLogData(std::string &SerialNumber, uint64_t HowMany, std::vector<GWObjects::DeviceLog> &Stats, uint64_t Type); bool DeleteLogData(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Type);
bool GetNewestLogData(std::string &SerialNumber, uint64_t HowMany,
std::vector<GWObjects::DeviceLog> &Stats, uint64_t Type);
bool CreateDefaultConfiguration(std::string & name, GWObjects::DefaultConfiguration & DefConfig); bool CreateDefaultConfiguration(std::string &name,
bool DeleteDefaultConfiguration(std::string & name); GWObjects::DefaultConfiguration &DefConfig);
bool UpdateDefaultConfiguration(std::string & name, GWObjects::DefaultConfiguration & DefConfig); bool DeleteDefaultConfiguration(std::string &name);
bool GetDefaultConfiguration(std::string &name, GWObjects::DefaultConfiguration & DefConfig); bool UpdateDefaultConfiguration(std::string &name,
bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany, std::vector<GWObjects::DefaultConfiguration> &Devices); GWObjects::DefaultConfiguration &DefConfig);
bool FindDefaultConfigurationForModel(const std::string & Model, GWObjects::DefaultConfiguration & DefConfig ); bool GetDefaultConfiguration(std::string &name, GWObjects::DefaultConfiguration &DefConfig);
bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany,
std::vector<GWObjects::DefaultConfiguration> &Devices);
bool FindDefaultConfigurationForModel(const std::string &Model,
GWObjects::DefaultConfiguration &DefConfig);
uint64_t GetDefaultConfigurationsCount(); uint64_t GetDefaultConfigurationsCount();
bool DefaultConfigurationAlreadyExists(std::string &Name); bool DefaultConfigurationAlreadyExists(std::string &Name);
bool AddCommand(std::string & SerialNumber, GWObjects::CommandDetails & Command,CommandExecutionType Type); bool AddCommand(std::string &SerialNumber, GWObjects::CommandDetails &Command,
bool GetCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands); CommandExecutionType Type);
bool GetCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate,
uint64_t Offset, uint64_t HowMany,
std::vector<GWObjects::CommandDetails> &Commands);
bool DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate); bool DeleteCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate);
bool GetNonExecutedCommands( uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands ); bool GetNonExecutedCommands(uint64_t Offset, uint64_t HowMany,
bool UpdateCommand( std::string &UUID, GWObjects::CommandDetails & Command ); std::vector<GWObjects::CommandDetails> &Commands);
bool GetCommand( const std::string &UUID, GWObjects::CommandDetails & Command ); bool UpdateCommand(std::string &UUID, GWObjects::CommandDetails &Command);
bool DeleteCommand( std::string &UUID ); bool GetCommand(const std::string &UUID, GWObjects::CommandDetails &Command);
bool GetReadyToExecuteCommands( uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands ); bool DeleteCommand(std::string &UUID);
bool CommandExecuted(std::string & UUID); bool GetReadyToExecuteCommands(uint64_t Offset, uint64_t HowMany,
bool SetCommandLastTry(std::string & UUID); std::vector<GWObjects::CommandDetails> &Commands);
bool CommandCompleted(std::string & UUID, Poco::JSON::Object::Ptr ReturnVars, const std::chrono::duration<double, std::milli> & execution_time, bool FullCommand); bool CommandExecuted(std::string &UUID);
bool AttachFileDataToCommand(std::string & UUID, const std::stringstream &s, const std::string &Type); bool SetCommandLastTry(std::string &UUID);
bool CancelWaitFile( std::string & UUID, std::string & ErrorText ); bool CommandCompleted(std::string &UUID, Poco::JSON::Object::Ptr ReturnVars,
bool GetAttachedFileContent(std::string & UUID, const std::string & SerialNumber, std::string & FileContent, std::string &Type); const std::chrono::duration<double, std::milli> &execution_time,
bool RemoveAttachedFile(std::string & UUID); bool FullCommand);
bool SetCommandResult(std::string & UUID, std::string & Result); bool AttachFileDataToCommand(std::string &UUID, const std::stringstream &s,
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands); const std::string &Type);
bool SetCommandExecuted(std::string & CommandUUID); bool CancelWaitFile(std::string &UUID, std::string &ErrorText);
bool GetAttachedFileContent(std::string &UUID, const std::string &SerialNumber,
std::string &FileContent, std::string &Type);
bool RemoveAttachedFile(std::string &UUID);
bool SetCommandResult(std::string &UUID, std::string &Result);
bool GetNewestCommands(std::string &SerialNumber, uint64_t HowMany,
std::vector<GWObjects::CommandDetails> &Commands);
bool SetCommandExecuted(std::string &CommandUUID);
bool SetCommandTimedOut(std::string &CommandUUID); bool SetCommandTimedOut(std::string &CommandUUID);
bool SetCommandStatus(std::string & CommandUUID, std::uint64_t Error, const char *ErrorText); bool SetCommandStatus(std::string &CommandUUID, std::uint64_t Error, const char *ErrorText);
void RemovedExpiredCommands(); void RemovedExpiredCommands();
void RemoveTimedOutCommands(); void RemoveTimedOutCommands();
bool RemoveOldCommands(std::string & SerilNumber, std::string & Command); bool RemoveOldCommands(std::string &SerilNumber, std::string &Command);
bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> & Devices); bool AddBlackListDevices(std::vector<GWObjects::BlackListedDevice> &Devices);
bool AddBlackListDevice(GWObjects::BlackListedDevice & Device); bool AddBlackListDevice(GWObjects::BlackListedDevice &Device);
bool GetBlackListDevice(std::string & SerialNumber, GWObjects::BlackListedDevice & Device); bool GetBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
bool DeleteBlackListDevice(std::string & SerialNumber); bool DeleteBlackListDevice(std::string &SerialNumber);
bool IsBlackListed(const std::string &SerialNumber, std::string &reason, std::string &author, std::uint64_t &created); bool IsBlackListed(const std::string &SerialNumber, std::string &reason,
std::string &author, std::uint64_t &created);
bool IsBlackListed(const std::string &SerialNumber); bool IsBlackListed(const std::string &SerialNumber);
bool InitializeBlackListCache(); bool InitializeBlackListCache();
bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::BlackListedDevice> & Devices ); bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany,
bool UpdateBlackListDevice(std::string & SerialNumber, GWObjects::BlackListedDevice & Device); std::vector<GWObjects::BlackListedDevice> &Devices);
bool UpdateBlackListDevice(std::string &SerialNumber, GWObjects::BlackListedDevice &Device);
uint64_t GetBlackListDeviceCount(); uint64_t GetBlackListDeviceCount();
bool RemoveHealthChecksRecordsOlderThan(uint64_t Date); bool RemoveHealthChecksRecordsOlderThan(uint64_t Date);
@@ -197,16 +235,13 @@ namespace OpenWifi {
bool AnalyzeCommands(Types::CountedMap &R); bool AnalyzeCommands(Types::CountedMap &R);
bool AnalyzeDevices(GWObjects::Dashboard &D); bool AnalyzeDevices(GWObjects::Dashboard &D);
int Start() override; int Start() override;
void Stop() override; void Stop() override;
private: private:
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_;
};
std::unique_ptr<OpenWifi::ScriptDB> ScriptDB_; inline auto StorageService() { return Storage::instance(); }
};
inline auto StorageService() { return Storage::instance(); }
} // namespace
} // namespace OpenWifi

View File

@@ -2,27 +2,21 @@
// Created by stephane bourque on 2022-02-03. // Created by stephane bourque on 2022-02-03.
// //
#include "AP_WS_Server.h"
#include "TelemetryClient.h" #include "TelemetryClient.h"
#include "TelemetryStream.h" #include "AP_WS_Server.h"
#include "CommandManager.h" #include "CommandManager.h"
#include "TelemetryStream.h"
#include "Poco/Net/SSLException.h" #include "Poco/Net/SSLException.h"
#include "fmt/format.h" #include "fmt/format.h"
namespace OpenWifi { namespace OpenWifi {
TelemetryClient::TelemetryClient( TelemetryClient::TelemetryClient(std::string UUID, uint64_t SerialNumber,
std::string UUID, std::unique_ptr<Poco::Net::WebSocket> WSock,
uint64_t SerialNumber, Poco::Net::SocketReactor &Reactor, Poco::Logger &Logger)
std::unique_ptr<Poco::Net::WebSocket> WSock, : UUID_(std::move(UUID)), SerialNumber_(SerialNumber), Reactor_(Reactor), Logger_(Logger),
Poco::Net::SocketReactor& Reactor, WS_(std::move(WSock)) {
Poco::Logger &Logger):
UUID_(std::move(UUID)),
SerialNumber_(SerialNumber),
Reactor_(Reactor),
Logger_(Logger),
WS_(std::move(WSock)) {
CompleteStartup(); CompleteStartup();
} }
@@ -38,115 +32,126 @@ namespace OpenWifi {
WS_->setKeepAlive(true); WS_->setKeepAlive(true);
WS_->setMaxPayloadSize(2048); WS_->setMaxPayloadSize(2048);
WS_->setBlocking(false); WS_->setBlocking(false);
Reactor_.addEventHandler( Reactor_.addEventHandler(*WS_,
*WS_, Poco::NObserver<TelemetryClient, Poco::Net::ReadableNotification>( Poco::NObserver<TelemetryClient, Poco::Net::ReadableNotification>(
*this, &TelemetryClient::OnSocketReadable)); *this, &TelemetryClient::OnSocketReadable));
Reactor_.addEventHandler( Reactor_.addEventHandler(*WS_,
*WS_, Poco::NObserver<TelemetryClient, Poco::Net::ShutdownNotification>( Poco::NObserver<TelemetryClient, Poco::Net::ShutdownNotification>(
*this, &TelemetryClient::OnSocketShutdown)); *this, &TelemetryClient::OnSocketShutdown));
Reactor_.addEventHandler( Reactor_.addEventHandler(*WS_,
*WS_, Poco::NObserver<TelemetryClient, Poco::Net::ErrorNotification>( Poco::NObserver<TelemetryClient, Poco::Net::ErrorNotification>(
*this, &TelemetryClient::OnSocketError)); *this, &TelemetryClient::OnSocketError));
Registered_ = true; Registered_ = true;
poco_information(Logger(),fmt::format("TELEMETRY-CONNECTION({}): Connection completed.", CId_)); poco_information(Logger(),
fmt::format("TELEMETRY-CONNECTION({}): Connection completed.", CId_));
} }
TelemetryClient::~TelemetryClient() { TelemetryClient::~TelemetryClient() {
poco_information(Logger(),fmt::format("TELEMETRY-CONNECTION({}): Closing connection.", CId_)); poco_information(Logger(),
fmt::format("TELEMETRY-CONNECTION({}): Closing connection.", CId_));
DeRegister(); DeRegister();
} }
void TelemetryClient::DeRegister() { void TelemetryClient::DeRegister() {
if(Registered_) { if (Registered_) {
Registered_ = false; Registered_ = false;
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<TelemetryClient, *WS_, Poco::NObserver<TelemetryClient, Poco::Net::ReadableNotification>(
Poco::Net::ReadableNotification>(*this,&TelemetryClient::OnSocketReadable)); *this, &TelemetryClient::OnSocketReadable));
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<TelemetryClient, *WS_, Poco::NObserver<TelemetryClient, Poco::Net::ShutdownNotification>(
Poco::Net::ShutdownNotification>(*this,&TelemetryClient::OnSocketShutdown)); *this, &TelemetryClient::OnSocketShutdown));
Reactor_.removeEventHandler(*WS_, Reactor_.removeEventHandler(
Poco::NObserver<TelemetryClient, *WS_, Poco::NObserver<TelemetryClient, Poco::Net::ErrorNotification>(
Poco::Net::ErrorNotification>(*this,&TelemetryClient::OnSocketError)); *this, &TelemetryClient::OnSocketError));
} }
} }
bool TelemetryClient::Send(const std::string &Payload) { bool TelemetryClient::Send(const std::string &Payload) {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
size_t BytesSent = WS_->sendFrame(Payload.c_str(),(int)Payload.size()); size_t BytesSent = WS_->sendFrame(Payload.c_str(), (int)Payload.size());
return BytesSent == Payload.size(); return BytesSent == Payload.size();
} }
void TelemetryClient::SendTelemetryShutdown() { void TelemetryClient::SendTelemetryShutdown() {
poco_information(Logger(),fmt::format("TELEMETRY-SHUTDOWN({}): Closing.",CId_)); poco_information(Logger(), fmt::format("TELEMETRY-SHUTDOWN({}): Closing.", CId_));
DeRegister(); DeRegister();
AP_WS_Server()->StopWebSocketTelemetry(CommandManager()->Next_RPC_ID(), SerialNumber_); AP_WS_Server()->StopWebSocketTelemetry(CommandManager()->Next_RPC_ID(), SerialNumber_);
TelemetryStream()->DeRegisterClient(UUID_); TelemetryStream()->DeRegisterClient(UUID_);
} }
void TelemetryClient::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) { void TelemetryClient::OnSocketShutdown(
poco_information(Logger(),fmt::format("TELEMETRY-SOCKET-SHUTDOWN({}): Orderly shutdown.", CId_)); [[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
poco_information(Logger(),
fmt::format("TELEMETRY-SOCKET-SHUTDOWN({}): Orderly shutdown.", CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
void TelemetryClient::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf) { void TelemetryClient::OnSocketError(
poco_information(Logger(),fmt::format("TELEMETRY-SOCKET-ERROR({}): Closing.",CId_)); [[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
poco_information(Logger(), fmt::format("TELEMETRY-SOCKET-ERROR({}): Closing.", CId_));
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
void TelemetryClient::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf) { void TelemetryClient::OnSocketReadable(
try [[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
{ try {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
return ProcessIncomingFrame(); return ProcessIncomingFrame();
} } 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) {
std::string W = E.what(); std::string W = E.what();
poco_information(Logger(),fmt::format("TELEMETRY-std::exception caught: {}. Connection terminated with {}",W,CId_)); poco_information(
} Logger(),
catch ( ... ) { fmt::format("TELEMETRY-std::exception caught: {}. Connection terminated with {}", W,
poco_information(Logger(),fmt::format("TELEMETRY-Unknown exception for {}. Connection terminated.",CId_)); CId_));
} catch (...) {
poco_information(
Logger(),
fmt::format("TELEMETRY-Unknown exception for {}. Connection terminated.", CId_));
} }
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
void TelemetryClient::ProcessIncomingFrame() { void TelemetryClient::ProcessIncomingFrame() {
bool MustDisconnect=false; bool MustDisconnect = false;
Poco::Buffer<char> IncomingFrame(0); Poco::Buffer<char> IncomingFrame(0);
try { try {
int Op,flags; int Op, flags;
int IncomingSize; int IncomingSize;
IncomingSize = WS_->receiveFrame(IncomingFrame,flags); IncomingSize = WS_->receiveFrame(IncomingFrame, flags);
Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if (IncomingSize == 0 && flags == 0 && Op == 0) { if (IncomingSize == 0 && flags == 0 && Op == 0) {
poco_information(Logger(),fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_)); poco_information(
Logger(),
fmt::format("TELEMETRY-DISCONNECT({}): device has disconnected.", CId_));
MustDisconnect = true; MustDisconnect = true;
} else { } else {
if (Op == Poco::Net::WebSocket::FRAME_OP_PING) { if (Op == Poco::Net::WebSocket::FRAME_OP_PING) {
Logger().debug(fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_)); Logger().debug(
fmt::format("TELEMETRY-WS-PING({}): received. PONG sent back.", CId_));
WS_->sendFrame("", 0, WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG | (int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN); (int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
} else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) { } else if (Op == Poco::Net::WebSocket::FRAME_OP_CLOSE) {
poco_information(Logger(),fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_)); poco_information(
MustDisconnect = true ; Logger(),
fmt::format("TELEMETRY-DISCONNECT({}): device wants to disconnect.", CId_));
MustDisconnect = true;
} }
} }
} catch (...) { } catch (...) {
MustDisconnect = true ; MustDisconnect = true;
} }
if(!MustDisconnect) if (!MustDisconnect)
return; return;
SendTelemetryShutdown(); SendTelemetryShutdown();
} }
} } // namespace OpenWifi

View File

@@ -4,46 +4,44 @@
#pragma once #pragma once
#include <string>
#include <mutex> #include <mutex>
#include <string>
#include "Poco/AutoPtr.h" #include "Poco/AutoPtr.h"
#include "Poco/Logger.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketReactor.h" #include "Poco/Net/SocketReactor.h"
#include "Poco/Net/WebSocket.h" #include "Poco/Net/WebSocket.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Logger.h"
namespace OpenWifi { namespace OpenWifi {
class TelemetryClient { class TelemetryClient {
static constexpr int BufSize = 64000; static constexpr int BufSize = 64000;
public: public:
TelemetryClient( TelemetryClient(std::string UUID, uint64_t SerialNumber,
std::string UUID, std::unique_ptr<Poco::Net::WebSocket> WSock,
uint64_t SerialNumber, Poco::Net::SocketReactor &Reactor, Poco::Logger &Logger);
std::unique_ptr<Poco::Net::WebSocket> WSock,
Poco::Net::SocketReactor& Reactor,
Poco::Logger &Logger);
~TelemetryClient(); ~TelemetryClient();
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf); void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
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);
bool Send(const std::string &Payload); bool Send(const std::string &Payload);
void ProcessIncomingFrame(); void ProcessIncomingFrame();
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger &Logger() { return Logger_; }
private: private:
std::recursive_mutex Mutex_; std::recursive_mutex Mutex_;
std::string UUID_; std::string UUID_;
uint64_t SerialNumber_; uint64_t SerialNumber_;
Poco::Net::SocketReactor &Reactor_; Poco::Net::SocketReactor &Reactor_;
Poco::Logger &Logger_; Poco::Logger &Logger_;
Poco::Net::StreamSocket Socket_; Poco::Net::StreamSocket Socket_;
std::string CId_; std::string CId_;
std::unique_ptr<Poco::Net::WebSocket> WS_; std::unique_ptr<Poco::Net::WebSocket> WS_;
bool Registered_=false; bool Registered_ = false;
void SendTelemetryShutdown(); void SendTelemetryShutdown();
void CompleteStartup(); void CompleteStartup();
void DeRegister(); void DeRegister();
}; };
} } // namespace OpenWifi

View File

@@ -17,41 +17,42 @@ namespace OpenWifi {
int TelemetryStream::Start() { int TelemetryStream::Start() {
Running_ = true; Running_ = true;
ReactorThr_.start(Reactor_); ReactorThr_.start(Reactor_);
Utils::SetThreadName(ReactorThr_,"tel:reactor"); Utils::SetThreadName(ReactorThr_, "tel:reactor");
NotificationMgr_.start(*this); NotificationMgr_.start(*this);
return 0; return 0;
} }
void TelemetryStream::Stop() { void TelemetryStream::Stop() {
poco_information(Logger(),"Stopping..."); poco_information(Logger(), "Stopping...");
Running_ = false; Running_ = false;
Reactor_.stop(); Reactor_.stop();
ReactorThr_.join(); ReactorThr_.join();
MsgQueue_.wakeUpAll(); MsgQueue_.wakeUpAll();
NotificationMgr_.wakeUp(); NotificationMgr_.wakeUp();
NotificationMgr_.join(); NotificationMgr_.join();
poco_information(Logger(),"Stopped..."); poco_information(Logger(), "Stopped...");
} }
bool TelemetryStream::IsValidEndPoint(uint64_t SerialNumber, const std::string & UUID) { bool TelemetryStream::IsValidEndPoint(uint64_t SerialNumber, const std::string &UUID) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
auto U = Clients_.find(UUID); auto U = Clients_.find(UUID);
if(U == Clients_.end() ) if (U == Clients_.end())
return false; return false;
auto N = SerialNumbers_.find(SerialNumber); auto N = SerialNumbers_.find(SerialNumber);
if(N == SerialNumbers_.end()) if (N == SerialNumbers_.end())
return false; return false;
return (N->second.find(UUID) != N->second.end()); return (N->second.find(UUID) != N->second.end());
} }
bool TelemetryStream::CreateEndpoint(uint64_t SerialNumber, std::string &EndPoint, const std::string &UUID) { bool TelemetryStream::CreateEndpoint(uint64_t SerialNumber, std::string &EndPoint,
std::lock_guard G(Mutex_); const std::string &UUID) {
std::lock_guard G(Mutex_);
Poco::URI Public(MicroServiceConfigGetString("openwifi.system.uri.public","")); Poco::URI Public(MicroServiceConfigGetString("openwifi.system.uri.public", ""));
Poco::URI U; Poco::URI U;
U.setScheme("wss"); U.setScheme("wss");
U.setHost(Public.getHost()); U.setHost(Public.getHost());
U.setPort(Public.getPort()); U.setPort(Public.getPort());
@@ -73,60 +74,74 @@ namespace OpenWifi {
while (NextNotification && Running_) { while (NextNotification && Running_) {
auto Notification = dynamic_cast<TelemetryNotification *>(NextNotification.get()); auto Notification = dynamic_cast<TelemetryNotification *>(NextNotification.get());
if (Notification != nullptr) { if (Notification != nullptr) {
std::lock_guard Lock(Mutex_); std::lock_guard Lock(Mutex_);
switch( Notification->Type_ ) { switch (Notification->Type_) {
case TelemetryNotification::NotificationType::data : { case TelemetryNotification::NotificationType::data: {
auto SerialNumberSetOfUUIDs = SerialNumbers_.find(Notification->SerialNumber_); auto SerialNumberSetOfUUIDs = SerialNumbers_.find(Notification->SerialNumber_);
if (SerialNumberSetOfUUIDs != SerialNumbers_.end()) { if (SerialNumberSetOfUUIDs != SerialNumbers_.end()) {
for (auto &uuid : SerialNumberSetOfUUIDs->second) { for (auto &uuid : SerialNumberSetOfUUIDs->second) {
auto Client = Clients_.find(uuid); auto Client = Clients_.find(uuid);
if (Client != Clients_.end() && Client->second != nullptr) { if (Client != Clients_.end() && Client->second != nullptr) {
try { try {
// std::cout << "Sent WS telemetry notification" << std::endl; // std::cout << "Sent WS telemetry notification" << std::endl;
Client->second->Send(Notification->Data_); Client->second->Send(Notification->Data_);
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (std::exception &E) { } catch (std::exception &E) {
poco_warning(Logger(),fmt::format("Std:Ex Cannot send WS telemetry notification: {} for SerialNumber: {}", E.what(), Utils::IntToSerialNumber(Notification->SerialNumber_))); poco_warning(
} Logger(),
} else { fmt::format(
poco_warning(Logger(),fmt::format("Cannot send WS telemetry notification for SerialNumber: {}", Utils::IntToSerialNumber(Notification->SerialNumber_))); "Std:Ex Cannot send WS telemetry notification: {} for "
"SerialNumber: {}",
E.what(),
Utils::IntToSerialNumber(Notification->SerialNumber_)));
} }
} else {
poco_warning(Logger(),
fmt::format("Cannot send WS telemetry notification "
"for SerialNumber: {}",
Utils::IntToSerialNumber(
Notification->SerialNumber_)));
} }
} else {
poco_warning(Logger(),fmt::format("Cannot find serial: {}", Utils::IntToSerialNumber(Notification->SerialNumber_)));
} }
} break; } else {
case TelemetryNotification::NotificationType::unregister : { poco_warning(Logger(), fmt::format("Cannot find serial: {}",
std::lock_guard G(Mutex_); Utils::IntToSerialNumber(
Notification->SerialNumber_)));
}
} break;
case TelemetryNotification::NotificationType::unregister: {
std::lock_guard G(Mutex_);
auto client = Clients_.find(Notification->Data_); auto client = Clients_.find(Notification->Data_);
if(client!=Clients_.end()) { if (client != Clients_.end()) {
for(auto i = SerialNumbers_.begin(); i!= SerialNumbers_.end();) { for (auto i = SerialNumbers_.begin(); i != SerialNumbers_.end();) {
i->second.erase(Notification->Data_); i->second.erase(Notification->Data_);
if(i->second.empty()) { if (i->second.empty()) {
i = SerialNumbers_.erase(i); i = SerialNumbers_.erase(i);
} else { } else {
++i; ++i;
}
} }
Clients_.erase(client);
} else {
poco_warning(Logger(),fmt::format("Unknown connection: {}", Notification->Data_));
} }
} break; Clients_.erase(client);
} else {
poco_warning(Logger(),
fmt::format("Unknown connection: {}", Notification->Data_));
}
} break;
default: { default: {
} break; } break;
} }
} }
NextNotification = MsgQueue_.waitDequeueNotification(); NextNotification = MsgQueue_.waitDequeueNotification();
} }
} }
bool TelemetryStream::NewClient(const std::string &UUID, uint64_t SerialNumber, std::unique_ptr<Poco::Net::WebSocket> Client) { bool TelemetryStream::NewClient(const std::string &UUID, uint64_t SerialNumber,
std::lock_guard G(Mutex_); std::unique_ptr<Poco::Net::WebSocket> Client) {
std::lock_guard G(Mutex_);
try { try {
Clients_[UUID] = std::make_unique<TelemetryClient>( Clients_[UUID] = std::make_unique<TelemetryClient>(
UUID, SerialNumber, std::move(Client), NextReactor(), Logger()); UUID, SerialNumber, std::move(Client), NextReactor(), Logger());
@@ -137,8 +152,12 @@ namespace OpenWifi {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger().log(E); Logger().log(E);
} catch (...) { } catch (...) {
poco_warning(Logger(),fmt::format("Could not create a telemetry client for session {} and serial number {}", UUID, SerialNumber)); poco_warning(
Logger(),
fmt::format(
"Could not create a telemetry client for session {} and serial number {}", UUID,
SerialNumber));
} }
return false; return false;
} }
} } // namespace OpenWifi

View File

@@ -6,20 +6,20 @@
#include <iostream> #include <iostream>
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPRequestHandler.h" #include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerRequestImpl.h" #include "Poco/Net/HTTPServerRequestImpl.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Notification.h"
#include "Poco/NotificationQueue.h"
#include "Poco/Timespan.h" #include "Poco/Timespan.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/NotificationQueue.h"
#include "Poco/Notification.h"
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
@@ -30,37 +30,28 @@ namespace OpenWifi {
class TelemetryNotification : public Poco::Notification { class TelemetryNotification : public Poco::Notification {
public: public:
enum class NotificationType { enum class NotificationType { data, unregister };
data,
unregister
};
explicit TelemetryNotification(std::uint64_t SerialNumber, const std::string &Payload) : explicit TelemetryNotification(std::uint64_t SerialNumber, const std::string &Payload)
Type_(NotificationType::data), : Type_(NotificationType::data), SerialNumber_(SerialNumber), Data_(Payload) {}
SerialNumber_(SerialNumber),
Data_(Payload) {
}
explicit TelemetryNotification(const std::string &UUID) : explicit TelemetryNotification(const std::string &UUID)
Type_(NotificationType::unregister), : Type_(NotificationType::unregister), Data_(UUID) {}
Data_(UUID) {
}
NotificationType Type_; NotificationType Type_;
std::uint64_t SerialNumber_=0; std::uint64_t SerialNumber_ = 0;
std::string Data_; std::string Data_;
}; };
class TelemetryStream : public SubSystemServer, Poco::Runnable { class TelemetryStream : public SubSystemServer, Poco::Runnable {
public: public:
struct QueueUpdate { struct QueueUpdate {
uint64_t SerialNumber; uint64_t SerialNumber;
std::string Payload; std::string Payload;
}; };
static auto instance() { static auto instance() {
static auto instance_ = new TelemetryStream; static auto instance_ = new TelemetryStream;
return instance_; return instance_;
} }
@@ -68,37 +59,36 @@ namespace OpenWifi {
void Stop() override; void Stop() override;
void run() final; void run() final;
bool IsValidEndPoint(uint64_t SerialNumber, const std::string & UUID); bool IsValidEndPoint(uint64_t SerialNumber, const std::string &UUID);
bool CreateEndpoint(uint64_t SerialNumber, std::string &EndPoint, const std::string &UUID); bool CreateEndpoint(uint64_t SerialNumber, std::string &EndPoint, const std::string &UUID);
inline void NotifyEndPoint(uint64_t SerialNumber, const std::string &PayLoad) { inline void NotifyEndPoint(uint64_t SerialNumber, const std::string &PayLoad) {
MsgQueue_.enqueueNotification(new TelemetryNotification(SerialNumber,PayLoad)); MsgQueue_.enqueueNotification(new TelemetryNotification(SerialNumber, PayLoad));
} }
inline void DeRegisterClient(const std::string &UUID) { inline void DeRegisterClient(const std::string &UUID) {
MsgQueue_.enqueueNotification(new TelemetryNotification(UUID)); MsgQueue_.enqueueNotification(new TelemetryNotification(UUID));
} }
bool NewClient(const std::string &UUID, uint64_t SerialNumber, std::unique_ptr<Poco::Net::WebSocket> Client); bool NewClient(const std::string &UUID, uint64_t SerialNumber,
std::unique_ptr<Poco::Net::WebSocket> Client);
Poco::Net::SocketReactor &NextReactor() { return Reactor_; }
Poco::Net::SocketReactor & NextReactor() { return Reactor_; }
private: private:
volatile std::atomic_bool Running_=false; volatile std::atomic_bool Running_ = false;
std::map<uint64_t, std::set<std::string>> SerialNumbers_; // serialNumber -> uuid std::map<uint64_t, std::set<std::string>> SerialNumbers_; // serialNumber -> uuid
Poco::Net::SocketReactor Reactor_; Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThr_; Poco::Thread ReactorThr_;
Poco::Thread NotificationMgr_; Poco::Thread NotificationMgr_;
Poco::NotificationQueue MsgQueue_; Poco::NotificationQueue MsgQueue_;
std::map<std::string, std::unique_ptr<TelemetryClient> > Clients_; // uuid -> client std::map<std::string, std::unique_ptr<TelemetryClient>> Clients_; // uuid -> client
TelemetryStream() noexcept: TelemetryStream() noexcept
SubSystemServer("TelemetryServer", "TELEMETRY-SVR", "openwifi.telemetry") { : SubSystemServer("TelemetryServer", "TELEMETRY-SVR", "openwifi.telemetry") {}
}
}; };
inline auto TelemetryStream() { return TelemetryStream::instance(); } inline auto TelemetryStream() { return TelemetryStream::instance(); }
} } // namespace OpenWifi

View File

@@ -7,154 +7,147 @@
namespace OpenWifi::GWWebSocketNotifications { namespace OpenWifi::GWWebSocketNotifications {
inline void SingleDevice::to_json(Poco::JSON::Object &Obj) const { inline void SingleDevice::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber);
} }
inline bool SingleDevice::from_json(const Poco::JSON::Object::Ptr &Obj) { inline bool SingleDevice::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
RESTAPI_utils::field_from_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_from_json(Obj, "serialNumber", serialNumber);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
inline void SingleDeviceConfigurationChange::to_json(Poco::JSON::Object &Obj) const { inline void SingleDeviceConfigurationChange::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber);
RESTAPI_utils::field_to_json(Obj,"oldUUID", oldUUID); RESTAPI_utils::field_to_json(Obj, "oldUUID", oldUUID);
RESTAPI_utils::field_to_json(Obj,"newUUID", newUUID); RESTAPI_utils::field_to_json(Obj, "newUUID", newUUID);
} }
inline bool SingleDeviceConfigurationChange::from_json(const Poco::JSON::Object::Ptr &Obj) { inline bool SingleDeviceConfigurationChange::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
RESTAPI_utils::field_from_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_from_json(Obj, "serialNumber", serialNumber);
RESTAPI_utils::field_from_json(Obj,"oldUUID", oldUUID); RESTAPI_utils::field_from_json(Obj, "oldUUID", oldUUID);
RESTAPI_utils::field_from_json(Obj,"newUUID", newUUID); RESTAPI_utils::field_from_json(Obj, "newUUID", newUUID);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
inline void SingleDeviceFirmwareChange::to_json(Poco::JSON::Object &Obj) const { inline void SingleDeviceFirmwareChange::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber);
RESTAPI_utils::field_to_json(Obj,"newFirmware", newFirmware); RESTAPI_utils::field_to_json(Obj, "newFirmware", newFirmware);
} }
inline bool SingleDeviceFirmwareChange::from_json(const Poco::JSON::Object::Ptr &Obj) { inline bool SingleDeviceFirmwareChange::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
RESTAPI_utils::field_from_json(Obj,"serialNumber", serialNumber); RESTAPI_utils::field_from_json(Obj, "serialNumber", serialNumber);
RESTAPI_utils::field_from_json(Obj,"newFirmware", newFirmware); RESTAPI_utils::field_from_json(Obj, "newFirmware", newFirmware);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
inline void NumberOfConnection::to_json(Poco::JSON::Object &Obj) const { inline void NumberOfConnection::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"numberOfDevices", numberOfDevices); RESTAPI_utils::field_to_json(Obj, "numberOfDevices", numberOfDevices);
RESTAPI_utils::field_to_json(Obj,"averageConnectedTime", averageConnectedTime); RESTAPI_utils::field_to_json(Obj, "averageConnectedTime", averageConnectedTime);
RESTAPI_utils::field_to_json(Obj,"numberOfConnectingDevices", numberOfConnectingDevices); RESTAPI_utils::field_to_json(Obj, "numberOfConnectingDevices", numberOfConnectingDevices);
} }
inline bool NumberOfConnection::from_json(const Poco::JSON::Object::Ptr &Obj) { inline bool NumberOfConnection::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
RESTAPI_utils::field_from_json(Obj,"numberOfDevices", numberOfDevices); RESTAPI_utils::field_from_json(Obj, "numberOfDevices", numberOfDevices);
RESTAPI_utils::field_from_json(Obj,"averageConnectedTime", averageConnectedTime); RESTAPI_utils::field_from_json(Obj, "averageConnectedTime", averageConnectedTime);
RESTAPI_utils::field_from_json(Obj,"numberOfConnectingDevices", numberOfConnectingDevices); RESTAPI_utils::field_from_json(Obj, "numberOfConnectingDevices",
numberOfConnectingDevices);
return true; return true;
} catch (...) { } catch (...) {
} }
return false; return false;
} }
void NumberOfConnections(NumberOfConnection_t &N) { void NumberOfConnections(NumberOfConnection_t &N) {
// N.type = "device_connections_statistics"; // N.type = "device_connections_statistics";
N.type_id = 1000 ; N.type_id = 1000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void NumberOfConnections(const std::string & User, NumberOfConnection_t &N) { void NumberOfConnections(const std::string &User, NumberOfConnection_t &N) {
// N.type = "device_connections_statistics"; // N.type = "device_connections_statistics";
N.type_id = 1000 ; N.type_id = 1000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceConfigurationChange(SingleDeviceConfigurationChange_t &N) { void DeviceConfigurationChange(SingleDeviceConfigurationChange_t &N) {
// N.type = "device_configuration_upgrade"; // N.type = "device_configuration_upgrade";
N.type_id = 2000 ; N.type_id = 2000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void DeviceConfigurationChange(const std::string & User, SingleDeviceConfigurationChange_t &N) { void DeviceConfigurationChange(const std::string &User, SingleDeviceConfigurationChange_t &N) {
// N.type = "device_configuration_upgrade"; // N.type = "device_configuration_upgrade";
N.type_id = 2000 ; N.type_id = 2000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceFirmwareUpdated(SingleDeviceFirmwareChange_t &N) { void DeviceFirmwareUpdated(SingleDeviceFirmwareChange_t &N) {
// N.type = "device_firmware_upgrade"; // N.type = "device_firmware_upgrade";
N.type_id = 3000 ; N.type_id = 3000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void DeviceFirmwareUpdated(const std::string & User, SingleDeviceFirmwareChange_t &N){ void DeviceFirmwareUpdated(const std::string &User, SingleDeviceFirmwareChange_t &N) {
// N.type = "device_firmware_upgrade"; // N.type = "device_firmware_upgrade";
N.type_id = 3000 ; N.type_id = 3000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceConnected(SingleDevice_t &N){ void DeviceConnected(SingleDevice_t &N) {
// N.type = "device_connection"; // N.type = "device_connection";
N.type_id = 4000 ; N.type_id = 4000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void DeviceConnected(const std::string & User, SingleDevice_t &N){ void DeviceConnected(const std::string &User, SingleDevice_t &N) {
// N.type = "device_connection"; // N.type = "device_connection";
N.type_id = 4000 ; N.type_id = 4000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceDisconnected(const std::string & User, SingleDevice_t &N){ void DeviceDisconnected(const std::string &User, SingleDevice_t &N) {
// N.type = "device_disconnection"; // N.type = "device_disconnection";
N.type_id = 5000 ; N.type_id = 5000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceDisconnected(SingleDevice_t &N){ void DeviceDisconnected(SingleDevice_t &N) {
// N.type = "device_disconnection"; // N.type = "device_disconnection";
N.type_id = 5000 ; N.type_id = 5000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void DeviceStatistics(const std::string & User, SingleDevice_t &N){ void DeviceStatistics(const std::string &User, SingleDevice_t &N) {
// N.type = "device_statistics"; // N.type = "device_statistics";
N.type_id = 6000 ; N.type_id = 6000;
UI_WebSocketClientServer()->SendUserNotification(User,N); UI_WebSocketClientServer()->SendUserNotification(User, N);
} }
void DeviceStatistics(SingleDevice_t &N){ void DeviceStatistics(SingleDevice_t &N) {
// N.type = "device_statistics"; // N.type = "device_statistics";
N.type_id = 6000 ; N.type_id = 6000;
UI_WebSocketClientServer()->SendNotification(N); UI_WebSocketClientServer()->SendNotification(N);
} }
void Register() { void Register() {
static const UI_WebSocketClientServer::NotificationTypeIdVec Notifications = { static const UI_WebSocketClientServer::NotificationTypeIdVec Notifications = {
{ 1000, "device_connections_statistics" }, {1000, "device_connections_statistics"}, {2000, "device_configuration_upgrade"},
{ 2000, "device_configuration_upgrade" }, {3000, "device_firmware_upgrade"}, {4000, "device_connection"},
{ 3000, "device_firmware_upgrade" }, {5000, "device_disconnection"}, {6000, "device_statistics"}};
{ 4000, "device_connection" },
{ 5000, "device_disconnection" },
{ 6000, "device_statistics" }
};
UI_WebSocketClientServer()->RegisterNotifications(Notifications); UI_WebSocketClientServer()->RegisterNotifications(Notifications);
} }
} } // namespace OpenWifi::GWWebSocketNotifications

View File

@@ -10,40 +10,41 @@
namespace OpenWifi::GWWebSocketNotifications { namespace OpenWifi::GWWebSocketNotifications {
struct SingleDevice { struct SingleDevice {
std::string serialNumber; std::string serialNumber;
inline void to_json(Poco::JSON::Object &Obj) const ; inline void to_json(Poco::JSON::Object &Obj) const;
inline bool from_json(const Poco::JSON::Object::Ptr &Obj); inline bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct SingleDeviceConfigurationChange { struct SingleDeviceConfigurationChange {
std::string serialNumber; std::string serialNumber;
uint64_t oldUUID; uint64_t oldUUID;
uint64_t newUUID; uint64_t newUUID;
inline void to_json(Poco::JSON::Object &Obj) const ; inline void to_json(Poco::JSON::Object &Obj) const;
inline bool from_json(const Poco::JSON::Object::Ptr &Obj); inline bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct SingleDeviceFirmwareChange { struct SingleDeviceFirmwareChange {
std::string serialNumber; std::string serialNumber;
std::string newFirmware; std::string newFirmware;
inline void to_json(Poco::JSON::Object &Obj) const ; inline void to_json(Poco::JSON::Object &Obj) const;
inline bool from_json(const Poco::JSON::Object::Ptr &Obj); inline bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct NumberOfConnection { struct NumberOfConnection {
std::uint64_t numberOfDevices=0; std::uint64_t numberOfDevices = 0;
std::uint64_t averageConnectedTime=0; std::uint64_t averageConnectedTime = 0;
std::uint64_t numberOfConnectingDevices=0; std::uint64_t numberOfConnectingDevices = 0;
inline void to_json(Poco::JSON::Object &Obj) const ; inline void to_json(Poco::JSON::Object &Obj) const;
inline bool from_json(const Poco::JSON::Object::Ptr &Obj); inline bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
void Register(); void Register();
typedef WebSocketNotification<SingleDevice> SingleDevice_t; typedef WebSocketNotification<SingleDevice> SingleDevice_t;
typedef WebSocketNotification<SingleDeviceConfigurationChange> SingleDeviceConfigurationChange_t; typedef WebSocketNotification<SingleDeviceConfigurationChange>
SingleDeviceConfigurationChange_t;
typedef WebSocketNotification<SingleDeviceFirmwareChange> SingleDeviceFirmwareChange_t; typedef WebSocketNotification<SingleDeviceFirmwareChange> SingleDeviceFirmwareChange_t;
typedef WebSocketNotification<NumberOfConnection> NumberOfConnection_t; typedef WebSocketNotification<NumberOfConnection> NumberOfConnection_t;
@@ -54,11 +55,11 @@ namespace OpenWifi::GWWebSocketNotifications {
void DeviceDisconnected(SingleDevice_t &N); void DeviceDisconnected(SingleDevice_t &N);
void DeviceStatistics(SingleDevice_t &N); void DeviceStatistics(SingleDevice_t &N);
void NumberOfConnections(const std::string & User, NumberOfConnection_t &N); void NumberOfConnections(const std::string &User, NumberOfConnection_t &N);
void DeviceConfigurationChange(const std::string & User, SingleDeviceConfigurationChange_t &N); void DeviceConfigurationChange(const std::string &User, SingleDeviceConfigurationChange_t &N);
void DeviceFirmwareUpdated(const std::string & User, SingleDeviceFirmwareChange_t &); void DeviceFirmwareUpdated(const std::string &User, SingleDeviceFirmwareChange_t &);
void DeviceConnected(const std::string & User, SingleDevice_t &N); void DeviceConnected(const std::string &User, SingleDevice_t &N);
void DeviceDisconnected(const std::string & User, SingleDevice_t &N); void DeviceDisconnected(const std::string &User, SingleDevice_t &N);
void DeviceStatistics(const std::string & User, SingleDevice_t &N); void DeviceStatistics(const std::string &User, SingleDevice_t &N);
}; }; // namespace OpenWifi::GWWebSocketNotifications

View File

@@ -7,8 +7,8 @@
#include "Poco/Notification.h" #include "Poco/Notification.h"
#include "Poco/NotificationQueue.h" #include "Poco/NotificationQueue.h"
#include "sdks/sdk_prov.h"
#include "AP_WS_Server.h" #include "AP_WS_Server.h"
#include "sdks/sdk_prov.h"
#include "framework/MicroServiceFuncs.h" #include "framework/MicroServiceFuncs.h"
#include "framework/SubSystemServer.h" #include "framework/SubSystemServer.h"
@@ -18,15 +18,12 @@ namespace OpenWifi {
class VenueBroadcastNotification : public Poco::Notification { class VenueBroadcastNotification : public Poco::Notification {
public: public:
VenueBroadcastNotification(const std::string &SourceSerialNumber, const std::string &Data, uint64_t TimeStamp) : VenueBroadcastNotification(const std::string &SourceSerialNumber, const std::string &Data,
SourceSerialNumber_(SourceSerialNumber), uint64_t TimeStamp)
Data_(Data), : SourceSerialNumber_(SourceSerialNumber), Data_(Data), TimeStamp_(TimeStamp) {}
TimeStamp_(TimeStamp) { std::string SourceSerialNumber_;
std::string Data_;
} uint64_t TimeStamp_ = Utils::Now();
std::string SourceSerialNumber_;
std::string Data_;
uint64_t TimeStamp_=Utils::Now();
}; };
class VenueBroadcaster : public SubSystemServer, Poco::Runnable { class VenueBroadcaster : public SubSystemServer, Poco::Runnable {
@@ -37,54 +34,57 @@ namespace OpenWifi {
} }
inline int Start() override { inline int Start() override {
Enabled_ = MicroServiceConfigGetBool("venue_broadcast.enabled",true); Enabled_ = MicroServiceConfigGetBool("venue_broadcast.enabled", true);
if(Enabled_) { if (Enabled_) {
BroadcastManager_.start(*this); BroadcastManager_.start(*this);
} }
return 0; return 0;
} }
inline void Stop() override { inline void Stop() override {
poco_information(Logger(),"Stopping..."); poco_information(Logger(), "Stopping...");
if(Enabled_ && Running_) { if (Enabled_ && Running_) {
BroadcastQueue_.wakeUpAll(); BroadcastQueue_.wakeUpAll();
BroadcastManager_.wakeUp(); BroadcastManager_.wakeUp();
BroadcastManager_.join(); BroadcastManager_.join();
} }
poco_information(Logger(),"Stopped..."); poco_information(Logger(), "Stopped...");
} }
inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override { inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override {
poco_information(Logger(),"Reinitializing."); poco_information(Logger(), "Reinitializing.");
} }
struct VenueInfo { struct VenueInfo {
uint64_t timestamp=Utils::Now(); uint64_t timestamp = Utils::Now();
Types::StringVec serialNumbers; Types::StringVec serialNumbers;
}; };
inline bool FindSerialNumberList(const std::string &Source, OpenWifi::Types::StringVec & SerialNumbers) { inline bool FindSerialNumberList(const std::string &Source,
OpenWifi::Types::StringVec &SerialNumbers) {
// Can we find our serial number in any of the lists so far... // Can we find our serial number in any of the lists so far...
for(const auto &venue:Venues_) { for (const auto &venue : Venues_) {
auto entry = std::find(venue.second.serialNumbers.begin(),venue.second.serialNumbers.end(),Source); auto entry = std::find(venue.second.serialNumbers.begin(),
if(entry!=venue.second.serialNumbers.end() && (Utils::Now()-venue.second.timestamp)<600) { venue.second.serialNumbers.end(), Source);
if (entry != venue.second.serialNumbers.end() &&
(Utils::Now() - venue.second.timestamp) < 600) {
SerialNumbers = venue.second.serialNumbers; SerialNumbers = venue.second.serialNumbers;
auto entry2 = std::find(SerialNumbers.begin(),SerialNumbers.end(),Source); auto entry2 = std::find(SerialNumbers.begin(), SerialNumbers.end(), Source);
SerialNumbers.erase(entry2); SerialNumbers.erase(entry2);
return true; return true;
} }
} }
// get the venue from Prov and the serial numbers. // get the venue from Prov and the serial numbers.
Types::UUID_t Venue; Types::UUID_t Venue;
Types::StringVec TmpSerialNumbers; Types::StringVec TmpSerialNumbers;
if(OpenWifi::SDK::Prov::GetSerialNumbersForVenueOfSerialNumber(Source,Venue,TmpSerialNumbers,Logger())) { if (OpenWifi::SDK::Prov::GetSerialNumbersForVenueOfSerialNumber(
std::sort(TmpSerialNumbers.begin(),TmpSerialNumbers.end()); Source, Venue, TmpSerialNumbers, Logger())) {
VenueInfo V{.timestamp=Utils::Now(), .serialNumbers=TmpSerialNumbers}; std::sort(TmpSerialNumbers.begin(), TmpSerialNumbers.end());
VenueInfo V{.timestamp = Utils::Now(), .serialNumbers = TmpSerialNumbers};
Venues_[Venue] = V; Venues_[Venue] = V;
auto p = std::find(TmpSerialNumbers.begin(),TmpSerialNumbers.end(),Source); auto p = std::find(TmpSerialNumbers.begin(), TmpSerialNumbers.end(), Source);
if(p!=TmpSerialNumbers.end()) { if (p != TmpSerialNumbers.end()) {
TmpSerialNumbers.erase(p); TmpSerialNumbers.erase(p);
SerialNumbers = TmpSerialNumbers; SerialNumbers = TmpSerialNumbers;
return true; return true;
@@ -94,57 +94,58 @@ namespace OpenWifi {
return false; return false;
} }
inline void SendToDevice(const std::string &SerialNumber,const std::string &Payload) { inline void SendToDevice(const std::string &SerialNumber, const std::string &Payload) {
AP_WS_Server()->SendFrame(SerialNumber,Payload); AP_WS_Server()->SendFrame(SerialNumber, Payload);
} }
inline void run() final { inline void run() final {
Running_ = true; Running_ = true;
Utils::SetThreadName("venue-bcast"); Utils::SetThreadName("venue-bcast");
Poco::AutoPtr<Poco::Notification> NextNotification(BroadcastQueue_.waitDequeueNotification()); Poco::AutoPtr<Poco::Notification> NextNotification(
BroadcastQueue_.waitDequeueNotification());
while (NextNotification && Running_) { while (NextNotification && Running_) {
auto Notification = dynamic_cast<VenueBroadcastNotification *>(NextNotification.get()); auto Notification =
dynamic_cast<VenueBroadcastNotification *>(NextNotification.get());
if (Notification != nullptr) { if (Notification != nullptr) {
Types::StringVec SerialNumbers; Types::StringVec SerialNumbers;
if(FindSerialNumberList(Notification->SourceSerialNumber_,SerialNumbers)) { if (FindSerialNumberList(Notification->SourceSerialNumber_, SerialNumbers)) {
Poco::JSON::Object Payload; Poco::JSON::Object Payload;
Payload.set("jsonrpc","2.0"); Payload.set("jsonrpc", "2.0");
Payload.set("method","venue_broadcast"); Payload.set("method", "venue_broadcast");
Poco::JSON::Object ParamBlock; Poco::JSON::Object ParamBlock;
ParamBlock.set("serial",Notification->SourceSerialNumber_); ParamBlock.set("serial", Notification->SourceSerialNumber_);
ParamBlock.set("timestamp",Notification->TimeStamp_); ParamBlock.set("timestamp", Notification->TimeStamp_);
ParamBlock.set("data",Notification->Data_); ParamBlock.set("data", Notification->Data_);
Payload.set("params", ParamBlock); Payload.set("params", ParamBlock);
std::ostringstream o; std::ostringstream o;
Payload.stringify(o); Payload.stringify(o);
for(const auto &Device:SerialNumbers) { for (const auto &Device : SerialNumbers) {
SendToDevice(Device,o.str()); SendToDevice(Device, o.str());
} }
} }
} }
NextNotification = BroadcastQueue_.waitDequeueNotification(); NextNotification = BroadcastQueue_.waitDequeueNotification();
} }
Running_=false; Running_ = false;
} }
inline void Broadcast(const std::string &SourceSerial, const std::string &Data, uint64_t TimeStamp) { inline void Broadcast(const std::string &SourceSerial, const std::string &Data,
BroadcastQueue_.enqueueNotification(new VenueBroadcastNotification(SourceSerial,Data,TimeStamp)); uint64_t TimeStamp) {
BroadcastQueue_.enqueueNotification(
new VenueBroadcastNotification(SourceSerial, Data, TimeStamp));
} }
private: private:
std::atomic_bool Running_=false; std::atomic_bool Running_ = false;
bool Enabled_=false; bool Enabled_ = false;
Poco::NotificationQueue BroadcastQueue_; Poco::NotificationQueue BroadcastQueue_;
Poco::Thread BroadcastManager_; Poco::Thread BroadcastManager_;
std::map<OpenWifi::Types::UUID_t,VenueInfo> Venues_; std::map<OpenWifi::Types::UUID_t, VenueInfo> Venues_;
VenueBroadcaster() noexcept: VenueBroadcaster() noexcept
SubSystemServer("VenueBroadcaster", "VENUE-BCAST", "venue.broacast") : SubSystemServer("VenueBroadcaster", "VENUE-BCAST", "venue.broacast") {}
{
}
}; };
inline auto VenueBroadcaster() { return VenueBroadcaster::instance(); } inline auto VenueBroadcaster() { return VenueBroadcaster::instance(); }
} } // namespace OpenWifi