Adding WebSocketNotification.

This commit is contained in:
stephb9959
2022-04-04 13:28:14 -07:00
parent c1454462c8
commit 266266481e
7 changed files with 116 additions and 102 deletions

2
build
View File

@@ -1 +1 @@
84
85

View File

@@ -38,102 +38,6 @@ namespace OpenWifi {
}
}
/*
void RESTAPI_webSocketServer::DoGet() {
// try and upgrade this session to websocket...
if(Request->find("Upgrade") != Request->end() && Poco::icompare((*Request)["Upgrade"], "websocket") == 0) {
try
{
Poco::Net::WebSocket WS(*Request, *Response);
Logger().information("WebSocket connection established.");
int flags;
int n;
bool Authenticated=false;
bool Done=false;
GoogleApiKey_ = MicroService::instance().ConfigGetString("google.apikey","");
GeoCodeEnabled_ = !GoogleApiKey_.empty();
do
{
Poco::Buffer<char> IncomingFrame(0);
n = WS.receiveFrame(IncomingFrame, flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
switch(Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: {
WS.sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
}
break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
}
break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
IncomingFrame.append(0);
if(!Authenticated) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame,':');
if(Tokens.size()==2 && AuthClient()->IsTokenAuthorized(Tokens[1], UserInfo_)) {
Authenticated=true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS.sendFrame(S.c_str(),S.size());
} else {
std::string S{"Invalid token. Closing connection."};
WS.sendFrame(S.c_str(),S.size());
Done=true;
}
} else {
try {
Poco::JSON::Parser P;
auto Obj = P.parse(IncomingFrame.begin())
.extract<Poco::JSON::Object::Ptr>();
std::string Answer;
Process(Obj, Answer, Done );
if (!Answer.empty())
WS.sendFrame(Answer.c_str(), Answer.size());
else {
WS.sendFrame("{}", 2);
}
} catch (const Poco::JSON::JSONException & E) {
Logger().log(E);
}
}
}
break;
default:
{
}
}
}
while (!Done && (n > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE));
Logger().information("WebSocket connection closed.");
}
catch (const Poco::Net::WebSocketException & E)
{
Logger().log(E);
switch (E.code())
{
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
Response->set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
// fallthrough
case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
Response->setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response->setContentLength(0);
Response->send();
break;
}
}
catch (const Poco::Exception &E) {
Logger().log(E);
}
}
}
*/
void RESTAPI_webSocketServer::Process(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done ) {
try {
if (O->has("command")) {

View File

@@ -857,5 +857,45 @@ namespace OpenWifi::ProvObjects {
return true;
}
void WebSocketNotificationContent::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"title",title);
RESTAPI_utils::field_to_json(Obj,"type",type);
RESTAPI_utils::field_to_json(Obj,"success",success);
RESTAPI_utils::field_to_json(Obj,"errors",errors);
RESTAPI_utils::field_to_json(Obj,"warnings",warnings);
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
}
bool WebSocketNotificationContent::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"title",title);
RESTAPI_utils::field_from_json(Obj,"type",type);
RESTAPI_utils::field_from_json(Obj,"success",success);
RESTAPI_utils::field_from_json(Obj,"errors",errors);
RESTAPI_utils::field_from_json(Obj,"warnings",warnings);
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
return true;
} catch(...) {
}
return false;
}
void WebSocketNotification::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"notification_id",notification_id);
RESTAPI_utils::field_to_json(Obj,"content",content);
}
bool WebSocketNotification::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);
return true;
} catch(...) {
}
return false;
}
}

View File

@@ -498,6 +498,26 @@ namespace OpenWifi::ProvObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WebSocketNotificationContent {
std::string title,
type;
std::vector<std::string> success,
errors,
warnings;
uint64_t timeStamp=std::time(nullptr);
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WebSocketNotification {
inline static uint64_t xid=1;
uint64_t notification_id=++xid;
WebSocketNotificationContent content;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);

View File

@@ -8,6 +8,7 @@
#include "StorageService.h"
#include "APConfig.h"
#include "sdks/SDK_gw.h"
#include "WebSocketClientServer.h"
namespace OpenWifi {
@@ -99,8 +100,21 @@ namespace OpenWifi {
} else {
Logger().warning(fmt::format("Venue {} no longer exists.",VenueUUID_));
}
Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update{} , {} bad configurations.",
JobId_, Updated ,Failed, BadConfigs));
ProvObjects::WebSocketNotification N;
N.content.title = "Bulk Configuration Updater";
N.content.type = "configuration_update";
N.content.success.push_back(fmt::format("Successfully updated {} devices.",Updated));
if(Failed>0)
N.content.warnings.push_back(fmt::format("Could not update {} devices.",Failed));
if(BadConfigs>0)
N.content.errors.push_back(fmt::format("Bad configuration for {} devices.",BadConfigs));
auto Sent = WebSocketClientServer()->SendUserNotification(UI_.email,N);
Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update{} , {} bad configurations. Notification was send={}",
JobId_, Updated ,Failed, BadConfigs, Sent));
delete this;
}
};

View File

@@ -32,6 +32,16 @@ namespace OpenWifi {
}
};
bool WebSocketClientServer::SendUserNotification(const std::string &userName,
const ProvObjects::WebSocketNotification &Notification) {
Poco::JSON::Object Payload;
Notification.to_json(Payload);
std::ostringstream OO;
Payload.stringify(OO);
return SendToUser(userName,OO.str());
}
void WebSocketClient::OnSocketError([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ErrorNotification> &pNf) {
delete this;
}
@@ -41,10 +51,23 @@ namespace OpenWifi {
auto It = Clients_.find(Id);
if(It!=Clients_.end())
return It->second->Send(Payload);
return It->second.first->Send(Payload);
return false;
}
bool WebSocketClientServer::SendToUser(const std::string &UserName, const std::string &Payload) {
std::lock_guard G(Mutex_);
uint64_t Sent=0;
for(const auto &client:Clients_) {
if(client.second.second == UserName) {
if(client.second.first->Send(Payload))
Sent++;
}
}
return Sent>0;
}
void WebSocketClient::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
int flags;
int n;
@@ -82,6 +105,7 @@ namespace OpenWifi {
Authenticated_=true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS_->sendFrame(S.c_str(),S.size());
WebSocketClientServer()->SetUser(Id_,UserInfo_.userinfo.email);
} else {
std::string S{"Invalid token. Closing connection."};
WS_->sendFrame(S.c_str(),S.size());

View File

@@ -12,6 +12,7 @@
#include "Poco/Net/SocketNotification.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "RESTObjects/RESTAPI_ProvObjects.h"
namespace OpenWifi {
@@ -60,19 +61,28 @@ namespace OpenWifi {
inline MyParallelSocketReactor & ReactorPool() { return *ReactorPool_; }
inline bool Register( WebSocketClient * Client, const std::string &Id) {
std::lock_guard G(Mutex_);
Clients_[Id] = Client;
Clients_[Id] = std::make_pair(Client,"");
return true;
}
inline void UnRegister(const std::string &Id) {
std::lock_guard G(Mutex_);
Clients_.erase(Id);
}
inline void SetUser(const std::string &Id, const std::string &UserId) {
std::lock_guard G(Mutex_);
auto it=Clients_.find(Id);
if(it!=Clients_.end()) {
Clients_[Id] = std::make_pair(it->second.first,UserId);
}
}
inline bool GeoCodeEnabled() const { return GeoCodeEnabled_; }
[[nodiscard]] inline std::string GoogleApiKey() const { return GoogleApiKey_; }
[[nodiscard]] bool Send(const std::string &Id, const std::string &Payload);
[[nodiscard]] bool SendUserNotification(const std::string &userName, const ProvObjects::WebSocketNotification & Notification);
private:
std::atomic_bool Running_=false;
@@ -80,7 +90,9 @@ namespace OpenWifi {
std::unique_ptr<MyParallelSocketReactor> ReactorPool_;
bool GeoCodeEnabled_=false;
std::string GoogleApiKey_;
std::map<std::string,WebSocketClient *> Clients_;
std::map<std::string, std::pair<WebSocketClient *,std::string>> Clients_;
[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload);
WebSocketClientServer() noexcept:
SubSystemServer("WebSocketClientServer", "WSCLNT-SVR", "websocketclients")