Skip to content

Commit b0619ca

Browse files
committed
[websocket] Add websocket server implementation
1 parent 0035623 commit b0619ca

File tree

9 files changed

+872
-15
lines changed

9 files changed

+872
-15
lines changed

src/tools/helpers/IniFile.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,19 +378,19 @@ std::string IniFile::Value::toString() const
378378
/** @brief Get the value as an integer */
379379
int IniFile::Value::toInt() const
380380
{
381-
return std::strtol(m_value.c_str(), NULL, 10);
381+
return std::strtol(m_value.c_str(), nullptr, 10);
382382
}
383383

384384
/** @brief Get the value as an unsigned integer */
385385
unsigned int IniFile::Value::toUInt() const
386386
{
387-
return std::strtoul(m_value.c_str(), NULL, 10);
387+
return std::strtoul(m_value.c_str(), nullptr, 10);
388388
}
389389

390390
/** @brief Get the value as a floating point value */
391391
double IniFile::Value::toFloat() const
392392
{
393-
return std::strtod(m_value.c_str(), NULL);
393+
return std::strtod(m_value.c_str(), nullptr);
394394
}
395395

396396
/** @brief Get the value as a boolean */

src/websockets/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_library(ws STATIC
99
Url.cpp
1010
WebsocketFactory.cpp
1111
libwebsockets/LibWebsocketClient.cpp
12+
libwebsockets/LibWebsocketServer.cpp
1213

1314
stubs/WebsocketClientStub.cpp
1415
)

src/websockets/IWebsocketServer.h

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
Copyright (c) 2020 Cedric Jimenez
3+
This file is part of OpenOCPP.
4+
5+
OpenOCPP is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Lesser General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
OpenOCPP is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public License
16+
along with OpenOCPP. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
#ifndef IWEBSOCKETSERVER_H
20+
#define IWEBSOCKETSERVER_H
21+
22+
#include <chrono>
23+
#include <memory>
24+
#include <string>
25+
26+
namespace ocpp
27+
{
28+
namespace websockets
29+
{
30+
31+
/** @brief Interface for websocket server implementations */
32+
class IWebsocketServer
33+
{
34+
public:
35+
// Forward declarations
36+
class IListener;
37+
class IClient;
38+
struct Credentials;
39+
40+
/** @brief Destructor */
41+
virtual ~IWebsocketServer() { }
42+
43+
/**
44+
* @brief Start the server
45+
* @param url URL to listen to
46+
* @param protocol Name of the protocol to use
47+
* @param credentials Credentials to use
48+
* @param ping_interval Interval between 2 websocket PING messages when the socket is idle
49+
* @return true if the server has been started, false otherwise
50+
*/
51+
virtual bool start(const std::string& url,
52+
const std::string& protocol,
53+
const Credentials& credentials,
54+
std::chrono::milliseconds ping_interval = std::chrono::seconds(5)) = 0;
55+
56+
/**
57+
* @brief Stop the server
58+
* @return true if the server has been stopped, false otherwise
59+
*/
60+
virtual bool stop() = 0;
61+
62+
/**
63+
* @brief Register a listener to the websocket events
64+
* @param listener Listener object
65+
*/
66+
virtual void registerListener(IListener& listener) = 0;
67+
68+
/** @brief Interface for the websocket server listeners */
69+
class IListener
70+
{
71+
public:
72+
/** @brief Destructor */
73+
virtual ~IListener() { }
74+
75+
/**
76+
* @brief Called to check the user credentials for HTTP basic authentication
77+
* @param uri Requested URI
78+
* @param user User name
79+
* @param password Password
80+
* @return true if the credentials are valid, false otherwise
81+
*/
82+
virtual bool wsCheckCredentials(const char* uri, const std::string& user, const std::string& password) = 0;
83+
84+
/**
85+
* @brief Called when connection is successfull
86+
* @param uri Requested URI
87+
* @param client Client connection
88+
*/
89+
virtual void wsClientConnected(const char* uri, std::shared_ptr<IClient> client) = 0;
90+
91+
/** @brief Called on critical error */
92+
virtual void wsServerError() = 0;
93+
};
94+
95+
/** @brief Interface for websocket client connection */
96+
class IClient
97+
{
98+
public:
99+
// Forward declarations
100+
class IListener;
101+
102+
/** @brief Destructor */
103+
virtual ~IClient() { }
104+
105+
/**
106+
* @brief Disconnect the client
107+
* @return true if the disconnection is successfull, false otherwise
108+
*/
109+
virtual bool disconnect() = 0;
110+
111+
/**
112+
* @brief Indicate if the client is connected
113+
* @return true if the client is connected, false otherwise
114+
*/
115+
virtual bool isConnected() = 0;
116+
117+
/**
118+
* @brief Send data through the websocket connection
119+
* @param buffer Buffer containing the data to send
120+
* @param size Size of the buffer in bytes
121+
* @return true is the data has been sent, false otherwise
122+
*/
123+
virtual bool send(const void* data, size_t size) = 0;
124+
125+
/**
126+
* @brief Register a listener to the websocket events
127+
* @param listener Listener object
128+
*/
129+
virtual void registerListener(IListener& listener) = 0;
130+
131+
/** @brief Interface for the websocket clients listeners */
132+
class IListener
133+
{
134+
public:
135+
/** @brief Destructor */
136+
virtual ~IListener() { }
137+
138+
/** @brief Called when connection is lost */
139+
virtual void wsClientDisconnected() = 0;
140+
141+
/** @brief Called when a critical error occured */
142+
virtual void wsClientError() = 0;
143+
144+
/**
145+
* @brief Call when data has been received
146+
* @param buffer Buffer containing received data
147+
* @param size Size of the buffer in bytes
148+
*/
149+
virtual void wsClientDataReceived(const void* data, size_t size) = 0;
150+
};
151+
};
152+
153+
/** @brief Connection credentials */
154+
struct Credentials
155+
{
156+
// Basic authentication
157+
158+
/** @bool Enable HTTP basic authentication */
159+
bool http_basic_authent;
160+
161+
// TLS connections (wss URLs only)
162+
163+
/** @brief Cipher list for TLSv1.2 connections, leave empty for default
164+
* (OpenSSL format, default = system dependent) */
165+
std::string tls12_cipher_list;
166+
/** @brief Cipher list for TLSv1.3 connections, leave empty for default
167+
* (OpenSSL format, default = system dependent) */
168+
std::string tls13_cipher_list;
169+
/** @brief ECDH curve, leave empty for default
170+
* (OpenSSL format, default = system dependent) */
171+
std::string ecdh_curve;
172+
/** @brief Server certificate */
173+
std::string server_certificate;
174+
/** @brief Server certificate's private key */
175+
std::string server_certificate_private_key;
176+
/** @brief Server certificate's private key passphrase */
177+
std::string server_certificate_private_key_passphrase;
178+
/** @brief Certification Authority signing chain for the server certificate */
179+
std::string server_certificate_ca;
180+
/** @brief Certification Authority signing chain for the clients certificates */
181+
std::string client_certificate_ca;
182+
/** @bool Enable client authentication using certificate */
183+
bool client_certificate_authent;
184+
};
185+
};
186+
187+
} // namespace websockets
188+
} // namespace ocpp
189+
190+
#endif // IWEBSOCKETSERVER_H

src/websockets/WebsocketFactory.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ along with OpenOCPP. If not, see <http://www.gnu.org/licenses/>.
1818

1919
#include "WebsocketFactory.h"
2020
#include "LibWebsocketClient.h"
21+
#include "LibWebsocketServer.h"
2122

2223
namespace ocpp
2324
{
@@ -30,5 +31,11 @@ IWebsocketClient* WebsocketFactory::newClient()
3031
return new LibWebsocketClient();
3132
}
3233

34+
/** @brief Instanciate a server websocket */
35+
IWebsocketServer* WebsocketFactory::newServer()
36+
{
37+
return new LibWebsocketServer();
38+
}
39+
3340
} // namespace websockets
3441
} // namespace ocpp

src/websockets/WebsocketFactory.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ along with OpenOCPP. If not, see <http://www.gnu.org/licenses/>.
2020
#define WEBSOCKETFACTORY_H
2121

2222
#include "IWebsocketClient.h"
23+
#include "IWebsocketServer.h"
2324

2425
namespace ocpp
2526
{
@@ -32,6 +33,8 @@ class WebsocketFactory
3233
public:
3334
/** @brief Instanciate a client websocket */
3435
static IWebsocketClient* newClient();
36+
/** @brief Instanciate a server websocket */
37+
static IWebsocketServer* newServer();
3538
};
3639

3740
} // namespace websockets

src/websockets/libwebsockets/LibWebsocketClient.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ bool LibWebsocketClient::connect(const std::string& url,
7878
{
7979
// Define callback
8080
static const struct lws_protocols protocols[] = {
81-
{"LibWebsocketClient", &LibWebsocketClient::eventCallback, 0, 0, 0, nullptr, 0}, {NULL, NULL, 0, 0, 0, nullptr, 0}};
81+
{"LibWebsocketClient", &LibWebsocketClient::eventCallback, 0, 0, 0, nullptr, 0}, {nullptr, nullptr, 0, 0, 0, nullptr, 0}};
8282

8383
// Fill context information
8484
struct lws_context_creation_info info;
@@ -136,7 +136,11 @@ bool LibWebsocketClient::disconnect()
136136
{
137137
// Stop thread
138138
m_end = true;
139-
m_send_msgs.clear();
139+
SendMsg* msg;
140+
while (m_send_msgs.pop(msg, 0))
141+
{
142+
delete msg;
143+
}
140144
lws_cancel_service(m_context);
141145
if (std::this_thread::get_id() != m_thread->get_id())
142146
{
@@ -174,7 +178,7 @@ bool LibWebsocketClient::send(const void* data, size_t size)
174178
ret = m_send_msgs.push(msg);
175179

176180
// Schedule a send
177-
lws_cancel_service(m_context);
181+
lws_callback_on_writable(m_wsi);
178182
}
179183

180184
return ret;
@@ -211,7 +215,7 @@ void LibWebsocketClient::process()
211215
/** @brief libwebsockets connection callback */
212216
void LibWebsocketClient::connectCallback(struct lws_sorted_usec_list* sul)
213217
{
214-
// Confiure retry policy
218+
// Configure retry policy
215219
client->m_retry_policy = {
216220
.retry_ms_table = &client->m_retry_interval,
217221
.retry_ms_table_count = 1,
@@ -350,14 +354,6 @@ int LibWebsocketClient::eventCallback(struct lws* wsi, enum lws_callback_reasons
350354
}
351355
break;
352356

353-
case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
354-
// If connected and not ending schedule a send
355-
if (client->m_connected && !client->m_end)
356-
{
357-
lws_callback_on_writable(client->m_wsi);
358-
}
359-
break;
360-
361357
default:
362358
break;
363359
}

src/websockets/libwebsockets/LibWebsocketClient.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ along with OpenOCPP. If not, see <http://www.gnu.org/licenses/>.
2323
#include "Queue.h"
2424
#include "Url.h"
2525
#include "libwebsockets.h"
26+
2627
#include <condition_variable>
2728
#include <mutex>
2829
#include <thread>

0 commit comments

Comments
 (0)