mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2025-11-02 03:27:51 +00:00
Adding WebSocketNotification.
This commit is contained in:
@@ -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")) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user