Cadabra
Computer algebra system for field theory problems
websocket_server.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <boost/beast/core.hpp>
4 #include <boost/beast/websocket.hpp>
5 #include <boost/beast/http.hpp>
6 #include <boost/asio/ip/tcp.hpp>
7 #include <functional>
8 #include <memory>
9 #include <string>
10 #include <queue>
11 #include <optional>
12 #include <unordered_map>
13 #include <iostream>
14 #include <pthread.h>
15 
17  public:
18  using id_type = std::size_t;
19  using request_type = boost::beast::http::request<boost::beast::http::string_body>;
20  using response_type = boost::beast::http::response<boost::beast::http::string_body>;
21 
22  using message_handler = std::function<void(id_type, const std::string&, const request_type&, const std::string& ip_address)>;
23  using connect_handler = std::function<void(id_type)>;
24  using disconnect_handler = std::function<void(id_type)>;
25  using http_handler = std::function<void(request_type&, response_type&)>;
26 
27  websocket_server() = default;
28  explicit websocket_server(uint16_t port);
30 
33 
34  // Change the port on which to listen.
35  void listen(uint16_t port);
36 
41 
42  // You should call `run` on a separate thread to start the
43  // listening process. All callbacks on the message handlers will
44  // come on this thread. It is safe to call `send` below from a
45  // different thread.
46  void run();
47  void stop();
48 
49  // Send a message. This is safe on a thread which is not the
50  // thread which called `run`.
51  void send(id_type id, const std::string& message);
52  void close(id_type id);
53 
54  uint16_t get_local_port() const;
55 
56  private:
57  // The connection class handles all actual communication. There
58  // is one instance for each connection. Connections are
59  // identified by the single `id_type` stored as `id`.
60 
61  class connection : public std::enable_shared_from_this<connection> {
62  public:
63  connection(boost::asio::io_context& ioc, websocket_server& server, id_type id);
64 
65  void start();
66  void send(const std::string& message);
67  void close();
68 
70 
71  private:
72  void on_read_request(boost::beast::error_code ec, std::size_t);
73  void on_websocket_accept(boost::beast::error_code ec);
74  void do_read_websocket();
75  void on_read_websocket(boost::beast::error_code ec, std::size_t);
76  void do_write();
77  void on_write(boost::beast::error_code ec, std::size_t);
78  void on_close(boost::beast::error_code ec);
79  void handle_http_request();
80 
81  boost::asio::ip::tcp::socket socket_;
82  std::optional<boost::beast::websocket::stream<boost::asio::ip::tcp::socket&>> ws_stream_;
83  boost::beast::flat_buffer buffer_;
86 
89  public:
91  // std::cerr << "Thread " << pthread_self() << " queued_message constructor " << (void*)this << std::endl;
92  }
94  // std::cerr << "Thread " << pthread_self() << " queued_message destructor " << (void*)this << std::endl;
95  }
96 
97  std::string data;
98  std::shared_ptr<boost::beast::flat_buffer> buffer;
99  int seq;
100  };
101  bool is_websocket_{false};
102 
103  std::mutex queue_mutex_; // lock this for access to the variables below
104  std::queue<queued_message> message_queue_;
105  bool writing_{false};
106  };
107 
108  void do_accept();
109  void remove_connection(id_type id);
110 
111  boost::asio::io_context ioc_;
112  std::optional<boost::asio::ip::tcp::acceptor> acceptor_;
113  std::unordered_map<id_type, std::shared_ptr<connection>> connections_;
115 
120 };
121 
Definition: websocket_server.hh:88
~queued_message()
Definition: websocket_server.hh:93
queued_message()
Definition: websocket_server.hh:90
int seq
Definition: websocket_server.hh:99
std::string data
Definition: websocket_server.hh:97
std::shared_ptr< boost::beast::flat_buffer > buffer
Definition: websocket_server.hh:98
Definition: websocket_server.hh:61
void on_websocket_accept(boost::beast::error_code ec)
Definition: websocket_server.cc:81
void close()
Definition: websocket_server.cc:169
bool is_websocket_
Definition: websocket_server.hh:101
void on_close(boost::beast::error_code ec)
Definition: websocket_server.cc:200
boost::asio::ip::tcp::socket socket_
Definition: websocket_server.hh:81
std::queue< queued_message > message_queue_
Definition: websocket_server.hh:104
void do_write()
Definition: websocket_server.cc:147
connection(boost::asio::io_context &ioc, websocket_server &server, id_type id)
Definition: websocket_server.cc:4
std::optional< boost::beast::websocket::stream< boost::asio::ip::tcp::socket & > > ws_stream_
Definition: websocket_server.hh:82
id_type id_
Definition: websocket_server.hh:87
void on_read_websocket(boost::beast::error_code ec, std::size_t)
Definition: websocket_server.cc:105
bool writing_
Definition: websocket_server.hh:105
void do_read_websocket()
Definition: websocket_server.cc:95
void handle_http_request()
Definition: websocket_server.cc:47
void start()
Definition: websocket_server.cc:11
websocket_server & server_
Definition: websocket_server.hh:85
void send(const std::string &message)
Definition: websocket_server.cc:123
boost::beast::flat_buffer buffer_
Definition: websocket_server.hh:83
websocket_server::request_type http_request_
Definition: websocket_server.hh:84
void on_read_request(boost::beast::error_code ec, std::size_t)
Definition: websocket_server.cc:24
void on_write(boost::beast::error_code ec, std::size_t)
Definition: websocket_server.cc:184
std::mutex queue_mutex_
Definition: websocket_server.hh:103
friend websocket_server
Definition: websocket_server.hh:69
Definition: websocket_server.hh:16
boost::asio::io_context ioc_
Definition: websocket_server.hh:111
void close(id_type id)
Definition: websocket_server.cc:283
uint16_t get_local_port() const
Definition: websocket_server.cc:228
connect_handler connect_handler_
Definition: websocket_server.hh:117
id_type next_connection_id_
Definition: websocket_server.hh:114
void set_http_handler(http_handler h)
Definition: websocket_server.cc:248
boost::beast::http::request< boost::beast::http::string_body > request_type
Definition: websocket_server.hh:19
void stop()
Definition: websocket_server.cc:309
std::function< void(id_type, const std::string &, const request_type &, const std::string &ip_address)> message_handler
Definition: websocket_server.hh:22
void set_disconnect_handler(disconnect_handler h)
Definition: websocket_server.cc:243
void send(id_type id, const std::string &message)
Definition: websocket_server.cc:276
disconnect_handler disconnect_handler_
Definition: websocket_server.hh:118
std::unordered_map< id_type, std::shared_ptr< connection > > connections_
Definition: websocket_server.hh:113
std::function< void(id_type)> connect_handler
Definition: websocket_server.hh:23
std::size_t id_type
Definition: websocket_server.hh:18
boost::beast::http::response< boost::beast::http::string_body > response_type
Definition: websocket_server.hh:20
void set_message_handler(message_handler h)
Definition: websocket_server.cc:233
message_handler message_handler_
Definition: websocket_server.hh:116
http_handler http_handler_
Definition: websocket_server.hh:119
std::optional< boost::asio::ip::tcp::acceptor > acceptor_
Definition: websocket_server.hh:112
websocket_server()=default
websocket_server & operator=(const websocket_server &)=delete
void listen(uint16_t port)
Definition: websocket_server.cc:215
void remove_connection(id_type id)
Definition: websocket_server.cc:290
~websocket_server()
Definition: websocket_server.cc:210
std::function< void(request_type &, response_type &)> http_handler
Definition: websocket_server.hh:25
websocket_server(const websocket_server &)=delete
void do_accept()
Definition: websocket_server.cc:253
std::function< void(id_type)> disconnect_handler
Definition: websocket_server.hh:24
void run()
Definition: websocket_server.cc:298
void set_connect_handler(connect_handler h)
Definition: websocket_server.cc:238
server
Definition: cadabra2_defaults.py:156