diff options
Diffstat (limited to 'src/emu/http.h')
-rw-r--r-- | src/emu/http.h | 146 |
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; + }; |