From d590bae995f4e18082b4ad6146f704861dbb27ab Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 28 Sep 2023 18:13:04 +0200 Subject: [PATCH 01/43] new `helpers::URIAppendPath()` Signed-off-by: Dominik K --- .gitignore | 1 + include/ocpp/helpers/uri.hpp | 15 +++++++++++++++ lib/CMakeLists.txt | 2 +- lib/ocpp/helpers/CMakeLists.txt | 5 +++++ lib/ocpp/helpers/uri.cpp | 22 ++++++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 include/ocpp/helpers/uri.hpp create mode 100644 lib/ocpp/helpers/CMakeLists.txt create mode 100644 lib/ocpp/helpers/uri.cpp diff --git a/.gitignore b/.gitignore index 2674aa109..fe793897e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *build* *vscode +.cache/ workspace.yaml CMakeLists.txt.user !doc/build-with-fetchcontent diff --git a/include/ocpp/helpers/uri.hpp b/include/ocpp/helpers/uri.hpp new file mode 100644 index 000000000..9e9d894d9 --- /dev/null +++ b/include/ocpp/helpers/uri.hpp @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest +#ifndef HELPERS_URI_HPP +#define HELPERS_URI_HPP + +#include + +namespace helpers { + + std::string URIAppendPath(std::string uri, std::string path); + +} // namespace helpers + + +#endif /* HELPERS_URI_HPP */ \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 588bd2a36..d46cec8b6 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,11 +36,11 @@ target_sources(ocpp ocpp/v201/ctrlr_component_variables.cpp ) +add_subdirectory(ocpp/helpers) add_subdirectory(ocpp/common/websocket) add_subdirectory(ocpp/v16/messages) add_subdirectory(ocpp/v201/messages) - target_include_directories(ocpp PUBLIC $ diff --git a/lib/ocpp/helpers/CMakeLists.txt b/lib/ocpp/helpers/CMakeLists.txt new file mode 100644 index 000000000..57df66ba6 --- /dev/null +++ b/lib/ocpp/helpers/CMakeLists.txt @@ -0,0 +1,5 @@ + +target_sources(ocpp + PRIVATE + uri.cpp +) diff --git a/lib/ocpp/helpers/uri.cpp b/lib/ocpp/helpers/uri.cpp new file mode 100644 index 000000000..5ac8be1d0 --- /dev/null +++ b/lib/ocpp/helpers/uri.cpp @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest +#include +#include + +namespace helpers { + +std::string URIAppendPath(std::string uri, std::string path) { + // remove ending "/" from `uri` + if ( boost::algorithm::ends_with(uri, "/") ) { + uri.pop_back(); + } + + // add initial "/" to `path` + if ( ! boost::algorithm::starts_with(path, "/")) { + path = "/" + path; + } + + return uri.append(path); +} + +} // namespace helpers \ No newline at end of file From 28a3d52e91368ae93b640fc215296101ae6b36fe Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 28 Sep 2023 18:19:32 +0200 Subject: [PATCH 02/43] append chargepoint ID to CSMS-URI Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_plain.cpp | 5 ++++- lib/ocpp/common/websocket/websocket_tls.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 09557de71..f0f81715d 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include @@ -16,7 +18,8 @@ bool WebsocketPlain::connect() { if (!this->initialized()) { return false; } - const auto uri = this->connection_options.cs_uri.insert(0, "ws://"); + auto uri = this->connection_options.cs_uri.insert(0, "ws://"); + uri = this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); EVLOG_info << "Connecting to plain websocket at uri: " << uri << " with profile: " << this->connection_options.security_profile; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index abc376a41..c8fc2ade6 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -1,11 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#include - #include #include #include +#include + +#include namespace ocpp { @@ -19,6 +20,7 @@ bool WebsocketTLS::connect() { return false; } this->uri = this->connection_options.cs_uri.insert(0, "wss://"); + this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); EVLOG_info << "Connecting TLS websocket to uri: " << this->uri << " with profile " << this->connection_options.security_profile; this->wss_client.clear_access_channels(websocketpp::log::alevel::all); From ad9f9dc366f03ed4fb7ac4e5fbd8c541d6ccbf25 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 28 Sep 2023 18:23:20 +0200 Subject: [PATCH 03/43] rename `cs_uri` to `csms_uri` Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 2 +- lib/ocpp/common/websocket/websocket.cpp | 4 ++-- lib/ocpp/common/websocket/websocket_plain.cpp | 4 ++-- lib/ocpp/common/websocket/websocket_tls.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 17b9e0d25..1105c4589 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,7 +19,7 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - std::string cs_uri; + std::string csms_uri; // The URI of the CSMS int security_profile; std::string chargepoint_id; std::optional authorization_key; diff --git a/lib/ocpp/common/websocket/websocket.cpp b/lib/ocpp/common/websocket/websocket.cpp index be5144444..eb617ffa9 100644 --- a/lib/ocpp/common/websocket/websocket.cpp +++ b/lib/ocpp/common/websocket/websocket.cpp @@ -15,10 +15,10 @@ Websocket::Websocket(const WebsocketConnectionOptions& connection_options, std:: std::shared_ptr logging) : logging(logging) { if (connection_options.security_profile <= 1) { - EVLOG_debug << "Creating plaintext websocket based on the provided URI: " << connection_options.cs_uri; + EVLOG_debug << "Creating plaintext websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options); } else if (connection_options.security_profile >= 2) { - EVLOG_debug << "Creating TLS websocket based on the provided URI: " << connection_options.cs_uri; + EVLOG_debug << "Creating TLS websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options, pki_handler); } } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index f0f81715d..b90ba92e1 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -18,7 +18,7 @@ bool WebsocketPlain::connect() { if (!this->initialized()) { return false; } - auto uri = this->connection_options.cs_uri.insert(0, "ws://"); + auto uri = this->connection_options.csms_uri.insert(0, "ws://"); uri = this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); EVLOG_info << "Connecting to plain websocket at uri: " << uri @@ -33,7 +33,7 @@ bool WebsocketPlain::connect() { websocket_thread.reset(new websocketpp::lib::thread(&client::run, &this->ws_client)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to plain websocket at uri: " << this->connection_options.cs_uri + EVLOG_info << "Reconnecting to plain websocket at uri: " << this->connection_options.csms_uri << " with profile: " << this->connection_options.security_profile; // close connection before reconnecting diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index c8fc2ade6..bf9566288 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -19,7 +19,7 @@ bool WebsocketTLS::connect() { if (!this->initialized()) { return false; } - this->uri = this->connection_options.cs_uri.insert(0, "wss://"); + this->uri = this->connection_options.csms_uri.insert(0, "wss://"); this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); EVLOG_info << "Connecting TLS websocket to uri: " << this->uri << " with profile " << this->connection_options.security_profile; @@ -34,7 +34,7 @@ bool WebsocketTLS::connect() { websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->connection_options.cs_uri + EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->connection_options.csms_uri << " with profile: " << this->connection_options.security_profile; // close connection before reconnecting From ed1495c2c114638c529af5e718009503ceff6c49 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 28 Sep 2023 18:28:53 +0200 Subject: [PATCH 04/43] fix in `websocket_plain.cpp`; consolidate both to avoid copy and paste errors Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_plain.cpp | 6 +++--- lib/ocpp/common/websocket/websocket_tls.cpp | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index b90ba92e1..d3140518f 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -19,16 +19,16 @@ bool WebsocketPlain::connect() { return false; } auto uri = this->connection_options.csms_uri.insert(0, "ws://"); - uri = this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); + uri = helpers::URIAppendPath(uri, this->connection_options.chargepoint_id); + this->uri = uri; - EVLOG_info << "Connecting to plain websocket at uri: " << uri + EVLOG_info << "Connecting to plain websocket at uri: " << this->uri << " with profile: " << this->connection_options.security_profile; this->ws_client.clear_access_channels(websocketpp::log::alevel::all); this->ws_client.clear_error_channels(websocketpp::log::elevel::all); this->ws_client.init_asio(); this->ws_client.start_perpetual(); - this->uri = uri; websocket_thread.reset(new websocketpp::lib::thread(&client::run, &this->ws_client)); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index bf9566288..49977c7b4 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -19,10 +19,13 @@ bool WebsocketTLS::connect() { if (!this->initialized()) { return false; } - this->uri = this->connection_options.csms_uri.insert(0, "wss://"); - this->uri = helpers::URIAppendPath(this->uri, this->connection_options.chargepoint_id); - EVLOG_info << "Connecting TLS websocket to uri: " << this->uri << " with profile " - << this->connection_options.security_profile; + auto uri = this->connection_options.csms_uri.insert(0, "wss://"); + uri = helpers::URIAppendPath(uri, this->connection_options.chargepoint_id); + this->uri = uri; + + EVLOG_info << "Connecting TLS websocket to uri: " << this->uri + << " with profile " << this->connection_options.security_profile; + this->wss_client.clear_access_channels(websocketpp::log::alevel::all); this->wss_client.clear_error_channels(websocketpp::log::elevel::all); this->wss_client.init_asio(); From ec0d20debe1bcf8c2ddb5c31a31424d388b384a6 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Fri, 29 Sep 2023 18:06:58 +0200 Subject: [PATCH 05/43] move `Uri`-struct to `websocket_common.cpp` Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_base.hpp | 8 ++-- .../common/websocket/websocket_common.hpp | 25 ++++++++++++ include/ocpp/helpers/uri.hpp | 15 -------- lib/CMakeLists.txt | 1 - lib/ocpp/common/websocket/CMakeLists.txt | 1 + .../common/websocket/websocket_common.cpp | 38 +++++++++++++++++++ lib/ocpp/common/websocket/websocket_plain.cpp | 12 +++--- lib/ocpp/common/websocket/websocket_tls.cpp | 23 ++++++----- lib/ocpp/helpers/CMakeLists.txt | 5 --- lib/ocpp/helpers/uri.cpp | 22 ----------- 10 files changed, 84 insertions(+), 66 deletions(-) create mode 100644 include/ocpp/common/websocket/websocket_common.hpp delete mode 100644 include/ocpp/helpers/uri.hpp create mode 100644 lib/ocpp/common/websocket/websocket_common.cpp delete mode 100644 lib/ocpp/helpers/CMakeLists.txt delete mode 100644 lib/ocpp/helpers/uri.cpp diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 1105c4589..edbb1d947 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -9,12 +9,12 @@ #include #include - -#include - #include #include +#include +#include + namespace ocpp { struct WebsocketConnectionOptions { @@ -48,7 +48,7 @@ class WebsocketBase { std::function message_callback; websocketpp::lib::shared_ptr reconnect_timer; std::unique_ptr ping_timer; - std::string uri; + ocpp::Uri uri; websocketpp::connection_hdl handle; std::mutex reconnect_mutex; std::mutex connection_mutex; diff --git a/include/ocpp/common/websocket/websocket_common.hpp b/include/ocpp/common/websocket/websocket_common.hpp new file mode 100644 index 000000000..12cf07225 --- /dev/null +++ b/include/ocpp/common/websocket/websocket_common.hpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest +#ifndef OCPP_WEBSOCKET_COMMON_HPP +#define OCPP_WEBSOCKET_COMMON_HPP + +#include + +namespace ocpp { + +class Uri { + public: + Uri(); + void set(std::string uri); + std::string string(); + + void append_path(std::string path); + std::string get_hostname(); + + private: + std::string value; +}; + +} // namespace ocpp + +#endif /* OCPP_WEBSOCKET_COMMON_HPP */ \ No newline at end of file diff --git a/include/ocpp/helpers/uri.hpp b/include/ocpp/helpers/uri.hpp deleted file mode 100644 index 9e9d894d9..000000000 --- a/include/ocpp/helpers/uri.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Pionix GmbH and Contributors to EVerest -#ifndef HELPERS_URI_HPP -#define HELPERS_URI_HPP - -#include - -namespace helpers { - - std::string URIAppendPath(std::string uri, std::string path); - -} // namespace helpers - - -#endif /* HELPERS_URI_HPP */ \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d46cec8b6..252182ef2 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,7 +36,6 @@ target_sources(ocpp ocpp/v201/ctrlr_component_variables.cpp ) -add_subdirectory(ocpp/helpers) add_subdirectory(ocpp/common/websocket) add_subdirectory(ocpp/v16/messages) add_subdirectory(ocpp/v201/messages) diff --git a/lib/ocpp/common/websocket/CMakeLists.txt b/lib/ocpp/common/websocket/CMakeLists.txt index 80f83bdd6..65a5dad14 100644 --- a/lib/ocpp/common/websocket/CMakeLists.txt +++ b/lib/ocpp/common/websocket/CMakeLists.txt @@ -2,6 +2,7 @@ target_sources(ocpp PRIVATE websocket_base.cpp + websocket_common.cpp websocket_plain.cpp websocket_tls.cpp websocket.cpp diff --git a/lib/ocpp/common/websocket/websocket_common.cpp b/lib/ocpp/common/websocket/websocket_common.cpp new file mode 100644 index 000000000..04c133585 --- /dev/null +++ b/lib/ocpp/common/websocket/websocket_common.cpp @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +#include + +#include + +#include + +namespace ocpp { + +Uri::Uri() { +} + +void Uri::set(std::string uri) { + this->value = uri; +} + +std::string Uri::string() { + return this->value; +} + +void Uri::append_path(std::string path) { + // remove ending "/" from `uri` + + if ( boost::algorithm::ends_with(this->value, "/") ) { + this->value.pop_back(); + } + + // add initial "/" to `path` + if ( ! boost::algorithm::starts_with(path, "/")) { + path = "/" + path; + } + + this->value.append(path); +} + +} \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index d3140518f..436b05521 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -3,8 +3,6 @@ #include #include -#include - #include @@ -18,11 +16,11 @@ bool WebsocketPlain::connect() { if (!this->initialized()) { return false; } - auto uri = this->connection_options.csms_uri.insert(0, "ws://"); - uri = helpers::URIAppendPath(uri, this->connection_options.chargepoint_id); - this->uri = uri; - EVLOG_info << "Connecting to plain websocket at uri: " << this->uri + this->uri.set(this->connection_options.csms_uri.insert(0, "ws://")); + this->uri.append_path(this->connection_options.chargepoint_id); + + EVLOG_info << "Connecting to plain websocket at uri: " << this->uri.string() << " with profile: " << this->connection_options.security_profile; this->ws_client.clear_access_channels(websocketpp::log::alevel::all); @@ -123,7 +121,7 @@ void WebsocketPlain::connect_plain() { websocketpp::lib::error_code ec; - client::connection_ptr con = this->ws_client.get_connection(this->uri, ec); + client::connection_ptr con = this->ws_client.get_connection(this->uri.string(), ec); if (ec) { EVLOG_error << "Connection initialization error for plain websocket: " << ec.message(); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 49977c7b4..cca12874c 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -1,12 +1,11 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#include #include +#include #include -#include -#include +#include namespace ocpp { @@ -19,11 +18,11 @@ bool WebsocketTLS::connect() { if (!this->initialized()) { return false; } - auto uri = this->connection_options.csms_uri.insert(0, "wss://"); - uri = helpers::URIAppendPath(uri, this->connection_options.chargepoint_id); - this->uri = uri; + + this->uri.set(this->connection_options.csms_uri.insert(0, "wss://")); + this->uri.append_path(this->connection_options.chargepoint_id); - EVLOG_info << "Connecting TLS websocket to uri: " << this->uri + EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() << " with profile " << this->connection_options.security_profile; this->wss_client.clear_access_channels(websocketpp::log::alevel::all); @@ -33,7 +32,7 @@ bool WebsocketTLS::connect() { websocket_thread.reset(new websocketpp::lib::thread(&tls_client::run, &this->wss_client)); this->wss_client.set_tls_init_handler( - websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->get_hostname(this->uri), + websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->uri.get_hostname(), websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { @@ -122,15 +121,15 @@ void WebsocketTLS::reconnect(std::error_code reason, long delay) { // https://github.com/zaphoyd/websocketpp/blob/master/websocketpp/close.hpp } -std::string WebsocketTLS::get_hostname(std::string uri) { +std::string Uri::get_hostname() { // FIXME(kai): This only works with a very limited subset of hostnames! std::string start = "wss://"; std::string stop = "/"; std::string port = ":"; auto hostname_start_pos = start.length(); - auto hostname_end_pos = uri.find_first_of(stop, hostname_start_pos); + auto hostname_end_pos = this->value.find_first_of(stop, hostname_start_pos); - auto hostname_with_port = uri.substr(hostname_start_pos, hostname_end_pos - hostname_start_pos); + auto hostname_with_port = this->value.substr(hostname_start_pos, hostname_end_pos - hostname_start_pos); auto port_pos = hostname_with_port.find_first_of(port); if (port_pos != std::string::npos) { return hostname_with_port.substr(0, port_pos); @@ -222,7 +221,7 @@ tls_context WebsocketTLS::on_tls_init(std::string hostname, websocketpp::connect void WebsocketTLS::connect_tls() { websocketpp::lib::error_code ec; - tls_client::connection_ptr con = this->wss_client.get_connection(this->uri, ec); + tls_client::connection_ptr con = this->wss_client.get_connection(this->uri.string(), ec); if (ec) { EVLOG_error << "Connection initialization error for TLS websocket: " << ec.message(); diff --git a/lib/ocpp/helpers/CMakeLists.txt b/lib/ocpp/helpers/CMakeLists.txt deleted file mode 100644 index 57df66ba6..000000000 --- a/lib/ocpp/helpers/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ - -target_sources(ocpp - PRIVATE - uri.cpp -) diff --git a/lib/ocpp/helpers/uri.cpp b/lib/ocpp/helpers/uri.cpp deleted file mode 100644 index 5ac8be1d0..000000000 --- a/lib/ocpp/helpers/uri.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Pionix GmbH and Contributors to EVerest -#include -#include - -namespace helpers { - -std::string URIAppendPath(std::string uri, std::string path) { - // remove ending "/" from `uri` - if ( boost::algorithm::ends_with(uri, "/") ) { - uri.pop_back(); - } - - // add initial "/" to `path` - if ( ! boost::algorithm::starts_with(path, "/")) { - path = "/" + path; - } - - return uri.append(path); -} - -} // namespace helpers \ No newline at end of file From 5a7103fcb510cfca5c4e1f212b4efaba73bb8f39 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 4 Oct 2023 16:13:09 +0200 Subject: [PATCH 06/43] v201: use `SecurityCtrlrIdentity` instead `ChargePointId` Signed-off-by: Dominik K --- config/v201/config.json | 6 ++++++ lib/ocpp/v201/charge_point.cpp | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/config/v201/config.json b/config/v201/config.json index 6236ee786..b886166d7 100644 --- a/config/v201/config.json +++ b/config/v201/config.json @@ -402,6 +402,12 @@ "attributes": { "Actual": "DEADBEEFDEADBEEF" } + }, + "Identity": { + "variable_name": "Identity", + "attributes": { + "Actual": "cp001" + } } }, "SmartChargingCtrlr": { diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 61454e2a1..2a576d387 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest +#include "ocpp/v201/ctrlr_component_variables.hpp" #include #include #include @@ -572,7 +573,7 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t OcppProtocolVersion::v201, ocpp_csms_url, network_connection_profile.securityProfile, - this->device_model->get_value(ControllerComponentVariables::ChargePointId), + this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity), this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRandomRange), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRepeatTimes), From 6062783eed531db20033d46c85be27bcf8fa8a64 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 4 Oct 2023 16:27:01 +0200 Subject: [PATCH 07/43] merge fix Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ocpp/common/websocket/websocket.cpp b/lib/ocpp/common/websocket/websocket.cpp index c9460a8eb..d3f0fc489 100644 --- a/lib/ocpp/common/websocket/websocket.cpp +++ b/lib/ocpp/common/websocket/websocket.cpp @@ -18,7 +18,7 @@ Websocket::Websocket(const WebsocketConnectionOptions& connection_options, std:: EVLOG_debug << "Creating plaintext websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options); } else if (connection_options.security_profile >= 2) { - EVLOG_debug << "Creating TLS websocket based on the provided URI: " << connection_options.cs_uri; + EVLOG_debug << "Creating TLS websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options, evse_security); } } From f2d05ddfa3ee87cce0cf7a123822f1cc27567d07 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Fri, 13 Oct 2023 13:39:11 +0200 Subject: [PATCH 08/43] use `set_path()`, use `websocketpp` with workaround Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_base.hpp | 2 +- .../common/websocket/websocket_common.hpp | 7 ++-- .../common/websocket/websocket_common.cpp | 35 ++++++++++--------- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 18 +--------- 5 files changed, 26 insertions(+), 38 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 46fc68b17..974363251 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,7 +19,7 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - std::string csms_uri; // The URI of the CSMS + std::string csms_uri; // the URI of the CSMS; TODO it can contain the `chargepoint_id` as path (for backwards-compatibility) int security_profile; std::string chargepoint_id; std::optional authorization_key; diff --git a/include/ocpp/common/websocket/websocket_common.hpp b/include/ocpp/common/websocket/websocket_common.hpp index 12cf07225..c2d532604 100644 --- a/include/ocpp/common/websocket/websocket_common.hpp +++ b/include/ocpp/common/websocket/websocket_common.hpp @@ -4,20 +4,21 @@ #define OCPP_WEBSOCKET_COMMON_HPP #include +#include namespace ocpp { class Uri { public: Uri(); - void set(std::string uri); + void set(std::string const & uri); std::string string(); - void append_path(std::string path); + void set_path(std::string const & path); std::string get_hostname(); private: - std::string value; + websocketpp::uri value; }; } // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_common.cpp b/lib/ocpp/common/websocket/websocket_common.cpp index 04c133585..0ac434e6a 100644 --- a/lib/ocpp/common/websocket/websocket_common.cpp +++ b/lib/ocpp/common/websocket/websocket_common.cpp @@ -5,34 +5,37 @@ #include +#include #include +#include namespace ocpp { -Uri::Uri() { +Uri::Uri(): + value(false, "", "") { // FIXME: Uri() should be constructed directly with real value } -void Uri::set(std::string uri) { - this->value = uri; +// if invalid, it throws `invalid_argument` exception +void Uri::set(std::string const & uri) { + auto u = websocketpp::uri(uri); + + if (! u.get_valid()) { + throw std::invalid_argument("Uri::set(): `uri` is invalid"); + } + + this->value = u; } std::string Uri::string() { - return this->value; + return this->value.str(); } -void Uri::append_path(std::string path) { - // remove ending "/" from `uri` - - if ( boost::algorithm::ends_with(this->value, "/") ) { - this->value.pop_back(); - } +void Uri::set_path(std::string const & path) { + this->value = websocketpp::uri(this->value.get_secure(), this->value.get_host(), this->value.get_port(), path); +} - // add initial "/" to `path` - if ( ! boost::algorithm::starts_with(path, "/")) { - path = "/" + path; - } - - this->value.append(path); +std::string Uri::get_hostname() { + return this->value.get_host(); } } \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index e9e89f7b7..28a8f4c14 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -18,7 +18,7 @@ bool WebsocketPlain::connect() { } this->uri.set(this->connection_options.csms_uri.insert(0, "ws://")); - this->uri.append_path(this->connection_options.chargepoint_id); + this->uri.set_path(this->connection_options.chargepoint_id); EVLOG_info << "Connecting to plain websocket at uri: " << this->uri.string() << " with profile: " << this->connection_options.security_profile; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index ed4e2e8ca..3d32f5077 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -20,7 +20,7 @@ bool WebsocketTLS::connect() { } this->uri.set(this->connection_options.csms_uri.insert(0, "wss://")); - this->uri.append_path(this->connection_options.chargepoint_id); + this->uri.set_path(this->connection_options.chargepoint_id); EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() << " with profile " << this->connection_options.security_profile; @@ -121,22 +121,6 @@ void WebsocketTLS::reconnect(std::error_code reason, long delay) { // https://github.com/zaphoyd/websocketpp/blob/master/websocketpp/close.hpp } -std::string Uri::get_hostname() { - // FIXME(kai): This only works with a very limited subset of hostnames! - std::string start = "wss://"; - std::string stop = "/"; - std::string port = ":"; - auto hostname_start_pos = start.length(); - auto hostname_end_pos = this->value.find_first_of(stop, hostname_start_pos); - - auto hostname_with_port = this->value.substr(hostname_start_pos, hostname_end_pos - hostname_start_pos); - auto port_pos = hostname_with_port.find_first_of(port); - if (port_pos != std::string::npos) { - return hostname_with_port.substr(0, port_pos); - } - return hostname_with_port; -} - tls_context WebsocketTLS::on_tls_init(std::string hostname, websocketpp::connection_hdl hdl, int32_t security_profile) { tls_context context = websocketpp::lib::make_shared(boost::asio::ssl::context::sslv23); From fb54d8f4de5d9859aac4fd8a6bdeee07c935b63e Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 16 Oct 2023 14:09:34 +0200 Subject: [PATCH 09/43] transfer `uri` around to avoid re-parsing Signed-off-by: Dominik K --- .../common/websocket/websocket_common.hpp | 27 ++++++++++++------- .../common/websocket/websocket_common.cpp | 12 +++------ lib/ocpp/common/websocket/websocket_plain.cpp | 3 ++- lib/ocpp/common/websocket/websocket_tls.cpp | 4 ++- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_common.hpp b/include/ocpp/common/websocket/websocket_common.hpp index c2d532604..19dde07b1 100644 --- a/include/ocpp/common/websocket/websocket_common.hpp +++ b/include/ocpp/common/websocket/websocket_common.hpp @@ -9,16 +9,23 @@ namespace ocpp { class Uri { - public: - Uri(); - void set(std::string const & uri); - std::string string(); - - void set_path(std::string const & path); - std::string get_hostname(); - - private: - websocketpp::uri value; +public: + Uri(); + void set(std::string const& uri); + std::string string(); + + void set_path(std::string const& path); + + std::string get_hostname() { + return this->value.get_host(); + } + + websocketpp::uri get_websocketpp_uri() { + return this->value; + } + +private: + websocketpp::uri value; }; } // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_common.cpp b/lib/ocpp/common/websocket/websocket_common.cpp index 0ac434e6a..68599bcbd 100644 --- a/lib/ocpp/common/websocket/websocket_common.cpp +++ b/lib/ocpp/common/websocket/websocket_common.cpp @@ -17,13 +17,13 @@ Uri::Uri(): // if invalid, it throws `invalid_argument` exception void Uri::set(std::string const & uri) { - auto u = websocketpp::uri(uri); + auto uri_temp = websocketpp::uri(uri); - if (! u.get_valid()) { + if (! uri_temp.get_valid()) { throw std::invalid_argument("Uri::set(): `uri` is invalid"); } - this->value = u; + this->value = uri_temp; } std::string Uri::string() { @@ -34,8 +34,4 @@ void Uri::set_path(std::string const & path) { this->value = websocketpp::uri(this->value.get_secure(), this->value.get_host(), this->value.get_port(), path); } -std::string Uri::get_hostname() { - return this->value.get_host(); -} - -} \ No newline at end of file +} /* namespace ocpp */ \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 28a8f4c14..4247b1e5a 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -2,6 +2,7 @@ // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest #include +#include #include #include @@ -121,7 +122,7 @@ void WebsocketPlain::connect_plain() { websocketpp::lib::error_code ec; - client::connection_ptr con = this->ws_client.get_connection(this->uri.string(), ec); + const client::connection_ptr con = this->ws_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for plain websocket: " << ec.message(); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 3d32f5077..d4ab24b62 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest +#include + #include #include #include @@ -200,7 +202,7 @@ tls_context WebsocketTLS::on_tls_init(std::string hostname, websocketpp::connect void WebsocketTLS::connect_tls() { websocketpp::lib::error_code ec; - tls_client::connection_ptr con = this->wss_client.get_connection(this->uri.string(), ec); + const tls_client::connection_ptr con = this->wss_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for TLS websocket: " << ec.message(); From d4323ed828afc1d8ce92ed87ded4d2a6b720db0f Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 18 Oct 2023 12:09:50 +0200 Subject: [PATCH 10/43] rename to `websocket_uri.*pp` Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 2 +- .../{websocket_common.hpp => websocket_uri.hpp} | 11 +++-------- lib/ocpp/common/types_internal.cpp | 8 ++++++++ lib/ocpp/common/websocket/CMakeLists.txt | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- .../{websocket_common.cpp => websocket_uri.cpp} | 11 +---------- 6 files changed, 15 insertions(+), 21 deletions(-) rename include/ocpp/common/websocket/{websocket_common.hpp => websocket_uri.hpp} (58%) create mode 100644 lib/ocpp/common/types_internal.cpp rename lib/ocpp/common/websocket/{websocket_common.cpp => websocket_uri.cpp} (59%) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 974363251..704e1b8f8 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace ocpp { diff --git a/include/ocpp/common/websocket/websocket_common.hpp b/include/ocpp/common/websocket/websocket_uri.hpp similarity index 58% rename from include/ocpp/common/websocket/websocket_common.hpp rename to include/ocpp/common/websocket/websocket_uri.hpp index 19dde07b1..f4f6fe893 100644 --- a/include/ocpp/common/websocket/websocket_common.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#ifndef OCPP_WEBSOCKET_COMMON_HPP -#define OCPP_WEBSOCKET_COMMON_HPP +#ifndef OCPP_WEBSOCKET_URI_HPP +#define OCPP_WEBSOCKET_URI_HPP #include #include @@ -11,23 +11,18 @@ namespace ocpp { class Uri { public: Uri(); - void set(std::string const& uri); - std::string string(); void set_path(std::string const& path); std::string get_hostname() { - return this->value.get_host(); } websocketpp::uri get_websocketpp_uri() { - return this->value; } private: - websocketpp::uri value; }; } // namespace ocpp -#endif /* OCPP_WEBSOCKET_COMMON_HPP */ \ No newline at end of file +#endif // OCPP_WEBSOCKET_URI_HPP */ \ No newline at end of file diff --git a/lib/ocpp/common/types_internal.cpp b/lib/ocpp/common/types_internal.cpp new file mode 100644 index 000000000..30f36a3ae --- /dev/null +++ b/lib/ocpp/common/types_internal.cpp @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +#include + +namespace ocpp { + typedef std::string chargepoint_id; +} \ No newline at end of file diff --git a/lib/ocpp/common/websocket/CMakeLists.txt b/lib/ocpp/common/websocket/CMakeLists.txt index 65a5dad14..896e37694 100644 --- a/lib/ocpp/common/websocket/CMakeLists.txt +++ b/lib/ocpp/common/websocket/CMakeLists.txt @@ -2,7 +2,7 @@ target_sources(ocpp PRIVATE websocket_base.cpp - websocket_common.cpp + websocket_uri.cpp websocket_plain.cpp websocket_tls.cpp websocket.cpp diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index d4ab24b62..e8f9250d6 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include diff --git a/lib/ocpp/common/websocket/websocket_common.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp similarity index 59% rename from lib/ocpp/common/websocket/websocket_common.cpp rename to lib/ocpp/common/websocket/websocket_uri.cpp index 68599bcbd..ee64783f9 100644 --- a/lib/ocpp/common/websocket/websocket_common.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Pionix GmbH and Contributors to EVerest -#include +#include #include @@ -11,19 +11,10 @@ namespace ocpp { -Uri::Uri(): - value(false, "", "") { // FIXME: Uri() should be constructed directly with real value -} // if invalid, it throws `invalid_argument` exception -void Uri::set(std::string const & uri) { - auto uri_temp = websocketpp::uri(uri); - if (! uri_temp.get_valid()) { - throw std::invalid_argument("Uri::set(): `uri` is invalid"); - } - this->value = uri_temp; } std::string Uri::string() { From 977c6d1ce293b06e0b52b8b499809f378f2aa6d1 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 18 Oct 2023 14:49:24 +0200 Subject: [PATCH 11/43] reworked with static `Uri::parse_from_string()` Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_base.hpp | 4 +-- .../ocpp/common/websocket/websocket_tls.hpp | 7 +---- .../ocpp/common/websocket/websocket_uri.hpp | 31 +++++++++++++++++-- include/ocpp/types/simple.hpp | 11 +++++++ lib/ocpp/common/types_internal.cpp | 8 ----- lib/ocpp/common/websocket/websocket.cpp | 2 -- lib/ocpp/common/websocket/websocket_plain.cpp | 8 +++-- lib/ocpp/common/websocket/websocket_tls.cpp | 10 +++--- lib/ocpp/common/websocket/websocket_uri.cpp | 24 +++++++++----- lib/ocpp/v201/charge_point.cpp | 9 +----- 10 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 include/ocpp/types/simple.hpp delete mode 100644 lib/ocpp/common/types_internal.cpp diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 704e1b8f8..bc6be8c97 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,7 +19,7 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - std::string csms_uri; // the URI of the CSMS; TODO it can contain the `chargepoint_id` as path (for backwards-compatibility) + std::string csms_uri; // the URI of the CSMS int security_profile; std::string chargepoint_id; std::optional authorization_key; @@ -49,7 +49,7 @@ class WebsocketBase { std::function message_callback; websocketpp::lib::shared_ptr reconnect_timer; std::unique_ptr ping_timer; - ocpp::Uri uri; + ocpp::Uri uri; // to be set in derived classes websocketpp::connection_hdl handle; std::mutex reconnect_mutex; std::mutex connection_mutex; diff --git a/include/ocpp/common/websocket/websocket_tls.hpp b/include/ocpp/common/websocket/websocket_tls.hpp index bc077406f..095640401 100644 --- a/include/ocpp/common/websocket/websocket_tls.hpp +++ b/include/ocpp/common/websocket/websocket_tls.hpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace ocpp { @@ -25,12 +26,6 @@ class WebsocketTLS final : public WebsocketBase { tls_client wss_client; std::shared_ptr evse_security; websocketpp::lib::shared_ptr websocket_thread; - - /// \brief Extracts the hostname from the provided \p uri - /// FIXME(kai): this only works with a very limited subset of hostnames and should be extended to work spec conform - /// \returns the extracted hostname - std::string get_hostname(std::string uri); - /// \brief Called when a TLS websocket connection gets initialized, manages the supported TLS versions, cipher lists /// and how verification of the server certificate is handled tls_context on_tls_init(std::string hostname, websocketpp::connection_hdl hdl, int32_t security_profile); diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index f4f6fe893..aa4d94d4c 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -3,6 +3,7 @@ #ifndef OCPP_WEBSOCKET_URI_HPP #define OCPP_WEBSOCKET_URI_HPP +#include #include #include @@ -10,17 +11,41 @@ namespace ocpp { class Uri { public: - Uri(); + Uri(){}; - void set_path(std::string const& path); + void init(bool secure, std::string host, int port, std::string path); // TODO should return an error if invalid + + // if a `chargepoint_id` is given, it will be checked that it is the same as the one in the URI-path, if set + // if invalid, it throws `invalid_argument` exception + static Uri parse_from_string(std::string const& uri, + ChargepointId chargepoint_id); // TODO should return an `expected<>` + + void set_secure(bool secure) { + this->secure = secure; + } std::string get_hostname() { + return this->host; } - websocketpp::uri get_websocketpp_uri() { + std::string string() { + auto uri = get_websocketpp_uri(); + return uri.str(); + } + + websocketpp::uri get_websocketpp_uri() { // FIXME: wrap needed `websocketpp:uri` functionality inside `Uri` + return websocketpp::uri(this->secure, this->host, this->port, this->path); } private: + Uri(bool secure, std::string host, uint16_t port, std::string path) : + secure(secure), host(host), port(port), path(path) { + } + + bool secure; + std::string host; + uint16_t port; + std::string path; }; } // namespace ocpp diff --git a/include/ocpp/types/simple.hpp b/include/ocpp/types/simple.hpp new file mode 100644 index 000000000..cc619b42f --- /dev/null +++ b/include/ocpp/types/simple.hpp @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +#ifndef OCPP_TYPES_SIMPLE_HPP +#define OCPP_TYPES_SIMPLE_HPP + +#include + +typedef std::string ChargepointId; + +#endif // OCPP_TYPES_SIMPLE_HPP \ No newline at end of file diff --git a/lib/ocpp/common/types_internal.cpp b/lib/ocpp/common/types_internal.cpp deleted file mode 100644 index 30f36a3ae..000000000 --- a/lib/ocpp/common/types_internal.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Pionix GmbH and Contributors to EVerest - -#include - -namespace ocpp { - typedef std::string chargepoint_id; -} \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket.cpp b/lib/ocpp/common/websocket/websocket.cpp index d3f0fc489..8de17c9e9 100644 --- a/lib/ocpp/common/websocket/websocket.cpp +++ b/lib/ocpp/common/websocket/websocket.cpp @@ -15,10 +15,8 @@ Websocket::Websocket(const WebsocketConnectionOptions& connection_options, std:: std::shared_ptr logging) : logging(logging) { if (connection_options.security_profile <= 1) { - EVLOG_debug << "Creating plaintext websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options); } else if (connection_options.security_profile >= 2) { - EVLOG_debug << "Creating TLS websocket based on the provided URI: " << connection_options.csms_uri; this->websocket = std::make_unique(connection_options, evse_security); } } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 4247b1e5a..f5e3187ca 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -11,6 +11,11 @@ namespace ocpp { WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_options) : WebsocketBase(connection_options) { + + this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); + this->uri.set_secure(false); + + EVLOG_debug << "Initialised WebsocketPlain with URI: " << this->uri.string(); } bool WebsocketPlain::connect() { @@ -18,9 +23,6 @@ bool WebsocketPlain::connect() { return false; } - this->uri.set(this->connection_options.csms_uri.insert(0, "ws://")); - this->uri.set_path(this->connection_options.chargepoint_id); - EVLOG_info << "Connecting to plain websocket at uri: " << this->uri.string() << " with profile: " << this->connection_options.security_profile; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index e8f9250d6..0b10fd91b 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -14,6 +14,11 @@ namespace ocpp { WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, std::shared_ptr evse_security) : WebsocketBase(connection_options), evse_security(evse_security) { + + this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); + this->uri.set_secure(true); + + EVLOG_debug << "Initialised WebsocketTLS with URI: " << this->uri.string(); } bool WebsocketTLS::connect() { @@ -21,11 +26,8 @@ bool WebsocketTLS::connect() { return false; } - this->uri.set(this->connection_options.csms_uri.insert(0, "wss://")); - this->uri.set_path(this->connection_options.chargepoint_id); - EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() - << " with profile " << this->connection_options.security_profile; + << " with security-profile " << this->connection_options.security_profile; this->wss_client.clear_access_channels(websocketpp::log::alevel::all); this->wss_client.clear_error_channels(websocketpp::log::elevel::all); diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index ee64783f9..4cb831227 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Pionix GmbH and Contributors to EVerest +#include "ocpp/types/simple.hpp" #include #include @@ -11,18 +12,25 @@ namespace ocpp { +Uri Uri::parse_from_string(std::string const& uri, ChargepointId chargepoint_id) { + auto uri_temp = websocketpp::uri(uri); -// if invalid, it throws `invalid_argument` exception + if (!uri_temp.get_valid()) { + throw std::invalid_argument("Uri constructor: given `uri` is invalid"); + } + const auto& hostname = uri_temp.get_host(); + if (!hostname.empty()) { + if (hostname != chargepoint_id) { + throw std::invalid_argument("Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); + } -} + chargepoint_id = hostname; + } -std::string Uri::string() { - return this->value.str(); -} + auto uri_return = Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), uri_temp.get_resource()); -void Uri::set_path(std::string const & path) { - this->value = websocketpp::uri(this->value.get_secure(), this->value.get_host(), this->value.get_port(), path); + return uri_return; } -} /* namespace ocpp */ \ No newline at end of file +} // namespace ocpp \ No newline at end of file diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 8d3b44f96..1afabca65 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -568,17 +568,10 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t } const auto network_connection_profile = network_connection_profile_opt.value(); - auto ocpp_csms_url = network_connection_profile.ocppCsmsUrl.get(); - - if (ocpp_csms_url.compare(0, 5, "ws://") == 0) { - ocpp_csms_url.erase(0, 5); - } else if (ocpp_csms_url.compare(0, 6, "wss://") == 0) { - ocpp_csms_url.erase(0, 6); - } WebsocketConnectionOptions connection_options{ OcppProtocolVersion::v201, - ocpp_csms_url, + network_connection_profile.ocppCsmsUrl.get(), network_connection_profile.securityProfile, this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity), this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), From 88b8abd73d325dc8bbef6e71b3d78a562e9cc738 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 18 Oct 2023 15:40:55 +0200 Subject: [PATCH 12/43] use `set_connection_options()` generically Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 3 ++- include/ocpp/common/websocket/websocket_plain.hpp | 2 ++ include/ocpp/common/websocket/websocket_tls.hpp | 2 ++ lib/ocpp/common/websocket/websocket_base.cpp | 4 +++- lib/ocpp/common/websocket/websocket_plain.cpp | 9 +++++++-- lib/ocpp/common/websocket/websocket_tls.cpp | 11 +++++++---- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index bc6be8c97..e236aa500 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -92,7 +92,8 @@ class WebsocketBase { virtual bool connect() = 0; /// \brief sets this connection_options to the given \p connection_options and resets the connection_attempts - void set_connection_options(const WebsocketConnectionOptions& connection_options); + virtual void set_connection_options(const WebsocketConnectionOptions& connection_options) = 0; + void set_connection_options_base(const WebsocketConnectionOptions& connection_options); /// \brief reconnect the websocket after the delay virtual void reconnect(std::error_code reason, long delay) = 0; diff --git a/include/ocpp/common/websocket/websocket_plain.hpp b/include/ocpp/common/websocket/websocket_plain.hpp index e2ea428fe..c7f21fb7e 100644 --- a/include/ocpp/common/websocket/websocket_plain.hpp +++ b/include/ocpp/common/websocket/websocket_plain.hpp @@ -41,6 +41,8 @@ class WebsocketPlain final : public WebsocketBase { /// \brief Called when a plaintext websocket connection fails to be established void on_fail_plain(client* c, websocketpp::connection_hdl hdl); + void set_connection_options(const WebsocketConnectionOptions& connection_options) override; + public: /// \brief Creates a new WebsocketPlain object with the providede \p connection_options explicit WebsocketPlain(const WebsocketConnectionOptions& connection_options); diff --git a/include/ocpp/common/websocket/websocket_tls.hpp b/include/ocpp/common/websocket/websocket_tls.hpp index 095640401..df5d582dd 100644 --- a/include/ocpp/common/websocket/websocket_tls.hpp +++ b/include/ocpp/common/websocket/websocket_tls.hpp @@ -45,6 +45,8 @@ class WebsocketTLS final : public WebsocketBase { /// \brief Called when a TLS websocket connection fails to be established void on_fail_tls(tls_client* c, websocketpp::connection_hdl hdl); + void set_connection_options(const WebsocketConnectionOptions& connection_options) override; + public: /// \brief Creates a new Websocket object with the providede \p connection_options explicit WebsocketTLS(const WebsocketConnectionOptions& connection_options, diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index 282434869..64c050c29 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -28,7 +28,9 @@ WebsocketBase::WebsocketBase(const WebsocketConnectionOptions& connection_option WebsocketBase::~WebsocketBase() { } -void WebsocketBase::set_connection_options(const WebsocketConnectionOptions& connection_options) { +void WebsocketBase::set_connection_options_base(const WebsocketConnectionOptions& connection_options) { + this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); + this->connection_attempts = 0; this->connection_options = connection_options; } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index f5e3187ca..ae509e63a 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -12,12 +12,17 @@ namespace ocpp { WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_options) : WebsocketBase(connection_options) { - this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); - this->uri.set_secure(false); + set_connection_options(connection_options); EVLOG_debug << "Initialised WebsocketPlain with URI: " << this->uri.string(); } +void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { + set_connection_options_base(connection_options); // initialises this->uri, too + + this->uri.set_secure(false); +} + bool WebsocketPlain::connect() { if (!this->initialized()) { return false; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 0b10fd91b..dc5fa2e7b 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -15,17 +15,20 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, std::shared_ptr evse_security) : WebsocketBase(connection_options), evse_security(evse_security) { - this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); - this->uri.set_secure(true); - EVLOG_debug << "Initialised WebsocketTLS with URI: " << this->uri.string(); } +void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { + set_connection_options_base(connection_options); // initialises this->uri, too + + this->uri.set_secure(true); +} + bool WebsocketTLS::connect() { if (!this->initialized()) { return false; } - + EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() << " with security-profile " << this->connection_options.security_profile; From 606a26b21dbd5de7805bf4bf4a8de159b1e22cd6 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 18 Oct 2023 18:29:49 +0200 Subject: [PATCH 13/43] `find . -iname '*.*pp' | xargs clang-format -i` Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 4 ++-- lib/ocpp/common/websocket/websocket_plain.cpp | 7 ++++--- lib/ocpp/common/websocket/websocket_tls.cpp | 13 +++++++------ lib/ocpp/common/websocket/websocket_uri.cpp | 3 ++- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index e236aa500..3ffbbdd31 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,7 +19,7 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - std::string csms_uri; // the URI of the CSMS + std::string csms_uri; // the URI of the CSMS int security_profile; std::string chargepoint_id; std::optional authorization_key; @@ -49,7 +49,7 @@ class WebsocketBase { std::function message_callback; websocketpp::lib::shared_ptr reconnect_timer; std::unique_ptr ping_timer; - ocpp::Uri uri; // to be set in derived classes + ocpp::Uri uri; // to be set in derived classes websocketpp::connection_hdl handle; std::mutex reconnect_mutex; std::mutex connection_mutex; diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index ae509e63a..5b0d7a864 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -18,7 +18,7 @@ WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_opti } void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { - set_connection_options_base(connection_options); // initialises this->uri, too + set_connection_options_base(connection_options); // initialises this->uri, too this->uri.set_secure(false); } @@ -129,7 +129,8 @@ void WebsocketPlain::connect_plain() { websocketpp::lib::error_code ec; - const client::connection_ptr con = this->ws_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); + const client::connection_ptr con = + this->ws_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for plain websocket: " << ec.message(); @@ -177,7 +178,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index dc5fa2e7b..5241d8cb1 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -4,8 +4,8 @@ #include #include -#include #include +#include #include @@ -19,7 +19,7 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, } void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { - set_connection_options_base(connection_options); // initialises this->uri, too + set_connection_options_base(connection_options); // initialises this->uri, too this->uri.set_secure(true); } @@ -29,8 +29,8 @@ bool WebsocketTLS::connect() { return false; } - EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() - << " with security-profile " << this->connection_options.security_profile; + EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() << " with security-profile " + << this->connection_options.security_profile; this->wss_client.clear_access_channels(websocketpp::log::alevel::all); this->wss_client.clear_error_channels(websocketpp::log::elevel::all); @@ -207,7 +207,8 @@ tls_context WebsocketTLS::on_tls_init(std::string hostname, websocketpp::connect void WebsocketTLS::connect_tls() { websocketpp::lib::error_code ec; - const tls_client::connection_ptr con = this->wss_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); + const tls_client::connection_ptr con = + this->wss_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for TLS websocket: " << ec.message(); @@ -253,7 +254,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 4cb831227..758c6ec58 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -22,7 +22,8 @@ Uri Uri::parse_from_string(std::string const& uri, ChargepointId chargepoint_id) const auto& hostname = uri_temp.get_host(); if (!hostname.empty()) { if (hostname != chargepoint_id) { - throw std::invalid_argument("Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); + throw std::invalid_argument( + "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); } chargepoint_id = hostname; From 3143cba265bacfe30ed22dfae6e633b5e1cc9719 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 18 Oct 2023 19:17:49 +0200 Subject: [PATCH 14/43] fix linter issues Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_uri.hpp | 2 -- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index aa4d94d4c..d7e59bd67 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -13,8 +13,6 @@ class Uri { public: Uri(){}; - void init(bool secure, std::string host, int port, std::string path); // TODO should return an error if invalid - // if a `chargepoint_id` is given, it will be checked that it is the same as the one in the URI-path, if set // if invalid, it throws `invalid_argument` exception static Uri parse_from_string(std::string const& uri, diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 5b0d7a864..fe7069f6b 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -178,7 +178,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 5241d8cb1..ae4f875fb 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -254,7 +254,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; From bbfafbf62483f3f7be2d9d191f939e185fc834e2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 19 Oct 2023 11:13:50 +0200 Subject: [PATCH 15/43] Codacy & own PR-reviews Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_uri.hpp | 2 +- lib/ocpp/common/websocket/websocket_plain.cpp | 10 +++++----- lib/ocpp/common/websocket/websocket_tls.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index d7e59bd67..4fa552901 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -36,7 +36,7 @@ class Uri { } private: - Uri(bool secure, std::string host, uint16_t port, std::string path) : + Uri(bool secure, const std::string host, uint16_t port, const std::string path) : secure(secure), host(host), port(port), path(path) { } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index fe7069f6b..f887a0186 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -29,7 +29,7 @@ bool WebsocketPlain::connect() { } EVLOG_info << "Connecting to plain websocket at uri: " << this->uri.string() - << " with profile: " << this->connection_options.security_profile; + << " with security profile: " << this->connection_options.security_profile; this->ws_client.clear_access_channels(websocketpp::log::alevel::all); this->ws_client.clear_error_channels(websocketpp::log::elevel::all); @@ -39,8 +39,8 @@ bool WebsocketPlain::connect() { websocket_thread.reset(new websocketpp::lib::thread(&client::run, &this->ws_client)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to plain websocket at uri: " << this->connection_options.csms_uri - << " with profile: " << this->connection_options.security_profile; + EVLOG_info << "Reconnecting to plain websocket at uri: " << this->uri.string() + << " with security profile: " << this->connection_options.security_profile; // close connection before reconnecting if (this->m_is_connected) { @@ -178,7 +178,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; @@ -258,4 +258,4 @@ void WebsocketPlain::ping() { } } -} // namespace ocpp +} // namespace ocpp \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index ae4f875fb..847051bb0 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -43,8 +43,8 @@ bool WebsocketTLS::connect() { websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->connection_options.csms_uri - << " with profile: " << this->connection_options.security_profile; + EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->uri.string() + << " with security profile: " << this->connection_options.security_profile; // close connection before reconnecting if (this->m_is_connected) { @@ -254,7 +254,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; @@ -338,4 +338,4 @@ void WebsocketTLS::ping() { } } -} // namespace ocpp +} // namespace ocpp \ No newline at end of file From 8b5b66563e65fc814675f7fbbf471586a4a5cdb1 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 19 Oct 2023 11:23:51 +0200 Subject: [PATCH 16/43] `clang-format` again :-( Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index f887a0186..a5f6d7b7e 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -178,7 +178,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 847051bb0..5b03bc242 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -254,7 +254,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; From 79994bb059f4eadd84213add1098b6b8abaa7cfa Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 19 Oct 2023 11:26:38 +0200 Subject: [PATCH 17/43] make Codacy happy again!?! Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_uri.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index 4fa552901..ad905c969 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -36,7 +36,7 @@ class Uri { } private: - Uri(bool secure, const std::string host, uint16_t port, const std::string path) : + Uri(bool secure, const std::string& host, uint16_t port, const std::string& path) : secure(secure), host(host), port(port), path(path) { } From f2f3f0ac3e0444984da422c21845fa1e6d381fa3 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 13:48:48 +0200 Subject: [PATCH 18/43] remove `typedef Chargepoint` Signed-off-by: Dominik K --- include/ocpp/types/simple.hpp | 11 ----------- lib/ocpp/common/websocket/websocket_base.cpp | 8 +++++--- lib/ocpp/common/websocket/websocket_uri.cpp | 2 +- 3 files changed, 6 insertions(+), 15 deletions(-) delete mode 100644 include/ocpp/types/simple.hpp diff --git a/include/ocpp/types/simple.hpp b/include/ocpp/types/simple.hpp deleted file mode 100644 index cc619b42f..000000000 --- a/include/ocpp/types/simple.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Pionix GmbH and Contributors to EVerest - -#ifndef OCPP_TYPES_SIMPLE_HPP -#define OCPP_TYPES_SIMPLE_HPP - -#include - -typedef std::string ChargepointId; - -#endif // OCPP_TYPES_SIMPLE_HPP \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index 64c050c29..0138fd5c2 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -8,7 +8,6 @@ namespace ocpp { WebsocketBase::WebsocketBase(const WebsocketConnectionOptions& connection_options) : m_is_connected(false), - connection_options(connection_options), connected_callback(nullptr), closed_callback(nullptr), message_callback(nullptr), @@ -17,7 +16,10 @@ WebsocketBase::WebsocketBase(const WebsocketConnectionOptions& connection_option reconnect_backoff_ms(0), shutting_down(false), reconnecting(false) { - this->ping_timer = std::make_unique(); + + set_connection_options_base(connection_options) + + this->ping_timer = std::make_unique(); const auto auth_key = connection_options.authorization_key; if (auth_key.has_value() and auth_key.value().length() < 16) { EVLOG_warning << "AuthorizationKey with only " << auth_key.value().length() @@ -161,4 +163,4 @@ void WebsocketBase::on_pong_timeout(websocketpp::connection_hdl hdl, std::string } } -} // namespace ocpp +} // namespace ocpp \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 758c6ec58..e91ff6f32 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -12,7 +12,7 @@ namespace ocpp { -Uri Uri::parse_from_string(std::string const& uri, ChargepointId chargepoint_id) { +Uri Uri::parse_from_string(std::string const& uri, std::string chargepoint_id) { auto uri_temp = websocketpp::uri(uri); if (!uri_temp.get_valid()) { From 534ae87d4055c2ba37a7329c13a1181f97947ee1 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 13:49:35 +0200 Subject: [PATCH 19/43] `WebsocketConnectionOptions.Uri` Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 3ffbbdd31..d17479f7d 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,7 +19,7 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - std::string csms_uri; // the URI of the CSMS + Uri csms_uri; // the URI of the CSMS int security_profile; std::string chargepoint_id; std::optional authorization_key; @@ -129,4 +129,4 @@ class WebsocketBase { }; } // namespace ocpp -#endif // OCPP_WEBSOCKET_BASE_HPP +#endif // OCPP_WEBSOCKET_BASE_HPP \ No newline at end of file From 7fb19cadbfd1862b0bd38b753636f0c34fd64824 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 14:40:37 +0200 Subject: [PATCH 20/43] init `Uri` before adding to `WebsocketConnectionOptions` Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_base.hpp | 1 - lib/ocpp/common/websocket/websocket_base.cpp | 2 -- lib/ocpp/common/websocket/websocket_plain.cpp | 15 +++++++-------- lib/ocpp/common/websocket/websocket_tls.cpp | 19 +++++++++---------- lib/ocpp/common/websocket/websocket_uri.cpp | 4 +--- lib/ocpp/v16/charge_point_impl.cpp | 7 +++++-- lib/ocpp/v201/charge_point.cpp | 10 +++++++--- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index d17479f7d..deb2f1d34 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -49,7 +49,6 @@ class WebsocketBase { std::function message_callback; websocketpp::lib::shared_ptr reconnect_timer; std::unique_ptr ping_timer; - ocpp::Uri uri; // to be set in derived classes websocketpp::connection_hdl handle; std::mutex reconnect_mutex; std::mutex connection_mutex; diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index 0138fd5c2..fabec93d2 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -31,8 +31,6 @@ WebsocketBase::~WebsocketBase() { } void WebsocketBase::set_connection_options_base(const WebsocketConnectionOptions& connection_options) { - this->uri = Uri::parse_from_string(connection_options.csms_uri, connection_options.chargepoint_id); - this->connection_attempts = 0; this->connection_options = connection_options; } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index a5f6d7b7e..a69e08222 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -14,13 +14,12 @@ WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_opti set_connection_options(connection_options); - EVLOG_debug << "Initialised WebsocketPlain with URI: " << this->uri.string(); + EVLOG_debug << "Initialised WebsocketPlain with URI: " << this->connection_options.csms_uri.string(); } void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { - set_connection_options_base(connection_options); // initialises this->uri, too - - this->uri.set_secure(false); + set_connection_options_base(connection_options); + this->connection_options.csms_uri.set_secure(false); } bool WebsocketPlain::connect() { @@ -28,7 +27,7 @@ bool WebsocketPlain::connect() { return false; } - EVLOG_info << "Connecting to plain websocket at uri: " << this->uri.string() + EVLOG_info << "Connecting to plain websocket at uri: " << this->connection_options.csms_uri.string() << " with security profile: " << this->connection_options.security_profile; this->ws_client.clear_access_channels(websocketpp::log::alevel::all); @@ -39,7 +38,7 @@ bool WebsocketPlain::connect() { websocket_thread.reset(new websocketpp::lib::thread(&client::run, &this->ws_client)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to plain websocket at uri: " << this->uri.string() + EVLOG_info << "Reconnecting to plain websocket at uri: " << this->connection_options.csms_uri.string() << " with security profile: " << this->connection_options.security_profile; // close connection before reconnecting @@ -129,8 +128,8 @@ void WebsocketPlain::connect_plain() { websocketpp::lib::error_code ec; - const client::connection_ptr con = - this->ws_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); + const client::connection_ptr con = this->ws_client.get_connection( + std::make_shared(this->connection_options.csms_uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for plain websocket: " << ec.message(); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 5b03bc242..9f91bf23d 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -15,13 +15,12 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, std::shared_ptr evse_security) : WebsocketBase(connection_options), evse_security(evse_security) { - EVLOG_debug << "Initialised WebsocketTLS with URI: " << this->uri.string(); + EVLOG_debug << "Initialised WebsocketTLS with URI: " << this->connection_options.csms_uri.string(); } void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { - set_connection_options_base(connection_options); // initialises this->uri, too - - this->uri.set_secure(true); + set_connection_options_base(connection_options); + this->connection_options.csms_uri.set_secure(true); } bool WebsocketTLS::connect() { @@ -29,8 +28,8 @@ bool WebsocketTLS::connect() { return false; } - EVLOG_info << "Connecting TLS websocket to uri: " << this->uri.string() << " with security-profile " - << this->connection_options.security_profile; + EVLOG_info << "Connecting TLS websocket to uri: " << this->connection_options.csms_uri.string() + << " with security-profile " << this->connection_options.security_profile; this->wss_client.clear_access_channels(websocketpp::log::alevel::all); this->wss_client.clear_error_channels(websocketpp::log::elevel::all); @@ -39,11 +38,11 @@ bool WebsocketTLS::connect() { websocket_thread.reset(new websocketpp::lib::thread(&tls_client::run, &this->wss_client)); this->wss_client.set_tls_init_handler( - websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->uri.get_hostname(), + websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->connection_options.csms_uri.get_hostname(), websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { - EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->uri.string() + EVLOG_info << "Reconnecting to TLS websocket at uri: " << this->connection_options.csms_uri.string() << " with security profile: " << this->connection_options.security_profile; // close connection before reconnecting @@ -207,8 +206,8 @@ tls_context WebsocketTLS::on_tls_init(std::string hostname, websocketpp::connect void WebsocketTLS::connect_tls() { websocketpp::lib::error_code ec; - const tls_client::connection_ptr con = - this->wss_client.get_connection(std::make_shared(this->uri.get_websocketpp_uri()), ec); + const tls_client::connection_ptr con = this->wss_client.get_connection( + std::make_shared(this->connection_options.csms_uri.get_websocketpp_uri()), ec); if (ec) { EVLOG_error << "Connection initialization error for TLS websocket: " << ec.message(); diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index e91ff6f32..691e981c1 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -25,11 +25,9 @@ Uri Uri::parse_from_string(std::string const& uri, std::string chargepoint_id) { throw std::invalid_argument( "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); } - - chargepoint_id = hostname; } - auto uri_return = Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), uri_temp.get_resource()); + auto uri_return = Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), hostname); return uri_return; } diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index 2fbb53aa0..acf25e00e 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -203,8 +203,11 @@ void ChargePointImpl::init_state_machine(const std::map& } WebsocketConnectionOptions ChargePointImpl::get_ws_connection_options() { + auto uri = + Uri::parse_from_string(this->configuration->getCentralSystemURI(), this->configuration->getChargePointId()); + WebsocketConnectionOptions connection_options{OcppProtocolVersion::v16, - this->configuration->getCentralSystemURI(), + uri, this->configuration->getSecurityProfile(), this->configuration->getChargePointId(), this->configuration->getAuthorizationKey(), @@ -3423,4 +3426,4 @@ ConfigurationStatus ChargePointImpl::set_custom_configuration_key(CiString<50> k } } // namespace v16 -} // namespace ocpp +} // namespace ocpp \ No newline at end of file diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 5844713ff..44c6d70de 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -629,11 +629,15 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t const auto network_connection_profile = network_connection_profile_opt.value(); + auto chargepoint_id = + this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity); + auto uri = Uri::parse_from_string(network_connection_profile.ocppCsmsUrl.get(), chargepoint_id); + WebsocketConnectionOptions connection_options{ OcppProtocolVersion::v201, - network_connection_profile.ocppCsmsUrl.get(), + uri, network_connection_profile.securityProfile, - this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity), + chargepoint_id, this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRandomRange), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRepeatTimes), @@ -2214,4 +2218,4 @@ void ChargePoint::handle_get_local_authorization_list_version_req(Call Date: Mon, 23 Oct 2023 14:42:59 +0200 Subject: [PATCH 21/43] run `set_connection_options()` in `Websocket...` constructor Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 5 +++-- lib/ocpp/common/websocket/websocket_base.cpp | 2 +- lib/ocpp/common/websocket/websocket_plain.cpp | 4 +--- lib/ocpp/common/websocket/websocket_tls.cpp | 4 +++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index deb2f1d34..1b4eec471 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -82,8 +82,9 @@ class WebsocketBase { void on_pong_timeout(websocketpp::connection_hdl hdl, std::string msg); public: - /// \brief Creates a new WebsocketBase object with the providede \p connection_options - explicit WebsocketBase(const WebsocketConnectionOptions& connection_options); + /// \brief Creates a new WebsocketBase object. The `connection_options` must be initialised with + /// `set_connection_options()` + explicit WebsocketBase(); virtual ~WebsocketBase(); /// \brief connect to a websocket diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index fabec93d2..37c3e4b22 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -6,7 +6,7 @@ #include namespace ocpp { -WebsocketBase::WebsocketBase(const WebsocketConnectionOptions& connection_options) : +WebsocketBase::WebsocketBase() : m_is_connected(false), connected_callback(nullptr), closed_callback(nullptr), diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index a69e08222..9975acfc4 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -9,9 +9,7 @@ namespace ocpp { -WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_options) : - WebsocketBase(connection_options) { - +WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_options) : WebsocketBase() { set_connection_options(connection_options); EVLOG_debug << "Initialised WebsocketPlain with URI: " << this->connection_options.csms_uri.string(); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 9f91bf23d..10f914db8 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -13,7 +13,9 @@ namespace ocpp { WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, std::shared_ptr evse_security) : - WebsocketBase(connection_options), evse_security(evse_security) { + WebsocketBase(), evse_security(evse_security) { + + set_connection_options(connection_options); EVLOG_debug << "Initialised WebsocketTLS with URI: " << this->connection_options.csms_uri.string(); } From 2ceec0db321cdb06f0ec331da5745312aa74dae5 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 14:51:21 +0200 Subject: [PATCH 22/43] single source for `chargepoint_id` Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_base.hpp | 1 - include/ocpp/common/websocket/websocket_uri.hpp | 11 +++++++---- lib/ocpp/common/websocket/websocket_base.cpp | 3 ++- lib/ocpp/common/websocket/websocket_tls.cpp | 4 ++-- lib/ocpp/v16/charge_point_impl.cpp | 1 - lib/ocpp/v201/charge_point.cpp | 7 +++---- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 1b4eec471..87e09b3ef 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -21,7 +21,6 @@ struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; Uri csms_uri; // the URI of the CSMS int security_profile; - std::string chargepoint_id; std::optional authorization_key; int retry_backoff_random_range_s; int retry_backoff_repeat_times; diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index ad905c969..7a41ce60f 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -25,6 +25,9 @@ class Uri { std::string get_hostname() { return this->host; } + std::string get_chargepoint_id() { + return this->chargepoint_id; + } std::string string() { auto uri = get_websocketpp_uri(); @@ -32,18 +35,18 @@ class Uri { } websocketpp::uri get_websocketpp_uri() { // FIXME: wrap needed `websocketpp:uri` functionality inside `Uri` - return websocketpp::uri(this->secure, this->host, this->port, this->path); + return websocketpp::uri(this->secure, this->host, this->port, this->chargepoint_id); } private: - Uri(bool secure, const std::string& host, uint16_t port, const std::string& path) : - secure(secure), host(host), port(port), path(path) { + Uri(bool secure, const std::string& host, uint16_t port, const std::string& chargepoint_id) : + secure(secure), host(host), port(port), chargepoint_id(chargepoint_id) { } bool secure; std::string host; uint16_t port; - std::string path; + std::string chargepoint_id; }; } // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index 37c3e4b22..0ffc8e063 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -93,7 +93,8 @@ std::optional WebsocketBase::getAuthorizationHeader() { const auto authorization_key = this->connection_options.authorization_key; if (authorization_key.has_value()) { EVLOG_debug << "AuthorizationKey present, encoding authentication header"; - std::string plain_auth_header = this->connection_options.chargepoint_id + ":" + authorization_key.value(); + std::string plain_auth_header = + this->connection_options.csms_uri.get_chargepoint_id() + ":" + authorization_key.value(); auth_header.emplace(std::string("Basic ") + websocketpp::base64_encode(plain_auth_header)); EVLOG_debug << "Basic Auth header: " << auth_header.value(); } diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 10f914db8..43e3f9f71 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -40,7 +40,7 @@ bool WebsocketTLS::connect() { websocket_thread.reset(new websocketpp::lib::thread(&tls_client::run, &this->wss_client)); this->wss_client.set_tls_init_handler( - websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->connection_options.csms_uri.get_hostname(), + websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->connection_options.csms_uri.get_chargepoint_id(), websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { @@ -255,7 +255,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index acf25e00e..a42acf508 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -209,7 +209,6 @@ WebsocketConnectionOptions ChargePointImpl::get_ws_connection_options() { WebsocketConnectionOptions connection_options{OcppProtocolVersion::v16, uri, this->configuration->getSecurityProfile(), - this->configuration->getChargePointId(), this->configuration->getAuthorizationKey(), this->configuration->getRetryBackoffRandomRange(), this->configuration->getRetryBackoffRepeatTimes(), diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 44c6d70de..582393c90 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -629,15 +629,14 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t const auto network_connection_profile = network_connection_profile_opt.value(); - auto chargepoint_id = - this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity); - auto uri = Uri::parse_from_string(network_connection_profile.ocppCsmsUrl.get(), chargepoint_id); + auto uri = Uri::parse_from_string( + network_connection_profile.ocppCsmsUrl.get(), + this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity)); WebsocketConnectionOptions connection_options{ OcppProtocolVersion::v201, uri, network_connection_profile.securityProfile, - chargepoint_id, this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRandomRange), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRepeatTimes), From a4e1ccaa3d18745dea35397080cabb0a9b18c6c9 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 15:39:14 +0200 Subject: [PATCH 23/43] check against security-profile at `set_connection_options()` Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 14 +++++++++++-- lib/ocpp/common/websocket/websocket_plain.cpp | 21 +++++++++++++++---- lib/ocpp/common/websocket/websocket_tls.cpp | 17 +++++++++++++-- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 60f587493..16c6a3748 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -558,6 +558,16 @@ firmware_status_notification_to_firmware_status_enum_type(const FirmwareStatusNo } // namespace conversions +namespace security { +// The security profiles defined in OCPP 2.0.1 resp. in the OCPP 1.6 security-whitepaper. +enum SecurityProfiles : int { + unspecified = 0, + unsecured_transport_with_basic_authentication = 1, + TLS_with_basic_authentication = 2, + TLS_with_client_side_certificates = 3, +}; +} // namespace security + namespace security_events { // This is the list of security events defined in OCPP 2.0.1 (and the 1.6 security whitepper). @@ -574,7 +584,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL @@ -588,4 +598,4 @@ inline const std::string INVALIDTLSCIPHERSUITE = "InvalidTLSCipherSuite"; } // namespace ocpp -#endif +#endif \ No newline at end of file diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 9975acfc4..1f86fd650 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -1,12 +1,15 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#include - -#include +#include #include +#include + #include +#include +#include + namespace ocpp { WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_options) : WebsocketBase() { @@ -16,6 +19,16 @@ WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_opti } void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { + switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values + case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + break; + case security::SecurityProfiles::TLS_with_basic_authentication: + case security::SecurityProfiles::TLS_with_client_side_certificates: + throw std::invalid_argument("`security_profile` is not a plain, unsecured one."); + default: + throw std::invalid_argument("unknown `security_profile`"); + } + set_connection_options_base(connection_options); this->connection_options.csms_uri.set_secure(false); } @@ -175,7 +188,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 43e3f9f71..9e3e0d6eb 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -1,14 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#include - #include +#include #include #include #include +#include +#include + namespace ocpp { WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, @@ -21,7 +23,18 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, } void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { + switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values + case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + throw std::invalid_argument("`security_profile` is not a TLS-profile"); + case security::SecurityProfiles::TLS_with_basic_authentication: + case security::SecurityProfiles::TLS_with_client_side_certificates: + break; + default: + throw std::invalid_argument("unknown `security_profile`"); + } + set_connection_options_base(connection_options); + this->connection_options.csms_uri.set_secure(true); } From 161ee4e881ec8c32b57c575e80a4337fb99786c0 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 16:17:37 +0200 Subject: [PATCH 24/43] check conforming URI-scheme and security-profile Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_uri.hpp | 3 +- lib/ocpp/common/websocket/websocket_uri.cpp | 34 ++++++++++++++----- lib/ocpp/v16/charge_point_impl.cpp | 7 ++-- lib/ocpp/v201/charge_point.cpp | 8 +++-- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index 7a41ce60f..6561fa5a3 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -15,8 +15,7 @@ class Uri { // if a `chargepoint_id` is given, it will be checked that it is the same as the one in the URI-path, if set // if invalid, it throws `invalid_argument` exception - static Uri parse_from_string(std::string const& uri, - ChargepointId chargepoint_id); // TODO should return an `expected<>` + static Uri parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile); void set_secure(bool secure) { this->secure = secure; diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 691e981c1..00889c673 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Pionix GmbH and Contributors to EVerest +#include "ocpp/common/types.hpp" #include "ocpp/types/simple.hpp" #include @@ -12,24 +13,41 @@ namespace ocpp { -Uri Uri::parse_from_string(std::string const& uri, std::string chargepoint_id) { - auto uri_temp = websocketpp::uri(uri); +Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile) { + // workaround for required schema in `websocketpp::uri()` + bool scheme_added_workaround = false; + if (uri.find("://") == std::string::npos) { + scheme_added_workaround = true; + uri = "ws://" + uri; + } + auto uri_temp = websocketpp::uri(uri); if (!uri_temp.get_valid()) { - throw std::invalid_argument("Uri constructor: given `uri` is invalid"); + throw std::invalid_argument("given `uri` is invalid"); + } + + if (!scheme_added_workaround) { + switch (security_profile) { // `switch` to lint for unused enum-values + case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + if (uri_temp.get_secure()) { + throw std::invalid_argument("secure schema in URI does not fit with insecure security-profile"); + } + case security::SecurityProfiles::TLS_with_basic_authentication: + case security::SecurityProfiles::TLS_with_client_side_certificates: + if (!uri_temp.get_secure()) { + throw std::invalid_argument("insecure schema in URI does not fit with secure security-profile"); + } + } } const auto& hostname = uri_temp.get_host(); if (!hostname.empty()) { if (hostname != chargepoint_id) { - throw std::invalid_argument( - "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); + throw std::invalid_argument("the chargepoint-ID in the `uri`-path is different to the defined one"); } } - auto uri_return = Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), hostname); - - return uri_return; + return Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), chargepoint_id); } } // namespace ocpp \ No newline at end of file diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index a42acf508..1a23b19dc 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -203,12 +203,13 @@ void ChargePointImpl::init_state_machine(const std::map& } WebsocketConnectionOptions ChargePointImpl::get_ws_connection_options() { - auto uri = - Uri::parse_from_string(this->configuration->getCentralSystemURI(), this->configuration->getChargePointId()); + auto security_profile = this->configuration->getSecurityProfile(); + auto uri = Uri::parse_and_validate(this->configuration->getCentralSystemURI(), + this->configuration->getChargePointId(), security_profile); WebsocketConnectionOptions connection_options{OcppProtocolVersion::v16, uri, - this->configuration->getSecurityProfile(), + security_profile, this->configuration->getAuthorizationKey(), this->configuration->getRetryBackoffRandomRange(), this->configuration->getRetryBackoffRepeatTimes(), diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 582393c90..64956b1bc 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -629,14 +629,16 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t const auto network_connection_profile = network_connection_profile_opt.value(); - auto uri = Uri::parse_from_string( + auto security_profile = network_connection_profile.securityProfile; + auto uri = Uri::parse_and_validate( network_connection_profile.ocppCsmsUrl.get(), - this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity)); + this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity), + security_profile); WebsocketConnectionOptions connection_options{ OcppProtocolVersion::v201, uri, - network_connection_profile.securityProfile, + security_profile, this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRandomRange), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRepeatTimes), From 76aa1e753f14e3e233bef2ecca6abb0330e4ad1d Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 23 Oct 2023 16:24:08 +0200 Subject: [PATCH 25/43] make `clang-format` happy again Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 2 +- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 16c6a3748..f715b2030 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -584,7 +584,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 1f86fd650..3ff063c58 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -188,7 +188,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 9e3e0d6eb..347ef142c 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -268,7 +268,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; From 87ef3ef04d75cb58cd5f24c395c01bbc14841d25 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Fri, 27 Oct 2023 12:40:05 +0200 Subject: [PATCH 26/43] fixes from review Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_uri.hpp | 2 +- lib/ocpp/common/websocket/websocket_base.cpp | 6 +++--- lib/ocpp/common/websocket/websocket_uri.cpp | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index ad905c969..23d4ef37e 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -16,7 +16,7 @@ class Uri { // if a `chargepoint_id` is given, it will be checked that it is the same as the one in the URI-path, if set // if invalid, it throws `invalid_argument` exception static Uri parse_from_string(std::string const& uri, - ChargepointId chargepoint_id); // TODO should return an `expected<>` + std::string chargepoint_id); // TODO should return an `expected<>` void set_secure(bool secure) { this->secure = secure; diff --git a/lib/ocpp/common/websocket/websocket_base.cpp b/lib/ocpp/common/websocket/websocket_base.cpp index 0138fd5c2..cca6913fa 100644 --- a/lib/ocpp/common/websocket/websocket_base.cpp +++ b/lib/ocpp/common/websocket/websocket_base.cpp @@ -17,9 +17,9 @@ WebsocketBase::WebsocketBase(const WebsocketConnectionOptions& connection_option shutting_down(false), reconnecting(false) { - set_connection_options_base(connection_options) + set_connection_options_base(connection_options); - this->ping_timer = std::make_unique(); + this->ping_timer = std::make_unique(); const auto auth_key = connection_options.authorization_key; if (auth_key.has_value() and auth_key.value().length() < 16) { EVLOG_warning << "AuthorizationKey with only " << auth_key.value().length() @@ -163,4 +163,4 @@ void WebsocketBase::on_pong_timeout(websocketpp::connection_hdl hdl, std::string } } -} // namespace ocpp \ No newline at end of file +} // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index e91ff6f32..744a2732a 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2023 Pionix GmbH and Contributors to EVerest -#include "ocpp/types/simple.hpp" #include #include @@ -19,14 +18,14 @@ Uri Uri::parse_from_string(std::string const& uri, std::string chargepoint_id) { throw std::invalid_argument("Uri constructor: given `uri` is invalid"); } - const auto& hostname = uri_temp.get_host(); - if (!hostname.empty()) { - if (hostname != chargepoint_id) { + const auto& path = uri_temp.get_resource(); + if (!path.empty()) { + if (path != chargepoint_id) { throw std::invalid_argument( "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); } - chargepoint_id = hostname; + chargepoint_id = path; } auto uri_return = Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), uri_temp.get_resource()); @@ -34,4 +33,4 @@ Uri Uri::parse_from_string(std::string const& uri, std::string chargepoint_id) { return uri_return; } -} // namespace ocpp \ No newline at end of file +} // namespace ocpp From 6f1e6009741da5c6ee66fcf2f979b83fbf111ab0 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 30 Oct 2023 13:40:40 +0100 Subject: [PATCH 27/43] rename to singural form; TODO for using `SecurityProfile`-type Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 15 ++++++++------- include/ocpp/common/websocket/websocket_base.hpp | 6 +++--- lib/ocpp/common/websocket/websocket_plain.cpp | 10 +++++----- lib/ocpp/common/websocket/websocket_tls.cpp | 10 +++++----- lib/ocpp/common/websocket/websocket_uri.cpp | 6 +++--- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index f715b2030..61106ec92 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -560,11 +560,12 @@ firmware_status_notification_to_firmware_status_enum_type(const FirmwareStatusNo namespace security { // The security profiles defined in OCPP 2.0.1 resp. in the OCPP 1.6 security-whitepaper. -enum SecurityProfiles : int { - unspecified = 0, - unsecured_transport_with_basic_authentication = 1, - TLS_with_basic_authentication = 2, - TLS_with_client_side_certificates = 3, +enum SecurityProfile { // no "enum class" because values are used in implicit `switch`-comparisons to `int + // security_profile` + UNSPECIFIED = 0, + UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION = 1, + TLS_WITH_BASIC_AUTHENTICATION = 2, + TLS_WITH_CLIENT_SIDE_CERTIFICATES = 3, }; } // namespace security @@ -584,7 +585,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL @@ -598,4 +599,4 @@ inline const std::string INVALIDTLSCIPHERSUITE = "InvalidTLSCipherSuite"; } // namespace ocpp -#endif \ No newline at end of file +#endif diff --git a/include/ocpp/common/websocket/websocket_base.hpp b/include/ocpp/common/websocket/websocket_base.hpp index 87e09b3ef..7d67f2375 100644 --- a/include/ocpp/common/websocket/websocket_base.hpp +++ b/include/ocpp/common/websocket/websocket_base.hpp @@ -19,8 +19,8 @@ namespace ocpp { struct WebsocketConnectionOptions { OcppProtocolVersion ocpp_version; - Uri csms_uri; // the URI of the CSMS - int security_profile; + Uri csms_uri; // the URI of the CSMS + int security_profile; // FIXME: change type to `SecurityProfile` std::optional authorization_key; int retry_backoff_random_range_s; int retry_backoff_repeat_times; @@ -128,4 +128,4 @@ class WebsocketBase { }; } // namespace ocpp -#endif // OCPP_WEBSOCKET_BASE_HPP \ No newline at end of file +#endif // OCPP_WEBSOCKET_BASE_HPP diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 3ff063c58..84f846c68 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -20,10 +20,10 @@ WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_opti void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values - case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: break; - case security::SecurityProfiles::TLS_with_basic_authentication: - case security::SecurityProfiles::TLS_with_client_side_certificates: + case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: + case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: throw std::invalid_argument("`security_profile` is not a plain, unsecured one."); default: throw std::invalid_argument("unknown `security_profile`"); @@ -188,7 +188,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; @@ -268,4 +268,4 @@ void WebsocketPlain::ping() { } } -} // namespace ocpp \ No newline at end of file +} // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 347ef142c..953a1a7d6 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -24,10 +24,10 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values - case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: throw std::invalid_argument("`security_profile` is not a TLS-profile"); - case security::SecurityProfiles::TLS_with_basic_authentication: - case security::SecurityProfiles::TLS_with_client_side_certificates: + case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: + case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: break; default: throw std::invalid_argument("unknown `security_profile`"); @@ -268,7 +268,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; @@ -352,4 +352,4 @@ void WebsocketTLS::ping() { } } -} // namespace ocpp \ No newline at end of file +} // namespace ocpp diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 5cc170dc6..d21c52e66 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -27,12 +27,12 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec if (!scheme_added_workaround) { switch (security_profile) { // `switch` to lint for unused enum-values - case security::SecurityProfiles::unsecured_transport_with_basic_authentication: + case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: if (uri_temp.get_secure()) { throw std::invalid_argument("secure schema in URI does not fit with insecure security-profile"); } - case security::SecurityProfiles::TLS_with_basic_authentication: - case security::SecurityProfiles::TLS_with_client_side_certificates: + case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: + case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: if (!uri_temp.get_secure()) { throw std::invalid_argument("insecure schema in URI does not fit with secure security-profile"); } From a9195406d6e647ba01b1b9d1c9014ced145980a8 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 31 Oct 2023 13:39:56 +0100 Subject: [PATCH 28/43] WIP: check CP-ID against path-base instead of full path Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_uri.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index d21c52e66..3d8f384c0 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -5,13 +5,17 @@ #include #include +#include #include #include -#include namespace ocpp { +auto path_last_segment(const std::string_view path) -> std::string { + return std::string(path.substr(path.rfind("/"), path.length())); +} + Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile) { // workaround for required schema in `websocketpp::uri()` bool scheme_added_workaround = false; @@ -39,14 +43,14 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec } } - const auto& path = uri_temp.get_resource(); - if (!path.empty()) { - if (path != chargepoint_id) { + const auto& base = path_last_segment(uri_temp.get_resource()); + if (!base.empty()) { + if (base != chargepoint_id) { throw std::invalid_argument( "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); } - chargepoint_id = path; + chargepoint_id = base; } return Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), chargepoint_id); From 3bd6d6228b9348b9125e1680c1bac2108ac0e0e1 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 2 Nov 2023 12:46:53 +0100 Subject: [PATCH 29/43] remove CP-ID from path if last segment Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_uri.hpp | 23 ++++++++--- lib/ocpp/common/websocket/websocket_uri.cpp | 38 ++++++++++++++----- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index 35b25ad7d..f07614fdd 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -4,6 +4,7 @@ #define OCPP_WEBSOCKET_URI_HPP #include +#include #include namespace ocpp { @@ -12,8 +13,13 @@ class Uri { public: Uri(){}; - // if a `chargepoint_id` is given, it will be checked that it is the same as the one in the URI-path, if set - // if invalid, it throws `invalid_argument` exception + // parse_and_validate parses the URI and checks + // 1. general validity of the URI + // 2. scheme fits to given `security_profile` + // + // Backwards-compatibility: The path (of the URI) can contain the `chargepoint_id` as last segment. + // + // It throws `std::invalid_argument` for several checks static Uri parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile); void set_secure(bool secure) { @@ -33,17 +39,24 @@ class Uri { } websocketpp::uri get_websocketpp_uri() { // FIXME: wrap needed `websocketpp:uri` functionality inside `Uri` - return websocketpp::uri(this->secure, this->host, this->port, this->chargepoint_id); + return websocketpp::uri(this->secure, this->host, this->port, + this->path_without_chargepoint_id + "/" + this->chargepoint_id); } private: - Uri(bool secure, const std::string& host, uint16_t port, const std::string& chargepoint_id) : - secure(secure), host(host), port(port), chargepoint_id(chargepoint_id) { + Uri(bool secure, const std::string& host, uint16_t port, const std::string& path_without_chargepoint_id, + const std::string& chargepoint_id) : + secure(secure), + host(host), + port(port), + path_without_chargepoint_id(path_without_chargepoint_id), + chargepoint_id(chargepoint_id) { } bool secure; std::string host; uint16_t port; + std::string path_without_chargepoint_id; std::string chargepoint_id; }; diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 3d8f384c0..caeae08ee 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -9,14 +9,29 @@ #include #include +#include namespace ocpp { -auto path_last_segment(const std::string_view path) -> std::string { - return std::string(path.substr(path.rfind("/"), path.length())); +auto path_split_last_segment(const std::string_view path) { + struct result { + std::string path_without_last_segment; + std::string last_segment; + }; + + auto pos_last_slash = path.rfind("/"); + + return result{std::string(path.substr(pos_last_slash, path.length())), std::string(path.substr(0, pos_last_slash))}; } Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile) { + if (uri.empty()) { + throw std::invalid_argument("`uri`-parameter must not be empty"); + } + if (chargepoint_id.empty()) { + throw std::invalid_argument("`chargepoint_id`-parameter must not be empty"); + } + // workaround for required schema in `websocketpp::uri()` bool scheme_added_workaround = false; if (uri.find("://") == std::string::npos) { @@ -40,20 +55,23 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec if (!uri_temp.get_secure()) { throw std::invalid_argument("insecure schema in URI does not fit with secure security-profile"); } + default: + throw std::invalid_argument("`security_profile`-parameter has unknown value = " + + std::to_string(security_profile)); } } - const auto& base = path_last_segment(uri_temp.get_resource()); - if (!base.empty()) { - if (base != chargepoint_id) { - throw std::invalid_argument( - "Uri constructor: the chargepoint-ID in the `uri`-path is different to the defined one"); - } + auto path = uri_temp.get_resource(); - chargepoint_id = base; + // backwards-compatibility: remove chargepoint-ID from URI, if given as last path-segment + if (path != "/") { + const auto [path_without_base, base] = path_split_last_segment(path); + if (base == chargepoint_id) { + path = path_without_base; + } } - return Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), chargepoint_id); + return Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), path, chargepoint_id); } } // namespace ocpp From 8b8e2693e4302875d840ca4dfb60759fdab754cd Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 2 Nov 2023 12:48:31 +0100 Subject: [PATCH 30/43] WIP: check OCPP1.6 with security-profile=1 Signed-off-by: Dominik K --- config/v16/config-docker.json | 117 +++++++++--------- lib/ocpp/common/websocket/websocket_plain.cpp | 3 +- lib/ocpp/common/websocket/websocket_tls.cpp | 4 +- 3 files changed, 64 insertions(+), 60 deletions(-) diff --git a/config/v16/config-docker.json b/config/v16/config-docker.json index 7f237149c..54c0c9d56 100644 --- a/config/v16/config-docker.json +++ b/config/v16/config-docker.json @@ -1,60 +1,61 @@ { - "Internal": { - "ChargePointId": "cp001", - "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/cp001", - "ChargeBoxSerialNumber": "cp001", - "ChargePointModel": "Yeti", - "ChargePointVendor": "Pionix", - "FirmwareVersion": "0.1", - "AllowChargingProfileWithoutStartSchedule": true - }, - "Core": { - "AuthorizeRemoteTxRequests": false, - "ClockAlignedDataInterval": 900, - "ConnectionTimeOut": 30, - "ConnectorPhaseRotation": "0.RST,1.RST", - "GetConfigurationMaxKeys": 100, - "HeartbeatInterval": 86400, - "LocalAuthorizeOffline": false, - "LocalPreAuthorize": false, - "MeterValuesAlignedData": "Energy.Active.Import.Register", - "MeterValuesSampledData": "Energy.Active.Import.Register", - "MeterValueSampleInterval": 60, - "NumberOfConnectors": 1, - "ResetRetries": 1, - "StopTransactionOnEVSideDisconnect": true, - "StopTransactionOnInvalidId": true, - "StopTxnAlignedData": "Energy.Active.Import.Register", - "StopTxnSampledData": "Energy.Active.Import.Register", - "SupportedFeatureProfiles": "Core,FirmwareManagement,RemoteTrigger,Reservation,LocalAuthListManagement,SmartCharging", - "TransactionMessageAttempts": 1, - "TransactionMessageRetryInterval": 10, - "UnlockConnectorOnEVSideDisconnect": true, - "WebsocketPingInterval": 0 - }, - "FirmwareManagement": { - "SupportedFileTransferProtocols": "FTP" - }, - "Security": { - "SecurityProfile": 0, - "CpoName": "Pionix" - }, - "LocalAuthListManagement": { - "LocalAuthListEnabled": true, - "LocalAuthListMaxLength": 42, - "SendLocalListMaxLength": 42 - }, - "SmartCharging": { - "ChargeProfileMaxStackLevel": 42, - "ChargingScheduleAllowedChargingRateUnit": "Current,Power", - "ChargingScheduleMaxPeriods": 42, - "MaxChargingProfilesInstalled": 42 - }, - "PnC": { - "ISO15118PnCEnabled": true, - "ContractValidationOffline": true - }, - "Custom": { - "ExampleConfigurationKey": "example" - } + "Internal": { + "ChargePointId": "cp001", + "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/cp001", + "ChargeBoxSerialNumber": "cp001", + "ChargePointModel": "Yeti", + "ChargePointVendor": "Pionix", + "FirmwareVersion": "0.1", + "AllowChargingProfileWithoutStartSchedule": true + }, + "Core": { + "AuthorizeRemoteTxRequests": false, + "ClockAlignedDataInterval": 900, + "ConnectionTimeOut": 30, + "ConnectorPhaseRotation": "0.RST,1.RST", + "GetConfigurationMaxKeys": 100, + "HeartbeatInterval": 86400, + "LocalAuthorizeOffline": false, + "LocalPreAuthorize": false, + "MeterValuesAlignedData": "Energy.Active.Import.Register", + "MeterValuesSampledData": "Energy.Active.Import.Register", + "MeterValueSampleInterval": 60, + "NumberOfConnectors": 1, + "ResetRetries": 1, + "StopTransactionOnEVSideDisconnect": true, + "StopTransactionOnInvalidId": true, + "StopTxnAlignedData": "Energy.Active.Import.Register", + "StopTxnSampledData": "Energy.Active.Import.Register", + "SupportedFeatureProfiles": "Core,FirmwareManagement,RemoteTrigger,Reservation,LocalAuthListManagement,SmartCharging", + "TransactionMessageAttempts": 1, + "TransactionMessageRetryInterval": 10, + "UnlockConnectorOnEVSideDisconnect": true, + "WebsocketPingInterval": 0 + }, + "FirmwareManagement": { + "SupportedFileTransferProtocols": "FTP" + }, + "Security": { + "SecurityProfile": 1, + "CpoName": "Pionix", + "AuthorizationKey": "12345678" + }, + "LocalAuthListManagement": { + "LocalAuthListEnabled": true, + "LocalAuthListMaxLength": 42, + "SendLocalListMaxLength": 42 + }, + "SmartCharging": { + "ChargeProfileMaxStackLevel": 42, + "ChargingScheduleAllowedChargingRateUnit": "Current,Power", + "ChargingScheduleMaxPeriods": 42, + "MaxChargingProfilesInstalled": 42 + }, + "PnC": { + "ISO15118PnCEnabled": true, + "ContractValidationOffline": true + }, + "Custom": { + "ExampleConfigurationKey": "example" + } } diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 84f846c68..999510b41 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -26,7 +26,8 @@ void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& co case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: throw std::invalid_argument("`security_profile` is not a plain, unsecured one."); default: - throw std::invalid_argument("unknown `security_profile`"); + throw std::invalid_argument("unknown `security_profile`, value = " + + std::to_string(connection_options.security_profile)); } set_connection_options_base(connection_options); diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 953a1a7d6..6d57e27b5 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace ocpp { @@ -30,7 +31,8 @@ void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& conn case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: break; default: - throw std::invalid_argument("unknown `security_profile`"); + throw std::invalid_argument("unknown `security_profile`, value = " + + std::to_string(connection_options.security_profile)); } set_connection_options_base(connection_options); From fbfcae7947d1eef6ab7a27dcd414b573df33f75b Mon Sep 17 00:00:00 2001 From: Dominik K Date: Fri, 3 Nov 2023 15:56:28 +0100 Subject: [PATCH 31/43] remove optional last slash Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_uri.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index caeae08ee..dd5cda8af 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -13,15 +13,19 @@ namespace ocpp { -auto path_split_last_segment(const std::string_view path) { +auto path_split_last_segment(std::string path) { struct result { std::string path_without_last_segment; std::string last_segment; }; auto pos_last_slash = path.rfind("/"); + if (pos_last_slash == path.length() + 1) { + path.pop_back(); + pos_last_slash = path.rfind("/"); + } - return result{std::string(path.substr(pos_last_slash, path.length())), std::string(path.substr(0, pos_last_slash))}; + return result{std::string(path.substr(0, pos_last_slash)), std::string(path.substr(0, pos_last_slash))}; } Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile) { From bf9bdc61bde6c4ffe8d9006b15c616f677f902e2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 6 Nov 2023 15:25:29 +0100 Subject: [PATCH 32/43] fix correct path splitting Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_uri.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index dd5cda8af..6d917dfdd 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -20,12 +20,17 @@ auto path_split_last_segment(std::string path) { }; auto pos_last_slash = path.rfind("/"); + if (pos_last_slash == path.length() + 1) { path.pop_back(); pos_last_slash = path.rfind("/"); } - return result{std::string(path.substr(0, pos_last_slash)), std::string(path.substr(0, pos_last_slash))}; + auto path_without_last_segment = std::string(path.substr(0, pos_last_slash)); + + auto last_segment = std::string(path.substr(pos_last_slash + 1)); + + return result{path_without_last_segment, last_segment}; } Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile) { From f5f0091aaa7a862bf6ef16f0b3f30480b84a85ec Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 6 Nov 2023 16:09:49 +0100 Subject: [PATCH 33/43] fix fallthrough in switch Signed-off-by: Dominik K --- lib/CMakeLists.txt | 7 +++++++ lib/ocpp/common/websocket/websocket_uri.cpp | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8fc43f80a..027d25203 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,6 +1,13 @@ # OCPP library add_library(ocpp) add_library(everest::ocpp ALIAS ocpp) + +target_compile_options(ocpp + PRIVATE + -Werror # turn warnings into errors + -Wimplicit-fallthrough # avoid unintended fallthroughs +) + target_sources(ocpp PRIVATE ocpp/common/call_types.cpp diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 6d917dfdd..87a290601 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -57,13 +57,19 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec switch (security_profile) { // `switch` to lint for unused enum-values case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: if (uri_temp.get_secure()) { - throw std::invalid_argument("secure schema in URI does not fit with insecure security-profile"); + throw std::invalid_argument( + "secure schema 'ws://' in URI does not fit with insecure security-profile = " + + std::to_string(security_profile)); } + break; case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: case security::SecurityProfile::TLS_WITH_CLIENT_SIDE_CERTIFICATES: if (!uri_temp.get_secure()) { - throw std::invalid_argument("insecure schema in URI does not fit with secure security-profile"); + throw std::invalid_argument( + "insecure schema 'ws://' in URI does not fit with secure security-profile = " + + std::to_string(security_profile)); } + break; default: throw std::invalid_argument("`security_profile`-parameter has unknown value = " + std::to_string(security_profile)); From 75a1705643a9779c106ae29a364fb33181a435ea Mon Sep 17 00:00:00 2001 From: Dominik K Date: Mon, 6 Nov 2023 16:40:10 +0100 Subject: [PATCH 34/43] 1.6: connection to SteVe working Signed-off-by: Dominik K --- config/v16/config-docker.json | 2 +- lib/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/v16/config-docker.json b/config/v16/config-docker.json index 54c0c9d56..0bc15914c 100644 --- a/config/v16/config-docker.json +++ b/config/v16/config-docker.json @@ -1,7 +1,7 @@ { "Internal": { "ChargePointId": "cp001", - "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/cp001", + "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/", "ChargeBoxSerialNumber": "cp001", "ChargePointModel": "Yeti", "ChargePointVendor": "Pionix", diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 027d25203..2190fc29a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,7 +4,7 @@ add_library(everest::ocpp ALIAS ocpp) target_compile_options(ocpp PRIVATE - -Werror # turn warnings into errors + #-Werror # turn warnings into errors -Wimplicit-fallthrough # avoid unintended fallthroughs ) From fe08ff2e06766274e48310640262e9e2b0fab111 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 7 Nov 2023 14:29:31 +0100 Subject: [PATCH 35/43] path normalization Signed-off-by: Dominik K --- include/ocpp/common/websocket/websocket_uri.hpp | 3 ++- lib/ocpp/common/websocket/websocket_uri.cpp | 16 +++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index f07614fdd..68d0bb857 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -40,7 +40,8 @@ class Uri { websocketpp::uri get_websocketpp_uri() { // FIXME: wrap needed `websocketpp:uri` functionality inside `Uri` return websocketpp::uri(this->secure, this->host, this->port, - this->path_without_chargepoint_id + "/" + this->chargepoint_id); + this->path_without_chargepoint_id /* is normalized with ending slash */ + + this->chargepoint_id); } private: diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 87a290601..748948af1 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -19,14 +19,18 @@ auto path_split_last_segment(std::string path) { std::string last_segment; }; + if (path == "/") { + return result{"/", ""}; + } auto pos_last_slash = path.rfind("/"); - if (pos_last_slash == path.length() + 1) { + if (pos_last_slash == path.length() - 1) { path.pop_back(); - pos_last_slash = path.rfind("/"); + pos_last_slash -= 1; } auto path_without_last_segment = std::string(path.substr(0, pos_last_slash)); + std::string last_segment = std::string(path.substr(pos_last_slash + 1)); auto last_segment = std::string(path.substr(pos_last_slash + 1)); @@ -79,11 +83,9 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec auto path = uri_temp.get_resource(); // backwards-compatibility: remove chargepoint-ID from URI, if given as last path-segment - if (path != "/") { - const auto [path_without_base, base] = path_split_last_segment(path); - if (base == chargepoint_id) { - path = path_without_base; - } + const auto [path_without_base, base] = path_split_last_segment(path); + if (base == chargepoint_id) { + path = path_without_base; } return Uri(uri_temp.get_secure(), uri_temp.get_host(), uri_temp.get_port(), path, chargepoint_id); From 3af51e335816a9bdf9f7669517347ae2cf4b2744 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 7 Nov 2023 15:39:44 +0100 Subject: [PATCH 36/43] (merge) fixes Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- lib/ocpp/common/websocket/websocket_uri.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 7c1903a36..cba068d8b 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -55,7 +55,7 @@ bool WebsocketTLS::connect() { websocket_thread.reset(new websocketpp::lib::thread(&tls_client::run, &this->wss_client)); this->wss_client.set_tls_init_handler( - websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->connection_options.csms_uri.get_chargepoint_id(), + websocketpp::lib::bind(&WebsocketTLS::on_tls_init, this, this->connection_options.csms_uri.get_hostname(), websocketpp::lib::placeholders::_1, this->connection_options.security_profile)); this->reconnect_callback = [this](const websocketpp::lib::error_code& ec) { diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 748948af1..b7549b664 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -29,7 +29,7 @@ auto path_split_last_segment(std::string path) { pos_last_slash -= 1; } - auto path_without_last_segment = std::string(path.substr(0, pos_last_slash)); + auto path_without_last_segment = std::string(path.substr(0, pos_last_slash + 1)); std::string last_segment = std::string(path.substr(pos_last_slash + 1)); auto last_segment = std::string(path.substr(pos_last_slash + 1)); From e9263b1765b5be4bc7d9526e8b02fb440c4b95b9 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 8 Nov 2023 13:12:40 +0100 Subject: [PATCH 37/43] make clang-format happy again Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 2 +- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 711be329b..867cfde7e 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -585,7 +585,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 1720e8350..2ebf3c868 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -189,7 +189,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index cba068d8b..be2ef0e20 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -270,7 +270,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; From 11c0a93a9099fa21c0c96539048816a0f2c72fb2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 8 Nov 2023 19:55:30 +0100 Subject: [PATCH 38/43] re-format touched JSONs with new `.editorconfig` Signed-off-by: Dominik K --- .editorconfig | 3 + config/v16/config-docker-tls.json | 2 +- config/v16/config-docker.json | 118 +++++++++++++++--------------- 3 files changed, 63 insertions(+), 60 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..1303e813e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.json] +indent_style = space +indent_size = 4 diff --git a/config/v16/config-docker-tls.json b/config/v16/config-docker-tls.json index 8391fa411..4133e48ec 100644 --- a/config/v16/config-docker-tls.json +++ b/config/v16/config-docker-tls.json @@ -1,7 +1,7 @@ { "Internal": { "ChargePointId": "cp001", - "CentralSystemURI": "127.0.0.1:8443/steve/websocket/CentralSystemService/cp001", + "CentralSystemURI": "127.0.0.1:8443/steve/websocket/CentralSystemService/", "ChargeBoxSerialNumber": "cp001", "ChargePointModel": "Yeti", "ChargePointVendor": "Pionix", diff --git a/config/v16/config-docker.json b/config/v16/config-docker.json index 0bc15914c..2c66ecf5d 100644 --- a/config/v16/config-docker.json +++ b/config/v16/config-docker.json @@ -1,61 +1,61 @@ { - "Internal": { - "ChargePointId": "cp001", - "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/", - "ChargeBoxSerialNumber": "cp001", - "ChargePointModel": "Yeti", - "ChargePointVendor": "Pionix", - "FirmwareVersion": "0.1", - "AllowChargingProfileWithoutStartSchedule": true - }, - "Core": { - "AuthorizeRemoteTxRequests": false, - "ClockAlignedDataInterval": 900, - "ConnectionTimeOut": 30, - "ConnectorPhaseRotation": "0.RST,1.RST", - "GetConfigurationMaxKeys": 100, - "HeartbeatInterval": 86400, - "LocalAuthorizeOffline": false, - "LocalPreAuthorize": false, - "MeterValuesAlignedData": "Energy.Active.Import.Register", - "MeterValuesSampledData": "Energy.Active.Import.Register", - "MeterValueSampleInterval": 60, - "NumberOfConnectors": 1, - "ResetRetries": 1, - "StopTransactionOnEVSideDisconnect": true, - "StopTransactionOnInvalidId": true, - "StopTxnAlignedData": "Energy.Active.Import.Register", - "StopTxnSampledData": "Energy.Active.Import.Register", - "SupportedFeatureProfiles": "Core,FirmwareManagement,RemoteTrigger,Reservation,LocalAuthListManagement,SmartCharging", - "TransactionMessageAttempts": 1, - "TransactionMessageRetryInterval": 10, - "UnlockConnectorOnEVSideDisconnect": true, - "WebsocketPingInterval": 0 - }, - "FirmwareManagement": { - "SupportedFileTransferProtocols": "FTP" - }, - "Security": { - "SecurityProfile": 1, - "CpoName": "Pionix", - "AuthorizationKey": "12345678" - }, - "LocalAuthListManagement": { - "LocalAuthListEnabled": true, - "LocalAuthListMaxLength": 42, - "SendLocalListMaxLength": 42 - }, - "SmartCharging": { - "ChargeProfileMaxStackLevel": 42, - "ChargingScheduleAllowedChargingRateUnit": "Current,Power", - "ChargingScheduleMaxPeriods": 42, - "MaxChargingProfilesInstalled": 42 - }, - "PnC": { - "ISO15118PnCEnabled": true, - "ContractValidationOffline": true - }, - "Custom": { - "ExampleConfigurationKey": "example" - } + "Internal": { + "ChargePointId": "cp001", + "CentralSystemURI": "127.0.0.1:8180/steve/websocket/CentralSystemService/", + "ChargeBoxSerialNumber": "cp001", + "ChargePointModel": "Yeti", + "ChargePointVendor": "Pionix", + "FirmwareVersion": "0.1", + "AllowChargingProfileWithoutStartSchedule": true + }, + "Core": { + "AuthorizeRemoteTxRequests": false, + "ClockAlignedDataInterval": 900, + "ConnectionTimeOut": 30, + "ConnectorPhaseRotation": "0.RST,1.RST", + "GetConfigurationMaxKeys": 100, + "HeartbeatInterval": 86400, + "LocalAuthorizeOffline": false, + "LocalPreAuthorize": false, + "MeterValuesAlignedData": "Energy.Active.Import.Register", + "MeterValuesSampledData": "Energy.Active.Import.Register", + "MeterValueSampleInterval": 60, + "NumberOfConnectors": 1, + "ResetRetries": 1, + "StopTransactionOnEVSideDisconnect": true, + "StopTransactionOnInvalidId": true, + "StopTxnAlignedData": "Energy.Active.Import.Register", + "StopTxnSampledData": "Energy.Active.Import.Register", + "SupportedFeatureProfiles": "Core,FirmwareManagement,RemoteTrigger,Reservation,LocalAuthListManagement,SmartCharging", + "TransactionMessageAttempts": 1, + "TransactionMessageRetryInterval": 10, + "UnlockConnectorOnEVSideDisconnect": true, + "WebsocketPingInterval": 0 + }, + "FirmwareManagement": { + "SupportedFileTransferProtocols": "FTP" + }, + "Security": { + "CpoName": "Pionix", + "AuthorizationKey": "AABBCCDDEEFFGGHH", + "SecurityProfile": 1 + }, + "LocalAuthListManagement": { + "LocalAuthListEnabled": true, + "LocalAuthListMaxLength": 42, + "SendLocalListMaxLength": 42 + }, + "SmartCharging": { + "ChargeProfileMaxStackLevel": 42, + "ChargingScheduleAllowedChargingRateUnit": "Current,Power", + "ChargingScheduleMaxPeriods": 42, + "MaxChargingProfilesInstalled": 42 + }, + "PnC": { + "ISO15118PnCEnabled": true, + "ContractValidationOffline": true + }, + "Custom": { + "ExampleConfigurationKey": "example" + } } From 2bfa19eb8e96b18d09d9d59f6c5df17d3a3acde2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 8 Nov 2023 21:44:57 +0100 Subject: [PATCH 39/43] fix doubled `last_segment` Signed-off-by: Dominik K --- lib/ocpp/common/websocket/websocket_uri.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index b7549b664..9ecd9bbf1 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -30,8 +30,6 @@ auto path_split_last_segment(std::string path) { } auto path_without_last_segment = std::string(path.substr(0, pos_last_slash + 1)); - std::string last_segment = std::string(path.substr(pos_last_slash + 1)); - auto last_segment = std::string(path.substr(pos_last_slash + 1)); return result{path_without_last_segment, last_segment}; From 2cb761d0f16438d533a267165963542592779493 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 9 Nov 2023 14:59:48 +0100 Subject: [PATCH 40/43] use Doxygen comments Signed-off-by: Dominik K --- .../ocpp/common/websocket/websocket_uri.hpp | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/include/ocpp/common/websocket/websocket_uri.hpp b/include/ocpp/common/websocket/websocket_uri.hpp index 68d0bb857..c91f51339 100644 --- a/include/ocpp/common/websocket/websocket_uri.hpp +++ b/include/ocpp/common/websocket/websocket_uri.hpp @@ -13,15 +13,22 @@ class Uri { public: Uri(){}; - // parse_and_validate parses the URI and checks - // 1. general validity of the URI - // 2. scheme fits to given `security_profile` - // - // Backwards-compatibility: The path (of the URI) can contain the `chargepoint_id` as last segment. - // - // It throws `std::invalid_argument` for several checks + // clang-format off + /// \brief parse_and_validate parses the \p uri and checks + /// 1. the general validity of it and + /// 2. if optional scheme fits to given \p security_profile + /// + /// \param uri The whole URI with optional scheme and \p chargepoint_id as last segment (as backward-compatibility). + /// \param chargepoint_id The identifier unique to the CSMS. + /// \param security_profile The security-profile. + /// \returns Uri + /// \throws std::invalid_argument for several checks + // clang-format on static Uri parse_and_validate(std::string uri, std::string chargepoint_id, int security_profile); + /// \brief set_secure defines if the connection is done via TLS + /// + /// \param secure true: connect via TLS; false: connect as plaintext void set_secure(bool secure) { this->secure = secure; } From ae3922ae5d7bb7e0cc70ed78f657c4ff49662411 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 9 Nov 2023 15:34:53 +0100 Subject: [PATCH 41/43] allow `SecurityProfile = 0` for OCPP 1.6 Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 4 ++-- lib/ocpp/common/websocket/websocket_plain.cpp | 3 ++- lib/ocpp/common/websocket/websocket_tls.cpp | 3 ++- lib/ocpp/common/websocket/websocket_uri.cpp | 1 + lib/ocpp/v201/charge_point.cpp | 22 ++++++++++++++----- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 867cfde7e..b42e8faae 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -562,7 +562,7 @@ namespace security { // The security profiles defined in OCPP 2.0.1 resp. in the OCPP 1.6 security-whitepaper. enum SecurityProfile { // no "enum class" because values are used in implicit `switch`-comparisons to `int // security_profile` - UNSPECIFIED = 0, + OCPP_1_6_ONLY_UNSECURED_TRANSPORT_WITHOUT_BASIC_AUTHENTICATION = 0, UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION = 1, TLS_WITH_BASIC_AUTHENTICATION = 2, TLS_WITH_CLIENT_SIDE_CERTIFICATES = 3, @@ -585,7 +585,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 2ebf3c868..484f87d51 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -20,6 +20,7 @@ WebsocketPlain::WebsocketPlain(const WebsocketConnectionOptions& connection_opti void WebsocketPlain::set_connection_options(const WebsocketConnectionOptions& connection_options) { switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values + case security::SecurityProfile::OCPP_1_6_ONLY_UNSECURED_TRANSPORT_WITHOUT_BASIC_AUTHENTICATION: case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: break; case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: @@ -189,7 +190,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index be2ef0e20..66e231463 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -25,6 +25,7 @@ WebsocketTLS::WebsocketTLS(const WebsocketConnectionOptions& connection_options, void WebsocketTLS::set_connection_options(const WebsocketConnectionOptions& connection_options) { switch (connection_options.security_profile) { // `switch` used to lint on missing enum-values + case security::SecurityProfile::OCPP_1_6_ONLY_UNSECURED_TRANSPORT_WITHOUT_BASIC_AUTHENTICATION: case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: throw std::invalid_argument("`security_profile` is not a TLS-profile"); case security::SecurityProfile::TLS_WITH_BASIC_AUTHENTICATION: @@ -270,7 +271,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_uri.cpp b/lib/ocpp/common/websocket/websocket_uri.cpp index 9ecd9bbf1..dc8e82699 100644 --- a/lib/ocpp/common/websocket/websocket_uri.cpp +++ b/lib/ocpp/common/websocket/websocket_uri.cpp @@ -57,6 +57,7 @@ Uri Uri::parse_and_validate(std::string uri, std::string chargepoint_id, int sec if (!scheme_added_workaround) { switch (security_profile) { // `switch` to lint for unused enum-values + case security::SecurityProfile::OCPP_1_6_ONLY_UNSECURED_TRANSPORT_WITHOUT_BASIC_AUTHENTICATION: case security::SecurityProfile::UNSECURED_TRANSPORT_WITH_BASIC_AUTHENTICATION: if (uri_temp.get_secure()) { throw std::invalid_argument( diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 0834df9b5..68ea3d5be 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -1,12 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest -#include "ocpp/v201/ctrlr_component_variables.hpp" +#include #include +#include #include #include #include +#include +#include + using namespace std::chrono_literals; const auto DEFAULT_MAX_CUSTOMER_INFORMATION_DATA_LENGTH = 51200; @@ -722,16 +726,15 @@ WebsocketConnectionOptions ChargePoint::get_ws_connection_options(const int32_t const auto network_connection_profile = network_connection_profile_opt.value(); - auto security_profile = network_connection_profile.securityProfile; auto uri = Uri::parse_and_validate( network_connection_profile.ocppCsmsUrl.get(), this->device_model->get_value(ControllerComponentVariables::SecurityCtrlrIdentity), - security_profile); + network_connection_profile.securityProfile); WebsocketConnectionOptions connection_options{ OcppProtocolVersion::v201, uri, - security_profile, + network_connection_profile.securityProfile, this->device_model->get_optional_value(ControllerComponentVariables::BasicAuthPassword), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRandomRange), this->device_model->get_value(ControllerComponentVariables::RetryBackOffRepeatTimes), @@ -757,6 +760,15 @@ std::optional ChargePoint::get_network_connection_prof for (const auto& network_profile : network_connection_profiles) { if (network_profile.configurationSlot == configuration_slot) { + auto security_profile = network_profile.connectionData.securityProfile; + switch (security_profile) { + case security::OCPP_1_6_ONLY_UNSECURED_TRANSPORT_WITHOUT_BASIC_AUTHENTICATION: + throw std::invalid_argument("security_profile = " + std::to_string(security_profile) + + " not officially allowed in OCPP 2.0.1"); + default: + break; + } + return network_profile.connectionData; } } @@ -2529,4 +2541,4 @@ void ChargePoint::handle_get_local_authorization_list_version_req(Call Date: Thu, 9 Nov 2023 15:39:29 +0100 Subject: [PATCH 42/43] require `SecurityCtrlr.Identity` Signed-off-by: Dominik K --- config/v201/component_schemas/standardized/SecurityCtrlr.json | 3 ++- lib/ocpp/v16/charge_point_impl.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/v201/component_schemas/standardized/SecurityCtrlr.json b/config/v201/component_schemas/standardized/SecurityCtrlr.json index 46b6274a1..bcaf56949 100644 --- a/config/v201/component_schemas/standardized/SecurityCtrlr.json +++ b/config/v201/component_schemas/standardized/SecurityCtrlr.json @@ -174,6 +174,7 @@ "required": [ "CertificateEntries", "OrganizationName", - "SecurityProfile" + "SecurityProfile", + "Identity" ] } diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index 8ea8abdac..f25088de9 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -3449,4 +3449,4 @@ ConfigurationStatus ChargePointImpl::set_custom_configuration_key(CiString<50> k } } // namespace v16 -} // namespace ocpp \ No newline at end of file +} // namespace ocpp From bcc88df958726bdb33470369d58d880535cb3906 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Thu, 9 Nov 2023 16:06:35 +0100 Subject: [PATCH 43/43] make `clang-format` happy again Signed-off-by: Dominik K --- include/ocpp/common/types.hpp | 2 +- lib/ocpp/common/websocket/websocket_plain.cpp | 2 +- lib/ocpp/common/websocket/websocket_tls.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index b42e8faae..c085458b7 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -585,7 +585,7 @@ inline const std::string RESET_OR_REBOOT = "ResetOrReboot"; // CRI inline const std::string STARTUP_OF_THE_DEVICE = "StartupOfTheDevice"; // CRITICAL inline const std::string SECURITYLOGWASCLEARED = "SecurityLogWasCleared"; // CRITICAL inline const std::string RECONFIGURATIONOFSECURITYPARAMETERS = "ReconfigurationOfSecurityParameters"; -inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL +inline const std::string MEMORYEXHAUSTION = "MemoryExhaustion"; // CRITICAL inline const std::string INVALIDMESSAGES = "InvalidMessages"; inline const std::string ATTEMPTEDREPLAYATTACKS = "AttemptedReplayAttacks"; inline const std::string TAMPERDETECTIONACTIVATED = "TamperDetectionActivated"; // CRITICAL diff --git a/lib/ocpp/common/websocket/websocket_plain.cpp b/lib/ocpp/common/websocket/websocket_plain.cpp index 484f87d51..5cc56f314 100644 --- a/lib/ocpp/common/websocket/websocket_plain.cpp +++ b/lib/ocpp/common/websocket/websocket_plain.cpp @@ -190,7 +190,7 @@ void WebsocketPlain::connect_plain() { void WebsocketPlain::on_open_plain(client* c, websocketpp::connection_hdl hdl) { std::lock_guard lk(this->connection_mutex); - (void)c; // client is not used in this function + (void)c; // client is not used in this function EVLOG_info << "OCPP client successfully connected to plain websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true; diff --git a/lib/ocpp/common/websocket/websocket_tls.cpp b/lib/ocpp/common/websocket/websocket_tls.cpp index 66e231463..19a628ac4 100644 --- a/lib/ocpp/common/websocket/websocket_tls.cpp +++ b/lib/ocpp/common/websocket/websocket_tls.cpp @@ -271,7 +271,7 @@ void WebsocketTLS::connect_tls() { this->wss_client.connect(con); } void WebsocketTLS::on_open_tls(tls_client* c, websocketpp::connection_hdl hdl) { - (void)c; // tls_client is not used in this function + (void)c; // tls_client is not used in this function EVLOG_info << "OCPP client successfully connected to TLS websocket server"; this->connection_attempts = 1; // reset connection attempts this->m_is_connected = true;