From 59886452a82f2577c20381a83f9718dc14e60dde Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Mon, 25 Sep 2023 20:50:41 +0200 Subject: [PATCH 1/3] [rpc] Add message queue disabling when disconnected --- src/rpc/RpcBase.cpp | 8 ++++++++ src/rpc/RpcBase.h | 2 ++ src/rpc/RpcServer.cpp | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/src/rpc/RpcBase.cpp b/src/rpc/RpcBase.cpp index dcfd978a..7ef526bf 100644 --- a/src/rpc/RpcBase.cpp +++ b/src/rpc/RpcBase.cpp @@ -272,6 +272,14 @@ void RpcBase::stop() } } +/** @brief Process the websocket disconnection event */ +void RpcBase::processDisconnected() +{ + // Disable queues + m_requests_queue.setEnable(false); + m_results_queue.setEnable(false); +} + /** @brief Process received data */ void RpcBase::processReceivedData(const void* data, size_t size) { diff --git a/src/rpc/RpcBase.h b/src/rpc/RpcBase.h index adac86a5..3a03cf55 100644 --- a/src/rpc/RpcBase.h +++ b/src/rpc/RpcBase.h @@ -124,6 +124,8 @@ class RpcBase : public IRpc void start(); /** @brief Stop RPC operations */ void stop(); + /** @brief Process the websocket disconnection event */ + void processDisconnected(); /** @brief Process received data */ void processReceivedData(const void* data, size_t size); /** @brief Get the RPC listener */ diff --git a/src/rpc/RpcServer.cpp b/src/rpc/RpcServer.cpp index 48eb14aa..6150ae1c 100644 --- a/src/rpc/RpcServer.cpp +++ b/src/rpc/RpcServer.cpp @@ -173,6 +173,10 @@ bool RpcServer::Client::isConnected() const /** @brief void IWebsocketServer::IClient::IListener::wsClientDisconnected() */ void RpcServer::Client::wsClientDisconnected() { + // Process disconnection event + processDisconnected(); + + // Notify listener rpcListener()->rpcDisconnected(); } From 8c2c5193112160a67c380abc26ba9bfcfa54abde Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Mon, 25 Sep 2023 21:30:31 +0200 Subject: [PATCH 2/3] =?UTF-8?q?[websocket]=C2=A0Add=20callback=20when=20cl?= =?UTF-8?q?ient=20closes=20connection=20before=20being=20fully=20establish?= =?UTF-8?q?ed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/common/DefaultCentralSystemEventsHandler.cpp | 6 ++++++ examples/common/DefaultCentralSystemEventsHandler.h | 3 +++ .../common/DefaultLocalControllerEventsHandler.cpp | 6 ++++++ examples/common/DefaultLocalControllerEventsHandler.h | 3 +++ src/centralsystem/CentralSystem.cpp | 8 ++++++++ src/centralsystem/CentralSystem.h | 3 +++ .../interface/ICentralSystemEventsHandler.h | 6 ++++++ src/localcontroller/LocalController.cpp | 8 ++++++++ src/localcontroller/LocalController.h | 3 +++ .../interface/ILocalControllerEventsHandler.h | 6 ++++++ src/rpc/RpcServer.cpp | 6 ++++++ src/rpc/RpcServer.h | 9 +++++++++ src/websockets/IWebsocketServer.h | 6 ++++++ src/websockets/libwebsockets/LibWebsocketServer.cpp | 11 +++++++++++ 14 files changed, 84 insertions(+) diff --git a/examples/common/DefaultCentralSystemEventsHandler.cpp b/examples/common/DefaultCentralSystemEventsHandler.cpp index 854fe4fc..4b5d2210 100644 --- a/examples/common/DefaultCentralSystemEventsHandler.cpp +++ b/examples/common/DefaultCentralSystemEventsHandler.cpp @@ -66,6 +66,12 @@ bool DefaultCentralSystemEventsHandler::acceptConnection(const char* ip_address) return true; } +/** @copydoc void ICentralSystemEventsHandler::clientFailedToConnect(const char*) */ +void DefaultCentralSystemEventsHandler::clientFailedToConnect(const char* ip_address) +{ + cout << "Client [" << ip_address << "] failed to connect" << endl; +} + /** @copydoc bool ICentralSystemEventsHandler::checkCredentials(const std::string&, const std::string&) */ bool DefaultCentralSystemEventsHandler::checkCredentials(const std::string& chargepoint_id, const std::string& password) { diff --git a/examples/common/DefaultCentralSystemEventsHandler.h b/examples/common/DefaultCentralSystemEventsHandler.h index 8be0c741..7e86c02b 100644 --- a/examples/common/DefaultCentralSystemEventsHandler.h +++ b/examples/common/DefaultCentralSystemEventsHandler.h @@ -48,6 +48,9 @@ class DefaultCentralSystemEventsHandler : public ocpp::centralsystem::ICentralSy /** @copydoc bool ICentralSystemEventsHandler::acceptConnection(const char*) */ bool acceptConnection(const char* ip_address) override; + /** @copydoc void ICentralSystemEventsHandler::clientFailedToConnect(const char*) */ + void clientFailedToConnect(const char* ip_address) override; + /** @copydoc bool ICentralSystemEventsHandler::checkCredentials(const std::string&, const std::string&) */ bool checkCredentials(const std::string& chargepoint_id, const std::string& password) override; diff --git a/examples/common/DefaultLocalControllerEventsHandler.cpp b/examples/common/DefaultLocalControllerEventsHandler.cpp index 1d3587b0..6c6d8f30 100644 --- a/examples/common/DefaultLocalControllerEventsHandler.cpp +++ b/examples/common/DefaultLocalControllerEventsHandler.cpp @@ -48,6 +48,12 @@ bool DefaultLocalControllerEventsHandler::acceptConnection(const char* ip_addres return true; } +/** @copydoc void ILocalControllerEventsHandler::clientFailedToConnect(const char*) */ +void DefaultLocalControllerEventsHandler::clientFailedToConnect(const char* ip_address) +{ + cout << "Client [" << ip_address << "] failed to connect" << endl; +} + /** @copydoc bool ILocalControllerEventsHandler::checkCredentials(const std::string&, const std::string&) */ bool DefaultLocalControllerEventsHandler::checkCredentials(const std::string& chargepoint_id, const std::string& password) { diff --git a/examples/common/DefaultLocalControllerEventsHandler.h b/examples/common/DefaultLocalControllerEventsHandler.h index a9ad9e56..52246ded 100644 --- a/examples/common/DefaultLocalControllerEventsHandler.h +++ b/examples/common/DefaultLocalControllerEventsHandler.h @@ -46,6 +46,9 @@ class DefaultLocalControllerEventsHandler : public ocpp::localcontroller::ILocal /** @copydoc bool ILocalControllerEventsHandler::acceptConnection(const char*) */ bool acceptConnection(const char* ip_address) override; + /** @copydoc void ILocalControllerEventsHandler::clientFailedToConnect(const char*) */ + void clientFailedToConnect(const char* ip_address) override; + /** @copydoc bool ILocalControllerEventsHandler::checkCredentials(const std::string&, const std::string&) */ bool checkCredentials(const std::string& chargepoint_id, const std::string& password) override; diff --git a/src/centralsystem/CentralSystem.cpp b/src/centralsystem/CentralSystem.cpp index bc5a3b0c..9864ced3 100644 --- a/src/centralsystem/CentralSystem.cpp +++ b/src/centralsystem/CentralSystem.cpp @@ -300,6 +300,14 @@ void CentralSystem::rpcClientConnected(const std::string& chargepoint_id, std::s m_events_handler.chargePointConnected(chargepoint); } +/** @copydoc void RpcServer::IListener::rpcClientFailedToConnect(const char*) */ +void CentralSystem::rpcClientFailedToConnect(const char* ip_address) +{ + // Notify failure => no additional processing is done here + // to keep this callback has fast as possible + return m_events_handler.clientFailedToConnect(ip_address); +} + /** @copydoc void RpcServer::IListener::rpcServerError() */ void CentralSystem::rpcServerError() { diff --git a/src/centralsystem/CentralSystem.h b/src/centralsystem/CentralSystem.h index e96bcae7..29a33e95 100644 --- a/src/centralsystem/CentralSystem.h +++ b/src/centralsystem/CentralSystem.h @@ -78,6 +78,9 @@ class CentralSystem : public ICentralSystem, public ocpp::rpc::RpcServer::IListe /** @copydoc void RpcServer::IListener::rpcClientConnected(const std::string&, std::shared_ptr) */ void rpcClientConnected(const std::string& chargepoint_id, std::shared_ptr client) override; + /** @copydoc void RpcServer::IListener::rpcClientFailedToConnect(const char*) */ + void rpcClientFailedToConnect(const char* ip_address) override; + /** @copydoc void RpcServer::IListener::rpcServerError() */ void rpcServerError() override; diff --git a/src/centralsystem/interface/ICentralSystemEventsHandler.h b/src/centralsystem/interface/ICentralSystemEventsHandler.h index 84723080..e8b6b610 100644 --- a/src/centralsystem/interface/ICentralSystemEventsHandler.h +++ b/src/centralsystem/interface/ICentralSystemEventsHandler.h @@ -40,6 +40,12 @@ class ICentralSystemEventsHandler */ virtual bool acceptConnection(const char* ip_address) = 0; + /** + * @brief Called when connection fails to established + * @param ip_address IP address of the client + */ + virtual void clientFailedToConnect(const char* ip_address) = 0; + /** * @brief Called to check the charge point credentials for HTTP basic authentication * @param chargepoint_id Charge Point identifier diff --git a/src/localcontroller/LocalController.cpp b/src/localcontroller/LocalController.cpp index 2a99cc86..4685ad3b 100644 --- a/src/localcontroller/LocalController.cpp +++ b/src/localcontroller/LocalController.cpp @@ -313,6 +313,14 @@ void LocalController::rpcClientConnected(const std::string& chargepoint_id, std: m_events_handler.chargePointConnected(chargepoint); } +/** @copydoc void RpcServer::IListener::rpcClientFailedToConnect(const char*) */ +void LocalController::rpcClientFailedToConnect(const char* ip_address) +{ + // Notify failure => no additional processing is done here + // to keep this callback has fast as possible + return m_events_handler.clientFailedToConnect(ip_address); +} + /** @copydoc void RpcServer::IListener::rpcServerError() */ void LocalController::rpcServerError() { diff --git a/src/localcontroller/LocalController.h b/src/localcontroller/LocalController.h index e6a57bfb..4dccbd72 100644 --- a/src/localcontroller/LocalController.h +++ b/src/localcontroller/LocalController.h @@ -78,6 +78,9 @@ class LocalController : public ILocalController, public ocpp::rpc::RpcServer::IL /** @copydoc void RpcServer::IListener::rpcClientConnected(const std::string&, std::shared_ptr) */ void rpcClientConnected(const std::string& chargepoint_id, std::shared_ptr client) override; + /** @copydoc void RpcServer::IListener::rpcClientFailedToConnect(const char*) */ + void rpcClientFailedToConnect(const char* ip_address) override; + /** @copydoc void RpcServer::IListener::rpcServerError() */ void rpcServerError() override; diff --git a/src/localcontroller/interface/ILocalControllerEventsHandler.h b/src/localcontroller/interface/ILocalControllerEventsHandler.h index 9cc4fa6c..65a1f7c5 100644 --- a/src/localcontroller/interface/ILocalControllerEventsHandler.h +++ b/src/localcontroller/interface/ILocalControllerEventsHandler.h @@ -40,6 +40,12 @@ class ILocalControllerEventsHandler */ virtual bool acceptConnection(const char* ip_address) = 0; + /** + * @brief Called when connection fails to established + * @param ip_address IP address of the client + */ + virtual void clientFailedToConnect(const char* ip_address) = 0; + /** * @brief Called to check the charge point credentials for HTTP basic authentication * @param chargepoint_id Charge Point identifier diff --git a/src/rpc/RpcServer.cpp b/src/rpc/RpcServer.cpp index 6150ae1c..4fd32530 100644 --- a/src/rpc/RpcServer.cpp +++ b/src/rpc/RpcServer.cpp @@ -123,6 +123,12 @@ void RpcServer::wsClientConnected(const char* uri, std::shared_ptrrpcClientConnected(chargepoint_id, rpc_client); } +/** @copydoc void IWebsocketServer::IListener::wsClientFailedToConnect(const char*) */ +void RpcServer::wsClientFailedToConnect(const char* ip_address) +{ + m_listener->rpcClientFailedToConnect(ip_address); +} + /** @copydoc void IWebsocketServer::IListener::wsServerError() */ void RpcServer::wsServerError() { diff --git a/src/rpc/RpcServer.h b/src/rpc/RpcServer.h index d64a67e6..b9f7eb26 100644 --- a/src/rpc/RpcServer.h +++ b/src/rpc/RpcServer.h @@ -78,6 +78,9 @@ class RpcServer : public ocpp::websockets::IWebsocketServer::IListener /** @copydoc void IWebsocketServer::IListener::wsClientConnected(const char*, std::shared_ptr) */ void wsClientConnected(const char* uri, std::shared_ptr client) override; + /** @copydoc void IWebsocketServer::IListener::wsClientFailedToConnect(const char*) */ + void wsClientFailedToConnect(const char* ip_address) override; + /** @copydoc void IWebsocketServer::IListener::wsServerError() */ void wsServerError() override; @@ -111,6 +114,12 @@ class RpcServer : public ocpp::websockets::IWebsocketServer::IListener */ virtual void rpcClientConnected(const std::string& chargepoint_id, std::shared_ptr client) = 0; + /** + * @brief Called when connection fails to established + * @param ip_address IP address of the client + */ + virtual void rpcClientFailedToConnect(const char* ip_address) = 0; + /** @brief Called on critical error */ virtual void rpcServerError() = 0; }; diff --git a/src/websockets/IWebsocketServer.h b/src/websockets/IWebsocketServer.h index 47060378..2e5bafe8 100644 --- a/src/websockets/IWebsocketServer.h +++ b/src/websockets/IWebsocketServer.h @@ -95,6 +95,12 @@ class IWebsocketServer */ virtual void wsClientConnected(const char* uri, std::shared_ptr client) = 0; + /** + * @brief Called when connection fails to established + * @param ip_address IP address of the client + */ + virtual void wsClientFailedToConnect(const char* ip_address) = 0; + /** @brief Called on critical error */ virtual void wsServerError() = 0; }; diff --git a/src/websockets/libwebsockets/LibWebsocketServer.cpp b/src/websockets/libwebsockets/LibWebsocketServer.cpp index 5729d61c..44493a77 100644 --- a/src/websockets/libwebsockets/LibWebsocketServer.cpp +++ b/src/websockets/libwebsockets/LibWebsocketServer.cpp @@ -459,6 +459,17 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons // Remove client server->m_clients.erase(iter_client); } + else + { + // Connection failed to be established + + // Get client IP address + char ip_address[64]; + lws_get_peer_simple(wsi, ip_address, sizeof(ip_address)); + + // Notify event + server->m_listener->wsClientFailedToConnect(ip_address); + } } break; From c2c9af297f0bc6230acf70c576649ed306702397 Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:37:36 +0200 Subject: [PATCH 3/3] [websocket] Fix handling for connecting client's IP address --- .../libwebsockets/LibWebsocketServer.cpp | 46 ++++++++++++++----- .../libwebsockets/LibWebsocketServer.h | 2 + 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/websockets/libwebsockets/LibWebsocketServer.cpp b/src/websockets/libwebsockets/LibWebsocketServer.cpp index 44493a77..2efa8b29 100644 --- a/src/websockets/libwebsockets/LibWebsocketServer.cpp +++ b/src/websockets/libwebsockets/LibWebsocketServer.cpp @@ -45,6 +45,7 @@ LibWebsocketServer::LibWebsocketServer() m_wsi(nullptr), m_retry_policy(), m_protocols(), + m_connecting_ip_address(nullptr), m_clients() { } @@ -278,18 +279,33 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons struct lws_filter_network_conn_args* filter = reinterpret_cast(user); // Get client IP address - char ip_address[64]; - lws_sa46_write_numeric_address(reinterpret_cast(&filter->cli_addr), ip_address, sizeof(ip_address)); + // => Save the current IP address so it can be retrieved + // in the LWS_CALLBACK_WSI_CREATE calls which happens + // during the same event loop processing + server->m_connecting_ip_address = new char[64u]; + lws_sa46_write_numeric_address(reinterpret_cast(&filter->cli_addr), server->m_connecting_ip_address, 64u); // Notify user - if (!server->m_listener->wsAcceptConnection(ip_address)) + if (!server->m_listener->wsAcceptConnection(server->m_connecting_ip_address)) { // Disconnect ret = -1; + + // Release memory + delete[] server->m_connecting_ip_address; } } break; + case LWS_CALLBACK_WSI_CREATE: + { + // Set client IP address + // => Must be done here to ensure that the event loop is still working + // with the same client as in the LWS_CALLBACK_FILTER_NETWORK_CONNECTION call + lws_set_wsi_user(wsi, server->m_connecting_ip_address); + } + break; + case LWS_CALLBACK_HTTP_CONFIRM_UPGRADE: { // Check selected protocol @@ -418,8 +434,7 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons case LWS_CALLBACK_ESTABLISHED: { // Get client IP address - char ip_address[64]; - lws_get_peer_simple(wsi, ip_address, sizeof(ip_address)); + char* ip_address = reinterpret_cast(lws_wsi_user(wsi)); // Instanciate a new client std::shared_ptr client(new Client(wsi, ip_address)); @@ -455,21 +470,30 @@ int LibWebsocketServer::eventCallback(struct lws* wsi, enum lws_callback_reasons { client->m_listener->wsClientDisconnected(); } + } + } + break; + + case LWS_CALLBACK_WSI_DESTROY: + { + // Get client IP address + char* ip_address = reinterpret_cast(lws_wsi_user(wsi)); + // Get corresponding client + auto iter_client = server->m_clients.find(wsi); + if (iter_client != server->m_clients.end()) + { // Remove client server->m_clients.erase(iter_client); } else { // Connection failed to be established - - // Get client IP address - char ip_address[64]; - lws_get_peer_simple(wsi, ip_address, sizeof(ip_address)); - - // Notify event server->m_listener->wsClientFailedToConnect(ip_address); } + + // Release memory + delete[] ip_address; } break; diff --git a/src/websockets/libwebsockets/LibWebsocketServer.h b/src/websockets/libwebsockets/LibWebsocketServer.h index d91dc812..798ce893 100644 --- a/src/websockets/libwebsockets/LibWebsocketServer.h +++ b/src/websockets/libwebsockets/LibWebsocketServer.h @@ -180,6 +180,8 @@ class LibWebsocketServer : public IWebsocketServer lws_retry_bo_t m_retry_policy; /** @brief Protocols */ std::array m_protocols; + /** @brief IP address of the currently connecting client */ + char* m_connecting_ip_address; /** @brief Connected clients */ std::unordered_map> m_clients;