stephb9959
2022-11-02 22:42:06 -07:00
parent 1688f5a39d
commit ccd5498f19
15 changed files with 320 additions and 101 deletions

View File

@@ -103,6 +103,7 @@ add_executable( owsec
src/framework/RESTAPI_RateLimiter.h
src/framework/WebSocketLogger.h
src/framework/RESTAPI_GenericServerAccounting.h
src/framework/RESTAPI_SystemConfiguration.h
src/framework/CIDR.h
src/framework/RESTAPI_Handler.cpp
src/framework/RESTAPI_Handler.h
@@ -168,7 +169,13 @@ add_executable( owsec
src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h
src/storage/orm_avatar.cpp src/storage/orm_avatar.h
src/SpecialUserHelpers.h
src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h src/MessagingTemplates.cpp src/MessagingTemplates.h)
src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h
src/RESTAPI/RESTAPI_totp_handler.cpp
src/RESTAPI/RESTAPI_totp_handler.h
src/TotpCache.h
src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h
src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h
src/MessagingTemplates.cpp src/MessagingTemplates.h)
if(NOT SMALL_BUILD)
target_link_libraries(owsec PUBLIC

2
build
View File

@@ -1 +1 @@
3
7

View File

@@ -50,6 +50,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"locale", locale);
field_to_json(Obj,"restrictedDevice", restrictedDevice);
}
void Device::to_json_with_status(Poco::JSON::Object &Obj) const {
@@ -70,6 +72,7 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"verifiedCertificate", "NO_CERTIFICATE");
field_to_json(Obj,"associations_2G", (uint64_t) 0);
field_to_json(Obj,"associations_5G", (uint64_t) 0);
field_to_json(Obj,"associations_6G", (uint64_t) 0);
}
#endif
}
@@ -89,6 +92,7 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"subscriber", subscriber);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"locale", locale);
field_from_json(Obj,"restrictedDevice", restrictedDevice);
return true;
} catch (const Poco::Exception &E) {
}
@@ -199,6 +203,7 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"lastContact", LastContact);
field_to_json(Obj,"associations_2G", Associations_2G);
field_to_json(Obj,"associations_5G", Associations_5G);
field_to_json(Obj,"associations_6G", Associations_6G);
field_to_json(Obj,"webSocketClients", webSocketClients);
field_to_json(Obj,"websocketPackets", websocketPackets);
field_to_json(Obj,"kafkaClients", kafkaClients);
@@ -208,6 +213,7 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"sessionId", sessionId);
field_to_json(Obj,"connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj,"totalConnectionTime", Utils::Now() - started);
field_to_json(Obj,"certificateExpiryDate", certificateExpiryDate);
switch(VerifiedCertificate) {
case NO_CERTIFICATE:
@@ -299,8 +305,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"timeout",timeout);
field_to_json(Obj,"type",type);
field_to_json(Obj,"script",script);
field_to_json(Obj,"scriptId",scriptId);
field_to_json(Obj,"when",when);
field_to_json(Obj,"signature", signature);
field_to_json(Obj,"deferred", deferred);
field_to_json(Obj,"uri", uri);
}
bool ScriptRequest::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -309,8 +317,10 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"timeout",timeout);
field_from_json(Obj,"type",type);
field_from_json(Obj,"script",script);
field_from_json(Obj,"scriptId",scriptId);
field_from_json(Obj,"when",when);
field_from_json(Obj,"signature", signature);
field_from_json(Obj,"deferred", deferred);
field_from_json(Obj,"uri", uri);
return true;
} catch (const Poco::Exception &E) {
}

View File

@@ -28,19 +28,21 @@ namespace OpenWifi::GWObjects {
uint64_t TX = 0, RX = 0;
uint64_t Associations_2G=0;
uint64_t Associations_5G=0;
uint64_t Associations_6G=0;
bool Connected = false;
uint64_t LastContact=0;
std::string Firmware;
CertificateValidation VerifiedCertificate = NO_CERTIFICATE;
std::string Compatible;
uint64_t kafkaClients=0;
uint64_t webSocketClients=0;
uint64_t kafkaPackets=0;
uint64_t websocketPackets=0;
std::string locale;
uint64_t started=0;
uint64_t sessionId=0;
double connectionCompletionTime=0.0;
std::string Compatible;
uint64_t kafkaClients=0;
uint64_t webSocketClients=0;
uint64_t kafkaPackets=0;
uint64_t websocketPackets=0;
std::string locale;
uint64_t started=0;
uint64_t sessionId=0;
double connectionCompletionTime=0.0;
std::uint64_t certificateExpiryDate=0;
void to_json(Poco::JSON::Object &Obj) const;
};
@@ -68,6 +70,7 @@ namespace OpenWifi::GWObjects {
std::string entity;
uint64_t modified=0;
std::string locale;
bool restrictedDevice=false;
void to_json(Poco::JSON::Object &Obj) const;
void to_json_with_status(Poco::JSON::Object &Obj) const;
@@ -214,12 +217,15 @@ namespace OpenWifi::GWObjects {
};
struct ScriptRequest {
uint64_t timeout=30;
std::string serialNumber;
uint64_t timeout=30;
std::string type;
std::string script;
std::string scriptId;
uint64_t when=0;
std::uint64_t when;
std::string signature;
bool deferred;
std::string uri;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};

View File

@@ -8,6 +8,7 @@
#include "Poco/FormattingChannel.h"
#include "Poco/AsyncChannel.h"
#include "Poco/NullChannel.h"
#include "Poco/SplitterChannel.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/FTPSStreamFactory.h"
@@ -26,7 +27,7 @@
#include "framework/RESTAPI_ExtServer.h"
#include "framework/RESTAPI_IntServer.h"
#include "framework/utils.h"
#include "framework/WebSocketLogger.h"
namespace OpenWifi {
@@ -193,6 +194,8 @@ namespace OpenWifi {
auto LoggingFormat = MicroService::instance().ConfigGetString("logging.format",
"%Y-%m-%d %H:%M:%S.%i %s: [%p][thr:%I] %t");
auto UseAsyncLogs_ = MicroService::instance().ConfigGetBool("logging.asynch",false);
auto DisableWebSocketLogging = MicroService::instance().ConfigGetBool("logging.websocket",false);
if (LoggingDestination == "null") {
Poco::AutoPtr<Poco::NullChannel> DevNull(new Poco::NullChannel);
Poco::Logger::root().setChannel(DevNull);
@@ -240,25 +243,62 @@ namespace OpenWifi {
Poco::AutoPtr<Poco::FileChannel> FileChannel(new Poco::FileChannel);
FileChannel->setProperty("rotation", "10 M");
FileChannel->setProperty("archive", "timestamp");
FileChannel->setProperty("purgeCount", "10");
FileChannel->setProperty("path", LoggingLocation);
if(UseAsyncLogs_) {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::AsyncChannel> Async_File(
new Poco::AsyncChannel(FileChannel));
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
std::cout << __LINE__ << std::endl;
Formatter->setProperty("pattern", LoggingFormat);
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, Async_File));
Poco::Logger::root().setChannel(FormattingChannel);
std::cout << __LINE__ << std::endl;
if(DisableWebSocketLogging) {
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(FormattingChannel);
} else {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<WebSocketLogger> WSLogger(new WebSocketLogger);
Poco::AutoPtr<Poco::SplitterChannel> Splitter(new Poco::SplitterChannel);
Splitter->addChannel(WSLogger);
Splitter->addChannel(FormattingChannel);
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(Splitter);
}
} else {
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
Formatter->setProperty("pattern", LoggingFormat);
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, FileChannel));
Poco::Logger::root().setChannel(FormattingChannel);
if(DisableWebSocketLogging) {
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(FormattingChannel);
} else {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::SplitterChannel> Splitter(new Poco::SplitterChannel);
Poco::AutoPtr<WebSocketLogger> WSLogger(new WebSocketLogger);
Splitter->addChannel(WSLogger);
Splitter->addChannel(FormattingChannel);
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(Splitter);
}
std::cout << __LINE__ << std::endl;
}
}
auto Level = Poco::Logger::parseLevel(MicroService::instance().ConfigGetString("logging.level", "debug"));
Poco::Logger::root().setLevel(Level);
if(!DisableWebSocketLogging) {
static const UI_WebSocketClientServer::NotificationTypeIdVec Notifications = {
{1, "log"}};
UI_WebSocketClientServer()->RegisterNotifications(Notifications);
}
}
}
@@ -630,4 +670,15 @@ namespace OpenWifi {
}
}
void MicroService::DeleteOverrideConfiguration() {
Poco::File F(DataDir_ + ExtraConfigurationFilename);
try {
if(F.exists())
F.remove();
} catch (...) {
}
}
}

View File

@@ -81,6 +81,8 @@ namespace OpenWifi {
// Logger_ = Poco::Logger::root().get("BASE-SVC");
}
inline static const char * ExtraConfigurationFilename = "/configuration_override.json";
inline void SaveConfig() { PropConfigurationFile_->save(ConfigFileName_); }
inline auto UpdateConfig() { return PropConfigurationFile_; }
inline bool NoAPISecurity() const { return NoAPISecurity_; }
@@ -151,6 +153,8 @@ namespace OpenWifi {
int main(const ArgVec &args) override;
void InitializeLoggingSystem();
void DeleteOverrideConfiguration();
[[nodiscard]] std::string Sign(Poco::JWT::Token &T, const std::string &Algo);
void AddActivity(const std::string &Activity);

View File

@@ -114,4 +114,8 @@ namespace OpenWifi {
std::string MicroServiceGetPublicAPIEndPoint() {
return MicroService::instance().GetPublicAPIEndPoint();
}
void MicroServiceDeleteOverrideConfiguration() {
return MicroService::instance().DeleteOverrideConfiguration();
}
}

View File

@@ -52,4 +52,5 @@ namespace OpenWifi {
std::uint64_t MicroServiceRandom(std::uint64_t Range);
std::string MicroServiceSign(Poco::JWT::Token &T, const std::string &Algo);
std::string MicroServiceGetPublicAPIEndPoint();
void MicroServiceDeleteOverrideConfiguration();
}

View File

@@ -0,0 +1,52 @@
//
// Created by stephane bourque on 2022-10-31.
//
#pragma once
#include "framework/RESTAPI_Handler.h"
#include "framework/MicroServiceFuncs.h"
using namespace std::chrono_literals;
namespace OpenWifi {
class RESTAPI_system_configuration : public RESTAPIHandler {
public:
RESTAPI_system_configuration(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/systemConfiguration"}; }
inline void DoPost() final {}
inline void DoGet() final {
return OK();
}
inline void DoPut() final{
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
return OK();
};
inline void DoDelete() final{
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
MicroServiceDeleteOverrideConfiguration();
return OK();
};
};
}

View File

@@ -16,7 +16,7 @@ namespace OpenWifi {
inline RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{ Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal,false) {}
static auto PathName() { return std::list<std::string>{"/api/v1/ws"};}
void DoGet() final {

View File

@@ -10,11 +10,13 @@
namespace OpenWifi {
template<typename ContentStruct>
struct WebSocketNotification {
inline static uint64_t xid = 1;
uint64_t notification_id = ++xid;
std::string type;
ContentStruct content;
uint64_t notification_id = ++xid;
// std::string type;
std::uint64_t type_id=0;
ContentStruct content;
void to_json(Poco::JSON::Object &Obj) const;
@@ -24,7 +26,8 @@ namespace OpenWifi {
template<typename ContentStruct>
void WebSocketNotification<ContentStruct>::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj, "notification_id", notification_id);
RESTAPI_utils::field_to_json(Obj, "type", type);
// RESTAPI_utils::field_to_json(Obj, "type", type);
RESTAPI_utils::field_to_json(Obj, "type_id", type_id);
RESTAPI_utils::field_to_json(Obj, "content", content);
}
@@ -32,8 +35,9 @@ namespace OpenWifi {
bool WebSocketNotification<ContentStruct>::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj, "notification_id", notification_id);
RESTAPI_utils::field_from_json(Obj, "content", content);
RESTAPI_utils::field_from_json(Obj, "type", type);
// RESTAPI_utils::field_from_json(Obj, "type", type);
RESTAPI_utils::field_from_json(Obj, "type_id", type_id);
RESTAPI_utils::field_from_json(Obj, "content", content);
return true;
} catch (...) {

View File

@@ -39,6 +39,7 @@ namespace OpenWifi {
*this, &UI_WebSocketClientServer::OnSocketError));
Client->SocketRegistered_ = true;
Clients_[ClientSocket] = std::move(Client);
UsersConnected_ = Clients_.size();
}
void UI_WebSocketClientServer::SetProcessor( UI_WebSocketClientProcessor * F) {
@@ -65,6 +66,7 @@ namespace OpenWifi {
Poco::Net::ErrorNotification>(*this,&UI_WebSocketClientServer::OnSocketError));
}
Clients_.erase(Client);
UsersConnected_ = Clients_.size();
std::cout << "How many clients: " << Clients_.size() << std::endl;
}
@@ -101,39 +103,37 @@ namespace OpenWifi {
}
};
bool UI_WebSocketClientServer::SendToId(const std::string &Id, const std::string &Payload) {
std::lock_guard G(Mutex_);
for(const auto &Client:Clients_) {
if(Client.second->Id_==Id)
return Client.second->WS_->sendFrame(Payload.c_str(),(int)Payload.size());
}
return false;
bool UI_WebSocketClientServer::IsFiltered(std::uint64_t id, const OpenWifi::UI_WebSocketClientInfo &Client) {
return std::find(Client.Filter_.begin(), Client.Filter_.end(),id)!=end(Client.Filter_);
}
bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, const std::string &Payload) {
bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id, const std::string &Payload) {
std::lock_guard G(Mutex_);
uint64_t Sent=0;
for(const auto &client:Clients_) {
if(client.second->UserName_ == UserName) {
for(const auto &Client:Clients_) {
if(Client.second->UserName_ == UserName) {
try {
if (client.second->WS_->sendFrame(Payload.c_str(),(int)Payload.size()))
Sent++;
if(!IsFiltered(id,*Client.second) && Client.second->Authenticated_) {
return Client.second->WS_->sendFrame(
Payload.c_str(), (int)Payload.size()) == (int)Payload.size();
} else {
return false;
}
} catch (...) {
return false;
}
}
}
return Sent>0;
return false;
}
void UI_WebSocketClientServer::SendToAll(const std::string &Payload) {
void UI_WebSocketClientServer::SendToAll(std::uint64_t id, const std::string &Payload) {
std::lock_guard G(Mutex_);
for(const auto &client:Clients_) {
for(const auto &Client:Clients_) {
try {
client.second->WS_->sendFrame(Payload.c_str(),(int)Payload.size());
if(!IsFiltered(id,*Client.second) && Client.second->Authenticated_)
Client.second->WS_->sendFrame(Payload.c_str(),(int)Payload.size());
} catch (...) {
}
@@ -144,6 +144,29 @@ namespace OpenWifi {
return Clients_.find(ClientSocket);
}
void UI_WebSocketClientServer::SortNotifications() {
struct {
bool operator()(const NotificationEntry &A, const NotificationEntry & B) const {
return A.id < B.id; };
} CompareNotifications;
std::sort(NotificationTypes_.begin(), NotificationTypes_.end(), CompareNotifications);
NotificationTypesJSON_.clear();
Poco::JSON::Array AllNotifications;
for(const auto &notification:NotificationTypes_) {
Poco::JSON::Object Notification;
Notification.set("id", notification.id);
Notification.set("helper", notification.helper);
AllNotifications.add(Notification);
}
NotificationTypesJSON_.set("notificationTypes", AllNotifications);
}
void UI_WebSocketClientServer::RegisterNotifications(const OpenWifi::UI_WebSocketClientServer::NotificationTypeIdVec &Notifications) {
std::copy(Notifications.begin(), Notifications.end(), std::back_inserter(NotificationTypes_));
SortNotifications();
}
void UI_WebSocketClientServer::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
std::lock_guard G(LocalMutex_);
auto Client = FindWSClient(G,pNf->socket().impl()->sockfd());
@@ -188,6 +211,7 @@ namespace OpenWifi {
return EndConnection(G, Client);
} break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
constexpr const char *DropMessagesCommand = "drop-notifications";
IncomingFrame.append(0);
if (!Client->second->Authenticated_) {
std::string Frame{IncomingFrame.begin()};
@@ -198,19 +222,36 @@ namespace OpenWifi {
Client->second->Authenticated_ = true;
Client->second->UserName_ = Client->second->UserInfo_.userinfo.email;
poco_debug(Logger(),fmt::format("START({}): {} UI Client is starting WS connection.", Client->second->Id_, Client->second->UserName_));
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
Client->second->WS_->sendFrame(S.c_str(), S.size());
auto WelcomeMessage = NotificationTypesJSON_;
WelcomeMessage.set("success", "Welcome! Bienvenue! Bienvenidos!");
std::ostringstream OS;
WelcomeMessage.stringify(OS);
Client->second->WS_->sendFrame(OS.str().c_str(), (int) OS.str().size());
Client->second->UserName_ = Client->second->UserInfo_.userinfo.email;
} else {
std::string S{"Invalid token. Closing connection."};
Client->second->WS_->sendFrame(S.c_str(), S.size());
Poco::JSON::Object WelcomeMessage;
WelcomeMessage.set("error", "Invalid token. Closing connection.");
std::ostringstream OS;
WelcomeMessage.stringify(OS);
Client->second->WS_->sendFrame(OS.str().c_str(), (int) OS.str().size());
Client->second->WS_->sendFrame(OS.str().c_str(), (int) OS.str().size());
return EndConnection(G, Client);
}
} else {
Poco::JSON::Parser P;
auto Obj =
P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>();
if(Obj->has(DropMessagesCommand) && Obj->isArray(DropMessagesCommand)) {
auto Filters = Obj->getArray(DropMessagesCommand);
Client->second->Filter_.clear();
for(const auto &Filter:*Filters) {
Client->second->Filter_.emplace_back( (std::uint64_t) Filter);
}
std::sort(begin(Client->second->Filter_),end(Client->second->Filter_));
return;
}
std::string Answer;
bool CloseConnection=false;
if (Processor_ != nullptr) {

View File

@@ -19,8 +19,6 @@
namespace OpenWifi {
class UI_WebSocketClient;
class UI_WebSocketClientProcessor {
public:
virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done ) = 0;
@@ -33,6 +31,7 @@ namespace OpenWifi {
std::string UserName_;
bool Authenticated_ = false;
bool SocketRegistered_=false;
std::vector<std::uint64_t> Filter_;
SecurityObjects::UserInfoAndPolicy UserInfo_;
UI_WebSocketClientInfo(Poco::Net::WebSocket &WS, const std::string &Id, const std::string &username) {
@@ -50,6 +49,10 @@ namespace OpenWifi {
return instance_;
}
bool IsAnyoneConnected() {
return UsersConnected_;
}
int Start() override;
void Stop() override;
void run() override;
@@ -69,7 +72,7 @@ namespace OpenWifi {
std::ostringstream OO;
Msg.stringify(OO);
return SendToUser(userName,OO.str());
return SendToUser(userName, Notification.type_id, OO.str());
}
template <typename T> void SendNotification(const WebSocketNotification<T> &Notification) {
@@ -79,16 +82,26 @@ namespace OpenWifi {
Msg.set("notification",Payload);
std::ostringstream OO;
Msg.stringify(OO);
SendToAll(OO.str());
SendToAll(Notification.type_id, OO.str());
}
[[nodiscard]] bool SendToId(const std::string &Id, const std::string &Payload);
[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload);
void SendToAll(const std::string &Payload);
[[nodiscard]] bool SendToUser(const std::string &userName, std::uint64_t id, const std::string &Payload);
void SendToAll(std::uint64_t id, const std::string &Payload);
struct NotificationEntry {
std::uint64_t id=0;
std::string helper;
};
using ClientList = std::map<int,std::unique_ptr<UI_WebSocketClientInfo>>;
using NotificationTypeIdVec = std::vector<NotificationEntry>;
void RegisterNotifications(const NotificationTypeIdVec & Notifications);
bool IsFiltered(std::uint64_t id, const UI_WebSocketClientInfo &Client);
private:
mutable std::atomic_bool Running_ = false;
std::atomic_uint64_t UsersConnected_=0;
Poco::Thread Thr_;
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
@@ -97,6 +110,9 @@ namespace OpenWifi {
std::string GoogleApiKey_;
ClientList Clients_;
UI_WebSocketClientProcessor *Processor_ = nullptr;
NotificationTypeIdVec NotificationTypes_;
Poco::JSON::Object NotificationTypesJSON_;
UI_WebSocketClientServer() noexcept;
void EndConnection(std::lock_guard<std::recursive_mutex> &G, ClientList::iterator & Client);
@@ -106,7 +122,7 @@ namespace OpenWifi {
ClientList::iterator FindWSClient( std::lock_guard<std::recursive_mutex> &G, int ClientSocket);
void SortNotifications();
};
inline auto UI_WebSocketClientServer() { return UI_WebSocketClientServer::instance(); }

View File

@@ -5,29 +5,39 @@
#pragma once
#include "framework/SubSystemServer.h"
#include "framework/UI_WebSocketClientServer.h"
#include "framework/UI_WebSocketClientNotifications.h"
namespace OpenWifi {
class WebSocketLogger : public Poco::Channel {
public:
inline std::string getProperty( [[maybe_unused]] const std::string &p ) const final {
WebSocketLogger() {
}
~WebSocketLogger() {
}
std::string getProperty( [[maybe_unused]] const std::string &p ) const {
std::cout << "WS getProperty" << std::endl;
return "";
}
inline void close() final {
void close() final {
}
inline void open() final {
void open() final {
}
inline static std::string to_string(Poco::Message::Priority p) {
static std::string to_string(Poco::Message::Priority p) {
switch(p) {
case Poco::Message::PRIO_INFORMATION: return "information";
case Poco::Message::PRIO_CRITICAL: return "critical";
case Poco::Message::PRIO_DEBUG: return "debug";
case Poco::Message::PRIO_ERROR: return "error";
case Poco::Message::PRIO_FATAL: return "level";
case Poco::Message::PRIO_FATAL: return "fatal";
case Poco::Message::PRIO_NOTICE: return "notice";
case Poco::Message::PRIO_TRACE: return "trace";
case Poco::Message::PRIO_WARNING: return "warning";
@@ -35,55 +45,63 @@ namespace OpenWifi {
}
}
inline void log(const Poco::Message &m) final {
if(Enabled_) {
/*
nlohmann::json log_msg;
log_msg["msg"] = m.getText();
log_msg["level"] = to_string(m.getPriority());
log_msg["timestamp"] = Poco::DateTimeFormatter::format(m.getTime(), Poco::DateTimeFormat::ISO8601_FORMAT);
log_msg["source"] = m.getSource();
log_msg["thread_name"] = m.getThread();
log_msg["thread_id"] = m.getTid();
struct NotificationLogMessage {
std::string msg;
std::string level;
std::string timestamp;
std::string source;
std::string thread_name;
std::uint64_t thread_id=0;
inline void to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"msg", msg);
RESTAPI_utils::field_to_json(Obj,"level", level);
RESTAPI_utils::field_to_json(Obj,"timestamp", timestamp);
RESTAPI_utils::field_to_json(Obj,"source", source);
RESTAPI_utils::field_to_json(Obj,"thread_name", thread_name);
RESTAPI_utils::field_to_json(Obj,"thread_id", thread_id);
}
inline bool from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj, "msg", msg);
RESTAPI_utils::field_from_json(Obj, "level", level);
RESTAPI_utils::field_from_json(Obj, "timestamp", timestamp);
RESTAPI_utils::field_from_json(Obj, "source", source);
RESTAPI_utils::field_from_json(Obj, "thread_name", thread_name);
RESTAPI_utils::field_from_json(Obj, "thread_id", thread_id);
return true;
} catch(...) {
std::cout << log_msg << std::endl;
*/
std::lock_guard G(Mutex_);
std::vector<uint64_t> Remove;
for(const auto &[Id,CallBack]:CallBacks_) {
try {
CallBack(m);
} catch (...) {
Remove.push_back(Id);
}
}
for(const auto &i:Remove)
CallBacks_.erase(i);
return false;
}
};
typedef WebSocketNotification<NotificationLogMessage> WebSocketClientNotificationLogMessage_t;
void log(const Poco::Message &m) final {
if(UI_WebSocketClientServer()->IsAnyoneConnected()) {
WebSocketClientNotificationLogMessage_t Msg;
Msg.content.msg = m.getText();
Msg.content.level = WebSocketLogger::to_string(m.getPriority());
Msg.content.timestamp = Poco::DateTimeFormatter::format(m.getTime(), Poco::DateTimeFormat::ISO8601_FORMAT);
Msg.content.source = m.getSource();
Msg.content.thread_name = m.getThread();
Msg.content.thread_id = m.getTid();
Msg.type_id = 1;
UI_WebSocketClientServer()->SendNotification(Msg);
}
}
inline void setProperty([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &value) final {
void setProperty([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &value) {
std::cout << "WS setProperty" << std::endl;
}
inline static auto instance() {
static auto instance_ = new WebSocketLogger;
return instance_;
}
inline void Enable(bool enable) { Enabled_ = enable; }
typedef std::function<void(const Poco::Message &M)> logmuxer_callback_func_t;
inline void RegisterCallback(const logmuxer_callback_func_t & R, uint64_t &Id) {
std::lock_guard G(Mutex_);
Id = CallBackId_++;
CallBacks_[Id] = R;
}
private:
std::recursive_mutex Mutex_;
std::map<uint64_t,logmuxer_callback_func_t> CallBacks_;
inline static uint64_t CallBackId_=1;
bool Enabled_ = false;
};
inline auto WebSocketLogger() { return WebSocketLogger::instance(); }
// inline auto WebSocketLogger() { return WebSocketLogger::instance(); }
}

View File

@@ -219,6 +219,9 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"};
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."};
static const struct msg DeviceRequiresSignature{1146,"Device requires device signature to be provided."};
}
@@ -433,6 +436,8 @@ namespace OpenWifi::uCentralProtocol {
static const char *CHANNELS = "channels";
static const char *PASSWORD = "password";
static const char *DEVICEUPDATE = "deviceupdate";
static const char *FWSIGNATURE = "FWsignature";
static const char *SIGNATURE = "signature";
static const char *SERIALNUMBER = "serialNumber";
static const char *COMPATIBLE = "compatible";