Skip to content

Commit 48f7846

Browse files
committed
Cleanup. Introduce new mutex to prevent pending, active and requested network slots in connectivity manager.
Signed-off-by: Maaike <maaike@iolar.nl>
1 parent 53668f2 commit 48f7846

11 files changed

+160
-512
lines changed

include/ocpp/common/websocket/websocket.hpp

-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class Websocket {
2121
// unique_ptr holds address of base - requires WebSocketBase to have a virtual destructor
2222
std::unique_ptr<WebsocketBase> websocket;
2323
std::function<void(const int security_profile)> connected_callback;
24-
// std::function<void()> disconnected_callback;
2524
std::function<void(const WebsocketCloseReason reason)> closed_callback;
2625
std::function<void(const WebsocketCloseReason reason)> failed_callback;
2726
std::function<void(const std::string& message)> message_callback;
@@ -42,7 +41,6 @@ class Websocket {
4241
void disconnect(const WebsocketCloseReason code);
4342

4443
// \brief reconnects the websocket after the delay
45-
// void reconnect(std::error_code reason, long delay);
4644
void reconnect();
4745

4846
/// \brief indicates if the websocket is connected
@@ -51,9 +49,6 @@ class Websocket {
5149
/// \brief register a \p callback that is called when the websocket is connected successfully
5250
void register_connected_callback(const std::function<void(const int security_profile)>& callback);
5351

54-
/// \brief register a \p callback that is called when the websocket connection is disconnected
55-
// void register_disconnected_callback(const std::function<void()>& callback);
56-
5752
/// \brief register a \p callback that is called when the websocket connection has been closed and will not attempt
5853
/// to reconnect
5954
void register_closed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback);

include/ocpp/common/websocket/websocket_base.hpp

+5-19
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct WebsocketConnectionOptions {
3636
std::optional<std::string> hostName;
3737
bool verify_csms_common_name;
3838
bool use_tpm_tls;
39-
std::optional<std::string> iface_or_ip; ///< The interface of the connection or the ip address of the interface
39+
std::optional<std::string> iface_or_ip; ///< The interface of the connection or the ip address of the interface
4040
};
4141

4242
///
@@ -47,20 +47,14 @@ class WebsocketBase {
4747
bool m_is_connected;
4848
WebsocketConnectionOptions connection_options;
4949
std::function<void(const int security_profile)> connected_callback;
50-
// std::function<void()> disconnected_callback;
5150
std::function<void(const WebsocketCloseReason reason)> closed_callback;
5251
std::function<void(const WebsocketCloseReason reason)> failed_callback;
5352
std::function<void(const std::string& message)> message_callback;
54-
// websocketpp::lib::shared_ptr<boost::asio::steady_timer> reconnect_timer;
5553
std::unique_ptr<Everest::SteadyTimer> ping_timer;
5654
websocketpp::connection_hdl handle;
5755
std::mutex reconnect_mutex;
5856
std::mutex connection_mutex;
59-
// long reconnect_backoff_ms;
60-
// websocketpp::transport::timer_handler reconnect_callback;
61-
// int connection_attempts;
6257
bool shutting_down;
63-
// bool reconnecting;
6458

6559
/// \brief Indicates if the required callbacks are registered
6660
/// \returns true if the websocket is properly initialized
@@ -72,13 +66,6 @@ class WebsocketBase {
7266
/// \brief Logs websocket connection error
7367
void log_on_fail(const std::error_code& ec, const boost::system::error_code& transport_ec, const int http_status);
7468

75-
/// \brief Calculates and returns the reconnect interval based on int retry_backoff_random_range_s,
76-
/// retry_backoff_repeat_times, int retry_backoff_wait_minimum_s of the WebsocketConnectionOptions
77-
// long get_reconnect_interval();
78-
79-
// \brief cancels the reconnect timer
80-
// void cancel_reconnect_timer();
81-
8269
/// \brief send a websocket ping
8370
virtual void ping() = 0;
8471

@@ -99,8 +86,10 @@ class WebsocketBase {
9986
virtual void set_connection_options(const WebsocketConnectionOptions& connection_options) = 0;
10087
void set_connection_options_base(const WebsocketConnectionOptions& connection_options);
10188

102-
/// \brief reconnect the websocket after the delay
103-
// virtual void reconnect(std::error_code reason, long delay) = 0;
89+
/// \brief reconnect the websocket.
90+
///
91+
/// This is needed because of websocketpp: we can not just call 'connect' because the websocket might be in a wrong
92+
/// state here.
10493
virtual void reconnect() = 0;
10594

10695
/// \brief disconnect the websocket
@@ -115,9 +104,6 @@ class WebsocketBase {
115104
/// \brief register a \p callback that is called when the websocket is connected successfully
116105
void register_connected_callback(const std::function<void(const int security_profile)>& callback);
117106

118-
/// \brief register a \p callback that is called when the websocket connection is disconnected
119-
// void register_disconnected_callback(const std::function<void()>& callback);
120-
121107
/// \brief register a \p callback that is called when the websocket connection has been closed and will not attempt
122108
/// to reconnect
123109
void register_closed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback);

include/ocpp/common/websocket/websocket_plain.hpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
#include <thread>
77

8+
#include <everest/logging.hpp>
89
#include <websocketpp/client.hpp>
910
#include <websocketpp/config/asio_client.hpp>
10-
#include <everest/logging.hpp>
1111

1212
#include <ocpp/common/websocket/websocket_base.hpp>
1313

@@ -27,6 +27,9 @@ class WebsocketPlain final : public WebsocketBase {
2727
client ws_client;
2828
websocketpp::lib::shared_ptr<websocketpp::lib::thread> websocket_thread;
2929

30+
/// \brief Set to true if websocket is already closed and should not close it again.
31+
std::atomic_bool closed;
32+
3033
/// \brief Connect to a plain websocket
3134
void connect_plain();
3235

@@ -50,9 +53,11 @@ class WebsocketPlain final : public WebsocketBase {
5053

5154
~WebsocketPlain() {
5255
this->close(WebsocketCloseReason::Normal, "", true);
53-
EVLOG_info << "In websocketplain destructor";
56+
if (!this->ws_client.stopped()) {
57+
this->ws_client.stop();
58+
}
59+
5460
this->websocket_thread->join();
55-
EVLOG_info << "In websocketplain destructor after join";
5661
}
5762

5863
/// \brief connect to a plaintext websocket
@@ -61,7 +66,6 @@ class WebsocketPlain final : public WebsocketBase {
6166

6267
/// \brief Reconnects the websocket using the delay, a reason for this reconnect can be provided with the
6368
/// \p reason parameter
64-
// void reconnect(std::error_code reason, long delay) override;
6569
void reconnect() override;
6670

6771
/// \brief Closes a plaintext websocket connection

include/ocpp/common/websocket/websocket_tls.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class WebsocketTLS final : public WebsocketBase {
6363
/// \brief Reconnects the websocket using the delay, a reason for this reconnect can be provided with the
6464
/// \param reason parameter
6565
/// \param delay delay of the reconnect attempt
66-
// void reconnect(std::error_code reason, long delay) override;
6766
void reconnect() override;
6867

6968
/// \brief closes the websocket

include/ocpp/v201/charge_point.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <ocpp/v201/types.hpp>
2121
#include <ocpp/v201/utils.hpp>
2222

23-
#include "ocpp/v201/connectivity_manager.h"
23+
#include "ocpp/v201/connectivity_manager.hpp"
2424
#include "ocpp/v201/messages/Get15118EVCertificate.hpp"
2525
#include <ocpp/v201/messages/Authorize.hpp>
2626
#include <ocpp/v201/messages/BootNotification.hpp>

include/ocpp/v201/connectivity_manager.h include/ocpp/v201/connectivity_manager.hpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2020 - 2024 Pionix GmbH and Contributors to EVerest
3+
14
#pragma once
25

36
#include <functional>
@@ -42,7 +45,9 @@ class ConnectivityManager {
4245
/// variable.
4346
std::atomic_bool try_reconnect;
4447
/// \brief Mutex for the requested, pending and active network slot.
45-
mutable std::mutex config_slot_mutex;
48+
mutable std::recursive_mutex config_slot_mutex;
49+
/// \brief Mutex for the condition variable.
50+
mutable std::mutex reconnect_mutex;
4651
/// \brief Condition variable that waits until it gets a sign to reconnect.
4752
std::condition_variable reconnect_condition_variable;
4853
/// \brief Reference to the device model class.
@@ -55,7 +60,7 @@ class ConnectivityManager {
5560
std::unique_ptr<Websocket> websocket;
5661
/// \brief The potential interface to use requested by libocpp, but not 'approved' by 'core' yet.
5762
int32_t requested_network_slot;
58-
/// \brief The interface which will be used to connect
63+
/// \brief The interface which will be used to connect, pending connection at the websocket.
5964
int32_t pending_network_slot;
6065
/// \brief The interface which is currently in use by the websocket
6166
int32_t active_network_slot;
@@ -132,16 +137,14 @@ class ConnectivityManager {
132137
/// \brief Stops the ChargePoint. Disconnects the websocket connection and stops MessageQueue and all timers
133138
void stop();
134139

135-
/// @brief Initializes the websocket and connects to CSMS if it is not yet connected.
136-
/// @param configuration_slot Optional configuration slot to connect to
137-
void connect_websocket(std::optional<int32_t> config_slot = std::nullopt);
138-
139140
/// \brief Disconnects the the websocket connection to the CSMS if it is connected
140141
/// \param code Optional websocket close status code (default: normal).
141142
void disconnect_websocket(WebsocketCloseReason code = WebsocketCloseReason::Normal);
142143

143144
/// \brief Switch to a specifc network connection profile given the configuration slot.
144-
/// This disregards the prority
145+
///
146+
/// Switch will only be done when the configuration slot has a higher priority.
147+
///
145148
/// \param configuration_slot Slot in which the configuration is stored
146149
/// \return true if the switch is possible.
147150
bool on_try_switch_network_connection_profile(const int32_t configuration_slot);

lib/ocpp/common/websocket/websocket.cpp

+4-25
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,16 @@ Websocket::Websocket(const WebsocketConnectionOptions& connection_options, std::
2323
this->websocket = std::make_unique<WebsocketTlsTPM>(connection_options, evse_security);
2424
#else
2525
if (connection_options.security_profile <= 1) {
26-
EVLOG_info << "Create plain websocket";
2726
this->websocket = std::make_unique<WebsocketPlain>(connection_options);
28-
EVLOG_info << "Plain websocket created";
2927
} else if (connection_options.security_profile >= 2) {
3028
this->websocket = std::make_unique<WebsocketTLS>(connection_options, evse_security);
3129
}
3230
#endif
3331
}
3432

3533
Websocket::~Websocket() {
36-
if (this->websocket != nullptr)
37-
{
34+
if (this->websocket != nullptr) {
3835
this->websocket->disconnect(WebsocketCloseReason::GoingAway);
39-
this->websocket->close(WebsocketCloseReason::GoingAway, "", true);
4036
this->websocket = nullptr;
4137
}
4238
}
@@ -55,16 +51,10 @@ void Websocket::disconnect(const WebsocketCloseReason code) {
5551
this->websocket->disconnect(code);
5652
}
5753

58-
void Websocket::reconnect()
59-
{
54+
void Websocket::reconnect() {
6055
this->websocket->reconnect();
6156
}
6257

63-
// void Websocket::reconnect(std::error_code reason, long delay) {
64-
// this->logging->sys("Reconnecting");
65-
// this->websocket->reconnect(reason, delay);
66-
// }
67-
6858
bool Websocket::is_connected() {
6959
return this->websocket->is_connected();
7060
}
@@ -78,24 +68,13 @@ void Websocket::register_connected_callback(const std::function<void(const int s
7868
});
7969
}
8070

81-
// void Websocket::register_disconnected_callback(const std::function<void()>& callback) {
82-
// this->disconnected_callback = callback;
83-
84-
// this->websocket->register_disconnected_callback([this]() {
85-
// this->logging->sys("Disconnected");
86-
// this->disconnected_callback();
87-
// });
88-
// }
89-
90-
void Websocket::register_closed_callback(
91-
const std::function<void(const WebsocketCloseReason reason)>& callback) {
71+
void Websocket::register_closed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback) {
9272
this->closed_callback = callback;
9373
this->websocket->register_closed_callback(
9474
[this](const WebsocketCloseReason reason) { this->closed_callback(reason); });
9575
}
9676

97-
void Websocket::register_failed_callback(const std::function<void (const WebsocketCloseReason)> &callback)
98-
{
77+
void Websocket::register_failed_callback(const std::function<void(const WebsocketCloseReason)>& callback) {
9978
this->failed_callback = callback;
10079
this->websocket->register_failed_callback(
10180
[this](const WebsocketCloseReason reason) { this->failed_callback(reason); });

lib/ocpp/common/websocket/websocket_base.cpp

+3-51
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ WebsocketBase::WebsocketBase() :
1111
connected_callback(nullptr),
1212
closed_callback(nullptr),
1313
message_callback(nullptr),
14-
// reconnect_timer(nullptr),
15-
// connection_attempts(0),
16-
// reconnect_backoff_ms(0),
17-
shutting_down(false)/*,
18-
reconnecting(false)*/ {
14+
shutting_down(false) {
1915

2016
set_connection_options_base(connection_options);
2117

@@ -38,17 +34,11 @@ void WebsocketBase::register_connected_callback(const std::function<void(const i
3834
this->connected_callback = callback;
3935
}
4036

41-
// void WebsocketBase::register_disconnected_callback(const std::function<void()>& callback) {
42-
// this->disconnected_callback = callback;
43-
// }
44-
45-
void WebsocketBase::register_closed_callback(
46-
const std::function<void(const WebsocketCloseReason reason)>& callback) {
37+
void WebsocketBase::register_closed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback) {
4738
this->closed_callback = callback;
4839
}
4940

50-
void WebsocketBase::register_failed_callback(const std::function<void (const WebsocketCloseReason)> &callback)
51-
{
41+
void WebsocketBase::register_failed_callback(const std::function<void(const WebsocketCloseReason)>& callback) {
5242
this->failed_callback = callback;
5343
}
5444

@@ -81,9 +71,6 @@ void WebsocketBase::disconnect(WebsocketCloseReason code) {
8171
if (code == WebsocketCloseReason::Normal) {
8272
this->shutting_down = true;
8373
}
84-
// if (this->reconnect_timer) {
85-
// this->reconnect_timer.get()->cancel();
86-
// }
8774
if (this->ping_timer) {
8875
this->ping_timer->stop();
8976
}
@@ -119,36 +106,6 @@ void WebsocketBase::log_on_fail(const std::error_code& ec, const boost::system::
119106
<< ", Transport error category: " << transport_ec.category().name();
120107
}
121108

122-
// long WebsocketBase::get_reconnect_interval() {
123-
124-
// // We need to add 1 to the repeat times since the first try is already connection_attempt 1
125-
// if (this->connection_attempts > (this->connection_options.retry_backoff_repeat_times + 1)) {
126-
// return this->reconnect_backoff_ms;
127-
// }
128-
129-
// std::random_device rd;
130-
// std::mt19937 gen(rd());
131-
// std::uniform_int_distribution<> distr(0, this->connection_options.retry_backoff_random_range_s);
132-
133-
// int random_number = distr(gen);
134-
135-
// if (this->connection_attempts == 1) {
136-
// this->reconnect_backoff_ms = (this->connection_options.retry_backoff_wait_minimum_s + random_number) * 1000;
137-
// return this->reconnect_backoff_ms;
138-
// }
139-
140-
// this->reconnect_backoff_ms = this->reconnect_backoff_ms * 2 + (random_number * 1000);
141-
// return this->reconnect_backoff_ms;
142-
// }
143-
144-
// void WebsocketBase::cancel_reconnect_timer() {
145-
// std::lock_guard<std::mutex> lk(this->reconnect_mutex);
146-
// if (this->reconnect_timer) {
147-
// this->reconnect_timer.get()->cancel();
148-
// }
149-
// this->reconnect_timer = nullptr;
150-
// }
151-
152109
void WebsocketBase::set_websocket_ping_interval(int32_t interval_s) {
153110
if (this->ping_timer) {
154111
this->ping_timer->stop();
@@ -165,11 +122,6 @@ void WebsocketBase::set_authorization_key(const std::string& authorization_key)
165122

166123
void WebsocketBase::on_pong_timeout(websocketpp::connection_hdl hdl, std::string msg) {
167124
this->close(WebsocketCloseReason::GoingAway, "Pong timeout", false);
168-
// if (!this->reconnecting) {
169-
// EVLOG_info << "Reconnecting because of a pong timeout after " << this->connection_options.pong_timeout_s << "s";
170-
// this->reconnecting = true;
171-
// this->close(WebsocketCloseReason::GoingAway, "Pong timeout");
172-
// }
173125
}
174126

175127
} // namespace ocpp

0 commit comments

Comments
 (0)