mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Refactored HTTP handling to be easier to extend and use (nw)
This commit is contained in:
parent
f31904f2b7
commit
ad2bedf06b
@ -119,6 +119,8 @@ files {
|
||||
MAME_DIR .. "src/emu/emupal.h",
|
||||
MAME_DIR .. "src/emu/fileio.cpp",
|
||||
MAME_DIR .. "src/emu/fileio.h",
|
||||
MAME_DIR .. "src/emu/http.h",
|
||||
MAME_DIR .. "src/emu/http.cpp",
|
||||
MAME_DIR .. "src/emu/image.cpp",
|
||||
MAME_DIR .. "src/emu/image.h",
|
||||
MAME_DIR .. "src/emu/input.cpp",
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include "eminline.h"
|
||||
#include "profiler.h"
|
||||
|
||||
// http interface helpers
|
||||
#include "http.h"
|
||||
|
||||
// commonly-referenced utilities imported from lib/util
|
||||
#include "palette.h"
|
||||
#include "unicode.h"
|
||||
|
213
src/emu/http.cpp
Normal file
213
src/emu/http.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
/***************************************************************************
|
||||
|
||||
http.cpp
|
||||
|
||||
HTTP server handling
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "server_ws.hpp"
|
||||
#include "server_http.hpp"
|
||||
#include <fstream>
|
||||
|
||||
const static struct mapping
|
||||
{
|
||||
const char* extension;
|
||||
const char* mime_type;
|
||||
} mappings[] =
|
||||
{
|
||||
{ "aac", "audio/aac" },
|
||||
{ "aat", "application/font-sfnt" },
|
||||
{ "aif", "audio/x-aif" },
|
||||
{ "arj", "application/x-arj-compressed" },
|
||||
{ "asf", "video/x-ms-asf" },
|
||||
{ "avi", "video/x-msvideo" },
|
||||
{ "bmp", "image/bmp" },
|
||||
{ "cff", "application/font-sfnt" },
|
||||
{ "css", "text/css" },
|
||||
{ "csv", "text/csv" },
|
||||
{ "doc", "application/msword" },
|
||||
{ "eps", "application/postscript" },
|
||||
{ "exe", "application/octet-stream" },
|
||||
{ "gif", "image/gif" },
|
||||
{ "gz", "application/x-gunzip" },
|
||||
{ "htm", "text/html" },
|
||||
{ "html", "text/html" },
|
||||
{ "ico", "image/x-icon" },
|
||||
{ "ief", "image/ief" },
|
||||
{ "jpeg", "image/jpeg" },
|
||||
{ "jpg", "image/jpeg" },
|
||||
{ "jpm", "image/jpm" },
|
||||
{ "jpx", "image/jpx" },
|
||||
{ "js", "application/javascript" },
|
||||
{ "json", "application/json" },
|
||||
{ "m3u", "audio/x-mpegurl" },
|
||||
{ "m4v", "video/x-m4v" },
|
||||
{ "mid", "audio/x-midi" },
|
||||
{ "mov", "video/quicktime" },
|
||||
{ "mp3", "audio/mpeg" },
|
||||
{ "mp4", "video/mp4" },
|
||||
{ "mpeg", "video/mpeg" },
|
||||
{ "mpg", "video/mpeg" },
|
||||
{ "oga", "audio/ogg" },
|
||||
{ "ogg", "audio/ogg" },
|
||||
{ "ogv", "video/ogg" },
|
||||
{ "otf", "application/font-sfnt" },
|
||||
{ "pct", "image/x-pct" },
|
||||
{ "pdf", "application/pdf" },
|
||||
{ "pfr", "application/font-tdpfr" },
|
||||
{ "pict", "image/pict" },
|
||||
{ "png", "image/png" },
|
||||
{ "ppt", "application/x-mspowerpoint" },
|
||||
{ "ps", "application/postscript" },
|
||||
{ "qt", "video/quicktime" },
|
||||
{ "ra", "audio/x-pn-realaudio" },
|
||||
{ "ram", "audio/x-pn-realaudio" },
|
||||
{ "rar", "application/x-arj-compressed" },
|
||||
{ "rgb", "image/x-rgb" },
|
||||
{ "rtf", "application/rtf" },
|
||||
{ "sgm", "text/sgml" },
|
||||
{ "shtm", "text/html" },
|
||||
{ "shtml", "text/html" },
|
||||
{ "sil", "application/font-sfnt" },
|
||||
{ "svg", "image/svg+xml" },
|
||||
{ "swf", "application/x-shockwave-flash" },
|
||||
{ "tar", "application/x-tar" },
|
||||
{ "tgz", "application/x-tar-gz" },
|
||||
{ "tif", "image/tiff" },
|
||||
{ "tiff", "image/tiff" },
|
||||
{ "torrent", "application/x-bittorrent" },
|
||||
{ "ttf", "application/font-sfnt" },
|
||||
{ "txt", "text/plain" },
|
||||
{ "wav", "audio/x-wav" },
|
||||
{ "webm", "video/webm" },
|
||||
{ "woff", "application/font-woff" },
|
||||
{ "wrl", "model/vrml" },
|
||||
{ "xhtml", "application/xhtml+xml" },
|
||||
{ "xls", "application/x-msexcel" },
|
||||
{ "xml", "text/xml" },
|
||||
{ "xsl", "application/xml" },
|
||||
{ "xslt", "application/xml" },
|
||||
{ "zip", "application/x-zip-compressed" }
|
||||
};
|
||||
|
||||
static std::string extension_to_type(const std::string& extension)
|
||||
{
|
||||
for (mapping m : mappings)
|
||||
{
|
||||
if (m.extension == extension)
|
||||
{
|
||||
return m.mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
http_manager::http_manager(bool active, short port, const char *root)
|
||||
: m_io_context(std::make_shared<asio::io_context>())
|
||||
{
|
||||
if (!active) return;
|
||||
|
||||
m_server = std::make_unique<webpp::http_server>();
|
||||
m_server->m_config.port = port;
|
||||
m_server->set_io_context(m_io_context);
|
||||
m_wsserver = std::make_unique<webpp::ws_server>();
|
||||
|
||||
auto& endpoint = m_wsserver->endpoint["/"];
|
||||
|
||||
m_server->on_get([this, root](auto response, auto request) {
|
||||
std::string doc_root = root;
|
||||
|
||||
std::string path = request->path;
|
||||
// If path ends in slash (i.e. is a directory) then add "index.html".
|
||||
if (path[path.size() - 1] == '/')
|
||||
{
|
||||
path += "index.html";
|
||||
}
|
||||
|
||||
std::size_t last_qmark_pos = path.find_last_of("?");
|
||||
if (last_qmark_pos != std::string::npos)
|
||||
path = path.substr(0, last_qmark_pos - 1);
|
||||
|
||||
// Determine the file extension.
|
||||
std::size_t last_slash_pos = path.find_last_of("/");
|
||||
std::size_t last_dot_pos = path.find_last_of(".");
|
||||
std::string extension;
|
||||
if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos)
|
||||
{
|
||||
extension = path.substr(last_dot_pos + 1);
|
||||
}
|
||||
|
||||
// Open the file to send back.
|
||||
std::string full_path = doc_root + path;
|
||||
std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (!is)
|
||||
{
|
||||
response->status(400).send("Error");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fill out the reply to be sent to the client.
|
||||
std::string content;
|
||||
char buf[512];
|
||||
while (is.read(buf, sizeof(buf)).gcount() > 0)
|
||||
content.append(buf, size_t(is.gcount()));
|
||||
|
||||
response->type(extension_to_type(extension));
|
||||
response->status(200).send(content);
|
||||
}
|
||||
});
|
||||
|
||||
endpoint.on_open = [&](auto connection) {
|
||||
auto send_stream = std::make_shared<webpp::ws_server::SendStream>();
|
||||
*send_stream << "update_machine";
|
||||
m_wsserver->send(connection, send_stream);
|
||||
};
|
||||
|
||||
m_server->on_upgrade = [this](auto socket, auto request) {
|
||||
auto connection = std::make_shared<webpp::ws_server::Connection>(socket);
|
||||
connection->method = std::move(request->method);
|
||||
connection->path = std::move(request->path);
|
||||
connection->http_version = std::move(request->http_version);
|
||||
connection->header = std::move(request->header);
|
||||
connection->remote_endpoint_address = std::move(request->remote_endpoint_address);
|
||||
connection->remote_endpoint_port = request->remote_endpoint_port;
|
||||
m_wsserver->upgrade(connection);
|
||||
};
|
||||
|
||||
m_server->start();
|
||||
|
||||
m_server_thread = std::thread([this]() {
|
||||
m_io_context->run();
|
||||
});
|
||||
}
|
||||
|
||||
http_manager::~http_manager()
|
||||
{
|
||||
if (!m_server) return;
|
||||
|
||||
m_server->stop();
|
||||
if (m_server_thread.joinable())
|
||||
m_server_thread.join();
|
||||
}
|
||||
|
||||
|
||||
void http_manager::update()
|
||||
{
|
||||
if (!m_server) return;
|
||||
|
||||
m_server->clear();
|
||||
for (auto handler : m_handlers)
|
||||
{
|
||||
m_server->on_get(handler.first, [handler](auto response, auto request)
|
||||
{
|
||||
std::tuple<std::string,int, std::string> output = handler.second(request->path);
|
||||
response->type(std::get<2>(output));
|
||||
response->status(std::get<1>(output)).send(std::get<0>(output).c_str());
|
||||
});
|
||||
}
|
||||
}
|
57
src/emu/http.h
Normal file
57
src/emu/http.h
Normal file
@ -0,0 +1,57 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic
|
||||
/***************************************************************************
|
||||
|
||||
http.cpp
|
||||
|
||||
HTTP server handling
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EMU_H__
|
||||
#error Dont include this file directly; include emu.h instead.
|
||||
#endif
|
||||
|
||||
#ifndef MAME_EMU_HTTP_H
|
||||
#define MAME_EMU_HTTP_H
|
||||
|
||||
#include <thread>
|
||||
#include <time.h>
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> http_manager
|
||||
namespace asio
|
||||
{
|
||||
class io_context;
|
||||
}
|
||||
namespace webpp
|
||||
{
|
||||
class http_server;
|
||||
class ws_server;
|
||||
}
|
||||
|
||||
class http_manager
|
||||
{
|
||||
DISABLE_COPYING(http_manager);
|
||||
public:
|
||||
http_manager(bool active, short port, const char *root);
|
||||
virtual ~http_manager();
|
||||
|
||||
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();
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAME_EMU_HTTP_H */
|
@ -84,7 +84,6 @@
|
||||
#include "network.h"
|
||||
#include "ui/uimain.h"
|
||||
#include <time.h>
|
||||
#include "server_http.hpp"
|
||||
#include "rapidjson/include/rapidjson/writer.h"
|
||||
#include "rapidjson/include/rapidjson/stringbuffer.h"
|
||||
|
||||
@ -291,6 +290,8 @@ int running_machine::run(bool quiet)
|
||||
// use try/catch for deep error recovery
|
||||
try
|
||||
{
|
||||
m_manager.http()->clear();
|
||||
|
||||
// move to the init phase
|
||||
m_current_phase = MACHINE_PHASE_INIT;
|
||||
|
||||
@ -339,6 +340,8 @@ int running_machine::run(bool quiet)
|
||||
|
||||
export_http_api();
|
||||
|
||||
m_manager.http()->update();
|
||||
|
||||
// run the CPUs until a reset or exit
|
||||
m_hard_reset_pending = false;
|
||||
while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
|
||||
@ -363,6 +366,7 @@ int running_machine::run(bool quiet)
|
||||
|
||||
g_profiler.stop();
|
||||
}
|
||||
m_manager.http()->clear();
|
||||
|
||||
// and out via the exit phase
|
||||
m_current_phase = MACHINE_PHASE_EXIT;
|
||||
@ -1185,9 +1189,7 @@ running_machine::logerror_callback_item::logerror_callback_item(logerror_callbac
|
||||
|
||||
void running_machine::export_http_api()
|
||||
{
|
||||
if (!options().http()) return;
|
||||
|
||||
m_manager.http_server()->on_get("/api/machine", [this](auto response, auto request)
|
||||
m_manager.http()->add("/api/machine", [this](std::string)
|
||||
{
|
||||
rapidjson::StringBuffer s;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
|
||||
@ -1205,8 +1207,7 @@ void running_machine::export_http_api()
|
||||
writer.EndArray();
|
||||
writer.EndObject();
|
||||
|
||||
response->type("application/json");
|
||||
response->status(200).send(s.GetString());
|
||||
return std::make_tuple(std::string(s.GetString()), 200, "application/json");
|
||||
});
|
||||
}
|
||||
|
||||
|
188
src/emu/main.cpp
188
src/emu/main.cpp
@ -10,198 +10,16 @@ Controls execution of the core MAME system.
|
||||
|
||||
#include "emu.h"
|
||||
#include "emuopts.h"
|
||||
#include "main.h"
|
||||
#include "server_ws.hpp"
|
||||
#include "server_http.hpp"
|
||||
#include <fstream>
|
||||
|
||||
const static struct mapping
|
||||
{
|
||||
const char* extension;
|
||||
const char* mime_type;
|
||||
} mappings[] =
|
||||
{
|
||||
{ "aac", "audio/aac" },
|
||||
{ "aat", "application/font-sfnt" },
|
||||
{ "aif", "audio/x-aif" },
|
||||
{ "arj", "application/x-arj-compressed" },
|
||||
{ "asf", "video/x-ms-asf" },
|
||||
{ "avi", "video/x-msvideo" },
|
||||
{ "bmp", "image/bmp" },
|
||||
{ "cff", "application/font-sfnt" },
|
||||
{ "css", "text/css" },
|
||||
{ "csv", "text/csv" },
|
||||
{ "doc", "application/msword" },
|
||||
{ "eps", "application/postscript" },
|
||||
{ "exe", "application/octet-stream" },
|
||||
{ "gif", "image/gif" },
|
||||
{ "gz", "application/x-gunzip" },
|
||||
{ "htm", "text/html" },
|
||||
{ "html", "text/html" },
|
||||
{ "ico", "image/x-icon" },
|
||||
{ "ief", "image/ief" },
|
||||
{ "jpeg", "image/jpeg" },
|
||||
{ "jpg", "image/jpeg" },
|
||||
{ "jpm", "image/jpm" },
|
||||
{ "jpx", "image/jpx" },
|
||||
{ "js", "application/javascript" },
|
||||
{ "json", "application/json" },
|
||||
{ "m3u", "audio/x-mpegurl" },
|
||||
{ "m4v", "video/x-m4v" },
|
||||
{ "mid", "audio/x-midi" },
|
||||
{ "mov", "video/quicktime" },
|
||||
{ "mp3", "audio/mpeg" },
|
||||
{ "mp4", "video/mp4" },
|
||||
{ "mpeg", "video/mpeg" },
|
||||
{ "mpg", "video/mpeg" },
|
||||
{ "oga", "audio/ogg" },
|
||||
{ "ogg", "audio/ogg" },
|
||||
{ "ogv", "video/ogg" },
|
||||
{ "otf", "application/font-sfnt" },
|
||||
{ "pct", "image/x-pct" },
|
||||
{ "pdf", "application/pdf" },
|
||||
{ "pfr", "application/font-tdpfr" },
|
||||
{ "pict", "image/pict" },
|
||||
{ "png", "image/png" },
|
||||
{ "ppt", "application/x-mspowerpoint" },
|
||||
{ "ps", "application/postscript" },
|
||||
{ "qt", "video/quicktime" },
|
||||
{ "ra", "audio/x-pn-realaudio" },
|
||||
{ "ram", "audio/x-pn-realaudio" },
|
||||
{ "rar", "application/x-arj-compressed" },
|
||||
{ "rgb", "image/x-rgb" },
|
||||
{ "rtf", "application/rtf" },
|
||||
{ "sgm", "text/sgml" },
|
||||
{ "shtm", "text/html" },
|
||||
{ "shtml", "text/html" },
|
||||
{ "sil", "application/font-sfnt" },
|
||||
{ "svg", "image/svg+xml" },
|
||||
{ "swf", "application/x-shockwave-flash" },
|
||||
{ "tar", "application/x-tar" },
|
||||
{ "tgz", "application/x-tar-gz" },
|
||||
{ "tif", "image/tiff" },
|
||||
{ "tiff", "image/tiff" },
|
||||
{ "torrent", "application/x-bittorrent" },
|
||||
{ "ttf", "application/font-sfnt" },
|
||||
{ "txt", "text/plain" },
|
||||
{ "wav", "audio/x-wav" },
|
||||
{ "webm", "video/webm" },
|
||||
{ "woff", "application/font-woff" },
|
||||
{ "wrl", "model/vrml" },
|
||||
{ "xhtml", "application/xhtml+xml" },
|
||||
{ "xls", "application/x-msexcel" },
|
||||
{ "xml", "text/xml" },
|
||||
{ "xsl", "application/xml" },
|
||||
{ "xslt", "application/xml" },
|
||||
{ "zip", "application/x-zip-compressed" }
|
||||
};
|
||||
|
||||
static std::string extension_to_type(const std::string& extension)
|
||||
{
|
||||
for (mapping m : mappings)
|
||||
{
|
||||
if (m.extension == extension)
|
||||
{
|
||||
return m.mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
machine_manager::machine_manager(emu_options& options, osd_interface& osd)
|
||||
: m_osd(osd),
|
||||
m_options(options),
|
||||
m_machine(nullptr),
|
||||
m_io_context(std::make_shared<asio::io_context>())
|
||||
{
|
||||
}
|
||||
|
||||
machine_manager::~machine_manager()
|
||||
{
|
||||
if (options().http())
|
||||
m_server->stop();
|
||||
if (m_server_thread.joinable())
|
||||
m_server_thread.join();
|
||||
m_machine(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void machine_manager::start_http_server()
|
||||
{
|
||||
if (options().http())
|
||||
{
|
||||
m_server = std::make_unique<webpp::http_server>();
|
||||
m_server->m_config.port = options().http_port();
|
||||
m_server->set_io_context(m_io_context);
|
||||
m_wsserver = std::make_unique<webpp::ws_server>();
|
||||
|
||||
auto& endpoint = m_wsserver->endpoint["/"];
|
||||
|
||||
m_server->on_get([this](auto response, auto request) {
|
||||
std::string doc_root = this->options().http_root();
|
||||
|
||||
std::string path = request->path;
|
||||
// If path ends in slash (i.e. is a directory) then add "index.html".
|
||||
if (path[path.size() - 1] == '/')
|
||||
{
|
||||
path += "index.html";
|
||||
}
|
||||
|
||||
std::size_t last_qmark_pos = path.find_last_of("?");
|
||||
if (last_qmark_pos != std::string::npos)
|
||||
path = path.substr(0, last_qmark_pos - 1);
|
||||
|
||||
// Determine the file extension.
|
||||
std::size_t last_slash_pos = path.find_last_of("/");
|
||||
std::size_t last_dot_pos = path.find_last_of(".");
|
||||
std::string extension;
|
||||
if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos)
|
||||
{
|
||||
extension = path.substr(last_dot_pos + 1);
|
||||
}
|
||||
|
||||
// Open the file to send back.
|
||||
std::string full_path = doc_root + path;
|
||||
std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (!is)
|
||||
{
|
||||
response->status(400).send("Error");
|
||||
}
|
||||
|
||||
// Fill out the reply to be sent to the client.
|
||||
std::string content;
|
||||
char buf[512];
|
||||
while (is.read(buf, sizeof(buf)).gcount() > 0)
|
||||
content.append(buf, size_t(is.gcount()));
|
||||
|
||||
response->type(extension_to_type(extension));
|
||||
response->status(200).send(content);
|
||||
|
||||
});
|
||||
|
||||
endpoint.on_open = [&](auto connection) {
|
||||
auto send_stream = std::make_shared<webpp::ws_server::SendStream>();
|
||||
*send_stream << "update_machine";
|
||||
m_wsserver->send(connection, send_stream);
|
||||
};
|
||||
|
||||
m_server->on_upgrade = [this](auto socket, auto request) {
|
||||
auto connection = std::make_shared<webpp::ws_server::Connection>(socket);
|
||||
connection->method = std::move(request->method);
|
||||
connection->path = std::move(request->path);
|
||||
connection->http_version = std::move(request->http_version);
|
||||
connection->header = std::move(request->header);
|
||||
connection->remote_endpoint_address = std::move(request->remote_endpoint_address);
|
||||
connection->remote_endpoint_port = request->remote_endpoint_port;
|
||||
m_wsserver->upgrade(connection);
|
||||
};
|
||||
m_server->start();
|
||||
}
|
||||
}
|
||||
|
||||
void machine_manager::start_context()
|
||||
{
|
||||
m_server_thread = std::thread([this]() {
|
||||
m_io_context->run();
|
||||
});
|
||||
m_http = std::make_unique<http_manager>(options().http(), options().http_port(), options().http_root());
|
||||
}
|
||||
|
||||
|
@ -67,15 +67,6 @@ public:
|
||||
|
||||
// ======================> machine_manager
|
||||
class ui_manager;
|
||||
namespace asio
|
||||
{
|
||||
class io_context;
|
||||
}
|
||||
namespace webpp
|
||||
{
|
||||
class http_server;
|
||||
class ws_server;
|
||||
}
|
||||
|
||||
class machine_manager
|
||||
{
|
||||
@ -84,7 +75,7 @@ protected:
|
||||
// construction/destruction
|
||||
machine_manager(emu_options& options, osd_interface& osd);
|
||||
public:
|
||||
virtual ~machine_manager();
|
||||
virtual ~machine_manager() { }
|
||||
|
||||
osd_interface &osd() const { return m_osd; }
|
||||
emu_options &options() const { return m_options; }
|
||||
@ -99,18 +90,15 @@ public:
|
||||
virtual void ui_initialize(running_machine& machine) { }
|
||||
|
||||
virtual void update_machine() { }
|
||||
|
||||
|
||||
http_manager *http() { return m_http.get(); }
|
||||
void start_http_server();
|
||||
void start_context();
|
||||
webpp::http_server* http_server() const { return m_server.get(); }
|
||||
|
||||
protected:
|
||||
osd_interface & m_osd; // reference to OSD system
|
||||
emu_options & m_options; // reference to options
|
||||
running_machine * m_machine;
|
||||
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;
|
||||
osd_interface & m_osd; // reference to OSD system
|
||||
emu_options & m_options; // reference to options
|
||||
running_machine * m_machine;
|
||||
std::unique_ptr<http_manager> m_http;
|
||||
};
|
||||
|
||||
|
||||
|
@ -231,9 +231,7 @@ void cli_frontend::start_execution(mame_machine_manager *manager, std::vector<st
|
||||
manager->start_http_server();
|
||||
|
||||
manager->start_luaengine();
|
||||
|
||||
manager->start_context();
|
||||
|
||||
|
||||
if (!option_errors.empty())
|
||||
osd_printf_error("Error in command line:\n%s\n", strtrimspace(option_errors).c_str());
|
||||
|
||||
|
@ -197,6 +197,10 @@ namespace webpp {
|
||||
}
|
||||
}
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
m_resource.clear();
|
||||
}
|
||||
|
||||
std::function<void(std::shared_ptr<typename ServerBase<socket_type>::Request>, const std::error_code&)> on_error;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user