Move to Qt

Everything seems to be working
Only timer is not moved over
This commit is contained in:
2024-09-12 16:59:54 +02:00
parent fc181726b9
commit 9eef1fc3ff
39 changed files with 399 additions and 501 deletions
+15 -4
View File
@@ -1,18 +1,29 @@
add_executable(server)
if (ANDROID)
message(FATAL_ERROR "This project cannot be built on Android.")
endif()
set(CMAKE_AUTOMOC ON)
find_package(Qt6 REQUIRED COMPONENTS WebSockets)
qt_add_executable(server)
include(FetchContent)
FetchContent_Declare(magic_enum URL https://github.com/Neargye/magic_enum/releases/download/v0.9.6/magic_enum-v0.9.6.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
FetchContent_MakeAvailable(magic_enum)
file(GLOB_RECURSE SIM_SOURCES "simulators/*.cpp")
file(GLOB_RECURSE SIM_SOURCES "simulators/*.[hc]pp")
target_sources(server PRIVATE
${CMAKE_CURRENT_LIST_DIR}/main.cpp
${CMAKE_CURRENT_LIST_DIR}/message_parser.cpp
${CMAKE_CURRENT_LIST_DIR}/simulator_base.cpp
${CMAKE_CURRENT_LIST_DIR}/simulator_base.hpp
${CMAKE_CURRENT_LIST_DIR}/simulators.cpp
${CMAKE_CURRENT_LIST_DIR}/simulators.hpp
${CMAKE_CURRENT_LIST_DIR}/websocket.cpp
${CMAKE_CURRENT_LIST_DIR}/websocket.hpp
${SIM_SOURCES}
)
@@ -25,12 +36,12 @@ target_include_directories(server
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/simulators
PRIVATE
${PROJECT_DIR}/external/websocketpp
)
target_link_libraries(server PRIVATE
Qt::WebSockets
UI
Timer
magic_enum::magic_enum
spdlog
)
)
+17 -71
View File
@@ -1,58 +1,15 @@
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QCommandLineParser>
#include <QtCore/QCommandLineOption>
#include "spdlog/async.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include "message_parser.hpp"
#include "simulators.hpp"
#include "websocket.hpp"
class Spdlog_buffer : public std::stringbuf
{
public:
Spdlog_buffer(std::function<void(std::string)> log_function) : log_function(log_function)
{
}
int sync()
{
std::string str = this->str();
str.pop_back();
log_function(str);
this->str("");
return 0;
}
private:
std::function<void(std::string)> log_function;
};
Simulators *g_simulators;
Websocket *g_web_socket;
Spdlog_buffer g_info_buffer([](std::string message) { spdlog::info(message); });
Spdlog_buffer g_error_buffer([](std::string message) { spdlog::error(message); });
std::ostream g_out(&g_info_buffer);
std::ostream g_err(&g_error_buffer);
void int_handler(int s)
{
UNUSED(s);
std::cout << std::endl;
g_out << "Caught Ctrl + C" << std::endl;
if (g_web_socket != nullptr)
g_web_socket->stop();
if (g_simulators != nullptr)
g_simulators->stop();
g_out << "Shutting down." << std::endl;
// delay to allow the server to stop gracefully
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
exit(1);
}
void init_logger()
{
spdlog::init_thread_pool(8192, 1);
@@ -67,38 +24,27 @@ void init_logger()
spdlog::set_level(spdlog::level::trace);
}
int main(void)
int main(int argc, char *argv[])
{
// Setup the signal handler
struct sigaction sigIntHandler;
QCoreApplication a(argc, argv);
sigIntHandler.sa_handler = int_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
QCommandLineParser parser;
parser.setApplicationDescription("QtWebSockets example: echoserver");
parser.addHelpOption();
sigaction(SIGINT, &sigIntHandler, NULL);
QCommandLineOption portOption(QStringList() << "p" << "port",
QCoreApplication::translate("main", "Port for echoserver [default: 9002]."),
QCoreApplication::translate("main", "port"), QLatin1String("9002"));
parser.addOption(portOption);
parser.process(a);
uint16_t port = parser.value(portOption).toUShort();
// Initialize the logger
init_logger();
// The server starts in this thread
spdlog::info("Starting server");
Simulators simulators;
g_simulators = &simulators;
Simulators simulators(port);
Websocket web_socket(
9002, &g_out, &g_err, [](std::string message) { return message_parser(message); },
[]() { return g_simulators->changed_UI_items().dump(); });
g_web_socket = &web_socket;
// Start the message processor and broadcast processor in separate threads
std::thread message_processor_thread(std::bind(&Websocket::process_messages, &web_socket));
std::thread broadcast_processor_thred(std::bind(&Websocket::process_broadcast, &web_socket));
// Run the asio loop with the main thread
web_socket.run();
// Wait for the threads to finish (should never happen)
message_processor_thread.join();
broadcast_processor_thred.join();
}
return a.exec();
}
+17 -19
View File
@@ -1,15 +1,13 @@
#include "message_parser.hpp"
#include "simulators.hpp"
#include <iostream>
#include <magic_enum.hpp>
extern Simulators *g_simulators;
std::string message_parser(std::string message)
QString Simulators::message_parser(QString message)
{
json j = json::parse(message);
json j = json::parse(message.toStdString());
if (j.contains("command"))
{
return command_parser(j["command"]).dump();
return QString::fromStdString(command_parser(j["command"]).dump());
}
else if (j.contains("event"))
{
@@ -22,7 +20,7 @@ std::string message_parser(std::string message)
}
}
json command_parser(json command)
json Simulators::command_parser(json command)
{
json j = "{}"_json;
try
@@ -35,27 +33,27 @@ json command_parser(json command)
spdlog::info("Command {}: {}", type, std::string(command.at("id")));
j["response"]["type"] = type;
j["response"]["UI_item"] =
g_simulators->invoke_active_simulator()->get_UI_item(command.at("id"))->to_json();
invoke_active_simulator()->get_UI_item(command.at("id"))->to_json();
break;
case Command::get_UI_elements:
spdlog::info("Command {}", type);
j["response"]["type"] = type;
j["response"]["UI_items"] = g_simulators->invoke_active_simulator()->get_UI_items()["UI_items"];
j["response"]["UI_items"] = invoke_active_simulator()->get_UI_items()["UI_items"];
break;
case Command::switch_simulator:
spdlog::info("Command {} to {}", type, std::string(command.at("name")));
g_simulators->switch_simulator(command.at("name"));
switch_simulator(command.at("name"));
j["response"]["type"] = type;
break;
case Command::get_active_simulator_name:
spdlog::info("Command {}", type);
j["response"]["type"] = type;
j["response"]["name"] = g_simulators->active_simulator_name();
j["response"]["name"] = active_simulator_name();
break;
case Command::get_simulators:
spdlog::info("Command {}", type);
j["response"]["type"] = type;
j["response"]["simulators"] = g_simulators->list_simulators();
j["response"]["simulators"] = list_simulators();
break;
default:
break;
@@ -69,13 +67,13 @@ json command_parser(json command)
return j;
}
void event_handler(json event)
void Simulators::event_handler(json event)
{
try
{
std::string type = event.at("type");
Event e = magic_enum::enum_cast<Event>(type).value_or(Event::end);
if (g_simulators->invoke_active_simulator() == nullptr)
if (invoke_active_simulator() == nullptr)
{
spdlog::error("Event got called but there is no active simulator");
return;
@@ -85,26 +83,26 @@ void event_handler(json event)
{
case Event::clicked: {
spdlog::debug("Event {}: {}", type, std::string(event.at("id")));
g_simulators->invoke_active_simulator()->get_UI_item(std::string(event.at("id")))->click();
invoke_active_simulator()->get_UI_item(std::string(event.at("id")))->click();
break;
}
case Event::value_changed: {
spdlog::debug("Event {}: {} {}", type, std::string(event.at("id")), (double)(event["value"]));
g_simulators->invoke_active_simulator()
invoke_active_simulator()
->get_UI_item(std::string(event.at("id")))
->set_value((double)event.at("value"));
break;
}
case Event::text_changed: {
spdlog::debug("Event {}: {} {}", type, std::string(event.at("id")), std::string(event.at("text")));
g_simulators->invoke_active_simulator()
invoke_active_simulator()
->get_UI_item(std::string(event.at("id")))
->set_text(std::string(event.at("text")));
break;
}
case Event::selected: {
spdlog::debug("Event {}: {} {}", type, std::string(event.at("id")), std::string(event.at("selected")));
g_simulators->invoke_active_simulator()
invoke_active_simulator()
->get_UI_item(std::string(event.at("id")))
->set_selected(std::string(event.at("selected")));
break;
@@ -118,4 +116,4 @@ void event_handler(json event)
{
spdlog::error(e.what());
}
}
}
-29
View File
@@ -1,29 +0,0 @@
#pragma once
#include "simulators.hpp"
enum class Command
{
get_UI_element,
get_UI_elements,
switch_simulator,
get_active_simulator_name,
get_simulators,
end,
begin = 0
};
enum class Event
{
clicked,
value_changed,
text_changed,
selected,
ui_changed,
end,
begin = 0
};
std::string message_parser(std::string message);
json command_parser(json command);
void event_handler(json event);
+4 -3
View File
@@ -1,7 +1,7 @@
#include "simulator_base.hpp"
Simulator_base::Simulator_base(std::string name, std::chrono::milliseconds interval)
: m_name(name), m_timer([this] { timer(); }), m_interval(interval)
Simulator_base::Simulator_base(std::string name, std::chrono::milliseconds interval, QObject* parrent)
: QObject(parrent), m_name(name), m_timer([this] { timer(); }), m_interval(interval)
{
}
@@ -32,6 +32,7 @@ void Simulator_base::add_UI_item(UI_item *item)
{
throw std::runtime_error("UI item id " + item->id() + " is not unique");
}
connect(item, &UI_item::value_changed, this, [this]{emit sim_changed();});
m_UI_items_map[item->id()] = item;
m_UI_items.push_back(item);
}
@@ -78,4 +79,4 @@ void Simulator_base::reboot()
{
// Reboot the simulator
system("reboot");
}
}
+6 -4
View File
@@ -4,9 +4,9 @@
#include "spdlog/spdlog.h"
#include "timer.hpp"
class Simulator_base
class Simulator_base : public QObject
{
Q_OBJECT
public:
/**
* @brief Construct a new Simulator_base object
@@ -14,7 +14,7 @@ class Simulator_base
* @param name The name of the simulator
* @param interval The interval of the timer (default is 100ms)
*/
Simulator_base(std::string name, std::chrono::milliseconds interval = std::chrono::milliseconds(100));
Simulator_base(std::string name, std::chrono::milliseconds interval = std::chrono::milliseconds(100), QObject* parrent = nullptr);
/**
* @brief Returns the name of the simulator
@@ -82,6 +82,8 @@ class Simulator_base
void shutdown();
void reboot();
signals:
void sim_changed();
protected:
std::string m_name;
@@ -89,4 +91,4 @@ class Simulator_base
std::map<std::string, UI_item *> m_UI_items_map;
Timer m_timer;
std::chrono::milliseconds m_interval;
};
};
+23 -2
View File
@@ -2,11 +2,26 @@
#include "can_debugger.hpp"
#include "test_sim.hpp"
#include <unordered_set>
#include <QDebug>
Simulators::Simulators()
Simulators::Simulators(uint16_t port, QObject* parrent) :
QObject(parrent),
m_server(new Websocket(port, this))
{
qDebug() << port;
INSERT_SIMULATOR(Test_Sim);
INSERT_SIMULATOR(Can_Debugger);
setup_connections();
}
void Simulators::setup_connections()
{
connect(m_server, &Websocket::on_message, this, [this](QWebSocket* conn, QString message){
QString response = message_parser(message);
if (response.isEmpty() || response == "{}")
return;
m_server->send(conn, response);
});
}
std::string Simulators::active_simulator_name() const
@@ -59,7 +74,13 @@ void Simulators::switch_simulator(std::string name)
return;
}
this->stop();
if (!this->m_current_simulator.empty())
{
disconnect(m_simulators.at(m_current_simulator).get());
}
this->m_current_simulator = name;
connect(m_simulators.at(m_current_simulator).get(), &Simulator_base::sim_changed, this, [this]{m_server->broadcast(QString::fromStdString(changed_UI_items().dump()));});
this->run();
}
@@ -139,4 +160,4 @@ json Simulators::changed_UI_items()
m_before = after;
return changed;
}
}
+34 -3
View File
@@ -3,14 +3,39 @@
#include <memory>
#include <mutex>
#include "websocket.hpp"
#include "simulator_base.hpp"
#define INSERT_SIMULATOR(type) m_simulators.insert(std::make_pair(type().name(), std::make_unique<type>()));
class Simulators
class Simulators : public QObject
{
Q_OBJECT
public:
Simulators();
enum class Command
{
get_UI_element,
get_UI_elements,
switch_simulator,
get_active_simulator_name,
get_simulators,
end,
begin = 0
};
enum class Event
{
clicked,
value_changed,
text_changed,
selected,
ui_changed,
end,
begin = 0
};
Simulators(uint16_t port, QObject *parent = nullptr);
void setup_connections();
std::string active_simulator_name() const;
void run();
void stop();
@@ -19,9 +44,15 @@ class Simulators
Simulator_base *invoke_active_simulator();
json changed_UI_items();
//parsing of websocket messages
QString message_parser(QString message);
json command_parser(json command);
void event_handler(json event);
private:
Websocket *m_server;
std::map<std::string, std::unique_ptr<Simulator_base>> m_simulators;
std::string m_current_simulator = "";
std::mutex m_mutex;
json m_before;
};
};
+1
View File
@@ -2,6 +2,7 @@
#include "simulator_base.hpp"
class Can_Debugger : public Simulator_base {
Q_OBJECT
public:
Can_Debugger();
void timer() override;
+10 -7
View File
@@ -1,13 +1,13 @@
#include "test_sim.hpp"
#include <iostream>
Test_Sim::Test_Sim() :
Simulator_base("Test_Sim", std::chrono::milliseconds(1000)),
m_button("button", "Off", Color(Color::White), Color(Color::Red), [this](std::string id) { button_clicked(id); }),
m_combobox("combobox", "Combobox", Color(Color::White), Color(Color::Black), {"Option 1", "Option 2", "Option 3"}, 0, [](std::string id, std::string selected) { spdlog::info("Combobox {} selected {}", id, selected); }),
Test_Sim::Test_Sim(QObject* parrent) :
Simulator_base("Test_Sim", std::chrono::milliseconds(1000), parrent),
m_button("button", "Off", Color(Color::White), Color(Color::Red)),
m_combobox("combobox", "Combobox", Color(Color::White), Color(Color::Black), {"Option 1", "Option 2", "Option 3"}, 0),
m_label("label", "Label", Color(Color::White), Color(Color::Black)),
m_checkbox("checkbox", "Checkbox", Color(Color::White), Color(Color::Black), {"Option 1", "Option 2", "Option 3"}, [](std::string id, std::vector<std::string> selected) { spdlog::info("Checkbox {} selected {}", id, (selected.size() > 0 ? selected[0] : "")); }),
m_slider("slider", "Slider", Color(Color::White), Color(Color::Black), 0, 100, 0, [this](std::string id, double value) { slider_changed(id, value); }),
m_checkbox("checkbox", "Checkbox", Color(Color::White), Color(Color::Black), {"Option 1", "Option 2", "Option 3"}),
m_slider("slider", "Slider", Color(Color::White), Color(Color::Black), 0, 100, 0),
m_dial("dial", "Dial", Color(Color::White), Color(Color::Black), 0, 100, 0),
m_thermo("thermo", "Thermo", Color(Color::White), Color(Color::Black), 0, 100, 0),
m_led("led", "Led", Color(Color::White), Color(Color::Black), Color(Color::Red))
@@ -27,6 +27,9 @@ m_led("led", "Led", Color(Color::White), Color(Color::Black), Color(Color::Red))
this->add_UI_item(&this->m_dial);
this->add_UI_item(&this->m_thermo);
this->add_UI_item(&this->m_led);
QObject::connect(&m_button, &UI_button::on_click, [this](std::string id) { button_clicked(id); });
QObject::connect(&m_slider, &UI_slider::on_change, [this](std::string id, double value) { slider_changed(id, value); });
}
void Test_Sim::timer()
@@ -69,4 +72,4 @@ void Test_Sim::slider_changed(std::string id, double value)
this->m_thermo.set_value(value);
return;
}
}
}
+2 -1
View File
@@ -2,8 +2,9 @@
#include "simulator_base.hpp"
class Test_Sim : public Simulator_base {
Q_OBJECT
public:
Test_Sim();
Test_Sim(QObject* parrent = nullptr);
void timer() override;
void run_at_startup() override;
private:
+54 -135
View File
@@ -1,150 +1,69 @@
#include "websocket.hpp"
#include "spdlog/spdlog.h"
#include "QtWebSockets/qwebsocketserver.h"
#include "QtWebSockets/qwebsocket.h"
#include <QtCore/QDebug>
Websocket::Websocket(uint16_t port, std::ostream *out, std::ostream *err,
std::function<std::string(std::string)> on_message, std::function<std::string()> on_update)
: m_on_message(on_message), m_on_update(on_update), m_port(port)
Websocket::Websocket(uint16_t port, QObject *parent) :
QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("sim_us Server"),
QWebSocketServer::NonSecureMode, this))
{
// Set logging settings
m_server.get_alog().set_custom(out != &std::cout);
m_server.get_elog().set_custom(err != &std::cerr);
m_server.get_alog().set_ostream(out);
m_server.get_elog().set_ostream(err);
m_server.set_access_channels(websocketpp::log::alevel::connect + websocketpp::log::alevel::disconnect);
m_server.clear_access_channels(websocketpp::log::alevel::frame_payload + websocketpp::log::alevel::frame_header +
websocketpp::log::alevel::control);
// Initialize Asio
m_server.init_asio();
// Register our message handler
m_server.set_open_handler(std::bind(&Websocket::on_open, this, ::_1));
m_server.set_close_handler(std::bind(&Websocket::on_close, this, ::_1));
m_server.set_message_handler(std::bind(&Websocket::on_message, this, ::_1, ::_2));
}
void Websocket::run()
{
try
{
// listen on specified port
m_server.listen(m_port);
// Start the server accept loop
m_server.start_accept();
// Start the ASIO io_service run loop
m_server.run();
}
catch (websocketpp::exception const &e)
{
spdlog::critical("{}", e.what());
exit(1);
}
catch (...)
{
spdlog::critical("other exception");
exit(1);
if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
qDebug() << "Echoserver listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &Websocket::onNewConnection);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &Websocket::closed);
}
}
void Websocket::stop()
Websocket::~Websocket()
{
m_server.stop_listening();
m_server.stop();
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
void Websocket::on_open(websocketpp::connection_hdl hdl)
void Websocket::broadcast(QString message)
{
{
std::lock_guard<std::mutex> guard(m_action_lock);
m_actions.push(action(SUBSCRIBE, hdl));
}
m_action_cond.notify_one();
}
void Websocket::on_close(websocketpp::connection_hdl hdl)
{
{
std::lock_guard<std::mutex> guard(m_action_lock);
m_actions.push(action(UNSUBSCRIBE, hdl));
}
m_action_cond.notify_one();
}
void Websocket::on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg)
{
// return pong
if (msg->get_opcode() == websocketpp::frame::opcode::PING)
{
m_server.send(hdl, msg->get_payload(), websocketpp::frame::opcode::PONG);
return;
}
// queue message up for sending by processing thread
{
std::lock_guard<std::mutex> guard(m_action_lock);
m_actions.push(action(MESSAGE, hdl, msg));
}
m_action_cond.notify_one();
}
void Websocket::process_messages()
{
while (1)
{
std::unique_lock<std::mutex> lock(m_action_lock);
while (m_actions.empty())
{
m_action_cond.wait(lock);
}
action a = m_actions.front();
m_actions.pop();
lock.unlock();
switch (a.type)
{
case SUBSCRIBE: {
std::lock_guard<std::mutex> guard(m_connection_lock);
m_connections.insert(a.hdl);
}
break;
case UNSUBSCRIBE: {
std::lock_guard<std::mutex> guard(m_connection_lock);
m_connections.erase(a.hdl);
}
break;
case MESSAGE: {
std::string response = m_on_message(a.msg->get_payload());
if (response.empty() || response == "{}")
{
continue;
}
m_server.send(a.hdl, response, websocketpp::frame::opcode::TEXT);
}
break;
default:
break;
}
foreach (QWebSocket* conn, m_clients) {
conn->sendTextMessage(message);
}
}
void Websocket::process_broadcast()
void Websocket::send(QWebSocket* conn, QString message)
{
while (1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::string update = m_on_update();
if (update.empty() || update == "{}")
{
continue;
}
{
std::lock_guard<std::mutex> guard(m_connection_lock);
for (auto it : m_connections)
{
m_server.send(it, update, websocketpp::frame::opcode::TEXT);
}
}
conn->sendTextMessage(message);
}
void Websocket::onNewConnection()
{
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &Websocket::processTextMessage);
connect(pSocket, &QWebSocket::binaryMessageReceived, this, &Websocket::processBinaryMessage);
connect(pSocket, &QWebSocket::disconnected, this, &Websocket::socketDisconnected);
m_clients << pSocket;
}
void Websocket::processTextMessage(QString message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
qDebug() << "Message received:" << message;
emit on_message(pClient, message);
}
void Websocket::processBinaryMessage(QByteArray message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
qDebug() << "Binary Message received:" << message;
}
void Websocket::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
qDebug() << "socketDisconnected:" << pClient;
if (pClient) {
m_clients.removeAll(pClient);
pClient->deleteLater();
}
}
}
+24 -60
View File
@@ -1,69 +1,33 @@
#pragma once
#include <functional>
#include <set>
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QByteArray>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
typedef websocketpp::server<websocketpp::config::asio> Server;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
/* on_open insert connection_hdl into channel
* on_close remove connection_hdl from channel
* on_message queue send to all channels
*/
enum action_type
class Websocket : public QObject
{
SUBSCRIBE,
UNSUBSCRIBE,
MESSAGE,
BROADCAST
};
Q_OBJECT
struct action
{
action(action_type t, websocketpp::connection_hdl h) : type(t), hdl(h)
{
}
action(action_type t, websocketpp::connection_hdl h, Server::message_ptr m) : type(t), hdl(h), msg(m)
{
}
action_type type;
websocketpp::connection_hdl hdl;
Server::message_ptr msg;
};
class Websocket
{
public:
Websocket(uint16_t port, std::ostream *out, std::ostream *err, std::function<std::string(std::string)> on_message,
std::function<std::string()> on_update);
void run();
void stop();
void process_messages();
void process_broadcast();
Websocket(uint16_t port, QObject *parent = nullptr);
~Websocket();
void broadcast(QString message);
void send(QWebSocket* conn, QString message);
signals:
void on_message(QWebSocket* conn, QString message);
void closed();
private slots:
void onNewConnection();
void processTextMessage(QString message);
void processBinaryMessage(QByteArray message);
void socketDisconnected();
private:
void on_open(websocketpp::connection_hdl hdl);
void on_close(websocketpp::connection_hdl hdl);
void on_message(websocketpp::connection_hdl hdl, Server::message_ptr msg);
private:
std::function<std::string(std::string)> m_on_message;
std::function<std::string()> m_on_update;
Server m_server;
uint16_t m_port;
typedef std::set<websocketpp::connection_hdl, std::owner_less<websocketpp::connection_hdl>> con_list;
con_list m_connections;
std::queue<action> m_actions;
std::mutex m_action_lock;
std::mutex m_connection_lock;
std::condition_variable m_action_cond;
};
QWebSocketServer *m_pWebSocketServer;
QList<QWebSocket *> m_clients;
};