-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathwebsocket_base.hpp
141 lines (113 loc) · 5.59 KB
/
websocket_base.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest
#ifndef OCPP_WEBSOCKET_BASE_HPP
#define OCPP_WEBSOCKET_BASE_HPP
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <everest/timer.hpp>
#include <websocketpp/client.hpp>
#include <websocketpp/config/asio_client.hpp>
#include <ocpp/common/types.hpp>
#include <ocpp/common/websocket/websocket_uri.hpp>
namespace ocpp {
struct WebsocketConnectionOptions {
OcppProtocolVersion ocpp_version;
Uri csms_uri; // the URI of the CSMS
int security_profile; // FIXME: change type to `SecurityProfile`
std::optional<std::string> authorization_key;
int retry_backoff_random_range_s;
int retry_backoff_repeat_times;
int retry_backoff_wait_minimum_s;
int max_connection_attempts;
std::string supported_ciphers_12;
std::string supported_ciphers_13;
int ping_interval_s;
std::string ping_payload;
int pong_timeout_s;
bool use_ssl_default_verify_paths;
std::optional<bool> additional_root_certificate_check;
std::optional<std::string> hostName;
bool verify_csms_common_name;
bool use_tpm_tls;
bool verify_csms_allow_wildcards;
std::optional<std::string> iface_or_ip; ///< The interface of the connection or the ip address of the interface
};
enum class ConnectionFailedReason {
InvalidCSMSCertificate = 0,
};
///
/// \brief contains a websocket abstraction
///
class WebsocketBase {
protected:
std::atomic_bool m_is_connected;
WebsocketConnectionOptions connection_options;
std::function<void(const int security_profile)> connected_callback;
std::function<void(const WebsocketCloseReason reason)> closed_callback;
std::function<void(const WebsocketCloseReason reason)> failed_callback;
std::function<void(const std::string& message)> message_callback;
std::function<void(ConnectionFailedReason)> connection_failed_callback;
std::unique_ptr<Everest::SteadyTimer> ping_timer;
websocketpp::connection_hdl handle;
std::mutex connection_mutex;
bool shutting_down;
/// \brief Indicates if the required callbacks are registered
/// \returns true if the websocket is properly initialized
bool initialized();
/// \brief getter for authorization header for connection with basic authentication
std::optional<std::string> getAuthorizationHeader();
/// \brief Logs websocket connection error
void log_on_fail(const std::error_code& ec, const boost::system::error_code& transport_ec, const int http_status);
/// \brief send a websocket ping
virtual void ping() = 0;
/// \brief Called when a websocket pong timeout is received
void on_pong_timeout(websocketpp::connection_hdl hdl, std::string msg);
public:
/// \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
/// \returns true if the websocket is initialized and a connection attempt is made
virtual bool connect() = 0;
/// \brief sets this connection_options to the given \p connection_options and resets the connection_attempts
virtual void set_connection_options(const WebsocketConnectionOptions& connection_options) = 0;
void set_connection_options_base(const WebsocketConnectionOptions& connection_options);
/// \brief reconnect the websocket.
///
/// This is needed because of websocketpp: we can not just call 'connect' because the websocket might be in a wrong
/// state here.
virtual void reconnect() = 0;
/// \brief disconnect the websocket
void disconnect(WebsocketCloseReason code);
/// \brief indicates if the websocket is connected
bool is_connected();
/// \brief closes the websocket
virtual void close(WebsocketCloseReason code, const std::string& reason, const bool stop_perpetual) = 0;
/// \brief register a \p callback that is called when the websocket is connected successfully
void register_connected_callback(const std::function<void(const int security_profile)>& callback);
/// \brief register a \p callback that is called when the websocket connection has been closed and will not attempt
/// to reconnect
void register_closed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback);
///
/// \brief Register a callback that is called when the websocket tried to connect, but could not make a connection
/// or was already connected and a failure occured.
/// \param callback The callback.
///
void register_failed_callback(const std::function<void(const WebsocketCloseReason reason)>& callback);
/// \brief register a \p callback that is called when the websocket receives a message
void register_message_callback(const std::function<void(const std::string& message)>& callback);
/// \brief register a \p callback that is called when the websocket could not connect with a specific reason
void register_connection_failed_callback(const std::function<void(ConnectionFailedReason)>& callback);
/// \brief send a \p message over the websocket
/// \returns true if the message was sent successfully
virtual bool send(const std::string& message) = 0;
/// \brief starts a timer that sends a websocket ping at the given \p interval_s
void set_websocket_ping_interval(int32_t interval_s);
/// \brief set the \p authorization_key of the connection_options
void set_authorization_key(const std::string& authorization_key);
};
} // namespace ocpp
#endif // OCPP_WEBSOCKET_BASE_HPP