summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/http.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/http.h')
-rw-r--r--src/emu/http.h146
1 files changed, 142 insertions, 4 deletions
diff --git a/src/emu/http.h b/src/emu/http.h
index 9f9f2e739b6..8da265c8893 100644
--- a/src/emu/http.h
+++ b/src/emu/http.h
@@ -39,18 +39,156 @@ class http_manager
{
DISABLE_COPYING(http_manager);
public:
+
+ /** An HTTP Request. */
+ struct http_request : public std::enable_shared_from_this<http_request>
+ {
+ /** Retrieves the requested resource. */
+ virtual const std::string get_resource() = 0; // The entire resource: path, query and fragment.
+
+ /** Returns the path part of the requested resource. */
+ virtual const std::string get_path() = 0;
+
+ /** Returns the query part of the requested resource. */
+ virtual const std::string get_query() = 0;
+
+ /** Returns the fragment part of the requested resource. */
+ virtual const std::string get_fragment() = 0;
+
+ /** Retrieves a header from the HTTP request. */
+ virtual const std::string get_header(const std::string &header_name) = 0;
+
+ /** Retrieves a header from the HTTP request. */
+ virtual const std::list<std::string> get_headers(const std::string &header_name) = 0;
+
+ /** Returns the body that was submitted with the HTTP request. */
+ virtual const std::string get_body() = 0;
+ };
+ typedef std::shared_ptr<http_request> http_request_ptr;
+
+ /** An HTTP response. */
+ struct http_response : public std::enable_shared_from_this<http_response>
+ {
+ /** Sets the HTTP status to be returned to the client. */
+ virtual void set_status(int status) = 0;
+
+ /** Sets the HTTP content type to be returned to the client. */
+ virtual void set_content_type(const std::string &type) = 0;
+
+ /** Sets the body to be sent to the client. */
+ virtual void set_body(const std::string &body) = 0;
+
+ /** Appends something to the body to be sent to the client. */
+ virtual void append_body(const std::string &body) = 0;
+ };
+ typedef std::shared_ptr<http_response> http_response_ptr;
+
+ /** Identifies a Websocket connection. */
+ struct websocket_connection : public std::enable_shared_from_this<websocket_connection>
+ {
+ /** Sends a message to the client that is connected on the other end of this Websocket connection. */
+ virtual void send_message(const std::string &payload, int opcode) = 0;
+
+ /** Closes this open Websocket connection. */
+ virtual void close() = 0;
+
+ virtual ~websocket_connection() { }
+ };
+ typedef std::shared_ptr<websocket_connection> websocket_connection_ptr;
+
+ /** Handles opening an incoming Websocket connection. */
+ typedef std::function<void(websocket_connection_ptr connection)> websocket_open_handler;
+
+ /** Handles an incoming message on an open Websocket connection. */
+ typedef std::function<void(websocket_connection_ptr connection, const std::string &payload, int opcode)> websocket_message_handler;
+
+ /** Handles when the client has closed a websocket connection. */
+ typedef std::function<void(websocket_connection_ptr connection, int status, const std::string& reason)> websocket_close_handler;
+
+ /** Handles when there has been an error on a websocket connection. */
+ typedef std::function<void(websocket_connection_ptr connection, const std::error_code& error_code)> websocket_error_handler;
+
+ /** Handles an incoming HTTP request, generating an HTTP response. */
+ typedef std::function<void(http_request_ptr, http_response_ptr)> http_handler;
+
+ struct websocket_endpoint : public std::enable_shared_from_this<websocket_endpoint> {
+ websocket_open_handler on_open;
+ websocket_message_handler on_message;
+ websocket_close_handler on_close;
+ websocket_error_handler on_error;
+ };
+ typedef std::shared_ptr<websocket_endpoint> websocket_endpoint_ptr;
+
+ /** Substitutes one string with another, and returns whether the substitution should be performed.
+ * Used when evaluating a template. */
+ typedef std::function<bool(std::string &)> substitution;
+
http_manager(bool active, short port, const char *root);
virtual ~http_manager();
+ void clear();
+
+ /** Adds a template to the web server. When the path is requested, the template will be read and parsed:
+ * strings between each pair of <init, term> characters will be passed to the substitute function and the result
+ * will be used instead.
+ */
+ void add_template(const std::string &path, substitution substitute, char init, char term);
+
+ /** Removes a template from the web server. */
+ void remove_template(const std::string &path);
+
+ /** Serves a template at an explicit path, which may be diffrent from the request path, under the document root.
+ * The template will be read and parsed:
+ * strings between each pair of <init, term> characters will be passed to the substitute function and the result
+ * will be used instead.
+ */
+ void serve_template(http_request_ptr request, http_response_ptr response, const std::string &path, substitution substitute, char init, char term);
- void clear() { m_handlers.clear(); update(); }
- void add(const char *url, std::function<std::tuple<std::string,int,std::string>(std::string)> func) { m_handlers.emplace(url, func); }
- void update();
+ void serve_document(http_request_ptr request, http_response_ptr response, const std::string &path);
+
+ /** Adds an HTTP handler. When the specified path is requested, the specified HTTP handler will be called. */
+ void add_http_handler(const std::string &path, http_handler handler);
+
+ /** Removes the HTTP handler at the specified path. */
+ void remove_http_handler(const std::string &path);
+
+ /** Retrieves a websocket endpoint, possibly adding it if it does not already exist. */
+ websocket_endpoint_ptr add_endpoint(const std::string &path, websocket_open_handler on_open, websocket_message_handler on_message, websocket_close_handler on_close, websocket_error_handler on_error);
+
+ /** Removes the websocket endpoint at the specified path. */
+ void remove_endpoint(const std::string &path);
+
+ bool is_active() {
+ return m_active;
+ }
+
private:
+ void on_open(http_manager::websocket_endpoint_ptr endpoint, void *onnection);
+
+ void on_message(http_manager::websocket_endpoint_ptr endpoint, void *connection, const std::string& payload, int opcode);
+
+ void on_close(http_manager::websocket_endpoint_ptr endpoint, void *connection, int status, const std::string& reason);
+
+ void on_error(http_manager::websocket_endpoint_ptr endpoint, void *connection, const std::error_code& error_code);
+
+ bool read_file(std::ostream &os, const std::string &path);
+
+ bool m_active;
+
std::shared_ptr<asio::io_context> m_io_context;
std::unique_ptr<webpp::http_server> m_server;
std::unique_ptr<webpp::ws_server> m_wsserver;
std::thread m_server_thread;
- std::unordered_map<const char *, std::function<std::tuple<std::string, int, std::string>(std::string)>> m_handlers;
+ std::string m_root;
+
+ std::unordered_map<std::string, http_handler> m_handlers;
+ std::mutex m_handlers_mutex;
+
+ std::unordered_map<std::string, websocket_endpoint_ptr> m_endpoints;
+ std::mutex m_endpoints_mutex;
+
+ std::unordered_map<void *, websocket_connection_ptr> m_connections; // the keys are really webpp::ws_server::Connection pointers
+ std::mutex m_connections_mutex;
+
};