This commit is contained in:
parent
0511259075
commit
7554691cfd
@ -9,6 +9,7 @@
|
|||||||
#include "SystemUsage.h"
|
#include "SystemUsage.h"
|
||||||
#include "WeChatContext/CorporationContext.h"
|
#include "WeChatContext/CorporationContext.h"
|
||||||
#include <Wt/Dbo/Json.h>
|
#include <Wt/Dbo/Json.h>
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
#include <boost/json/object.hpp>
|
#include <boost/json/object.hpp>
|
||||||
#include <boost/json/serialize.hpp>
|
#include <boost/json/serialize.hpp>
|
||||||
#include <boost/process/v2/process.hpp>
|
#include <boost/process/v2/process.hpp>
|
||||||
@ -17,22 +18,23 @@
|
|||||||
constexpr auto IpcUrl = "ipc:///tmp/nng_ipc_server";
|
constexpr auto IpcUrl = "ipc:///tmp/nng_ipc_server";
|
||||||
|
|
||||||
static std::vector<std::string> urlFilter = {
|
static std::vector<std::string> urlFilter = {
|
||||||
"/",
|
"/", "/search", "/LoginPage", "/MessageBoard", "/我的笔记", "/我的笔记/", "/我的博客",
|
||||||
"/search",
|
|
||||||
"/LoginPage",
|
|
||||||
"/MessageBoard",
|
|
||||||
"/我的笔记",
|
|
||||||
"/我的笔记/",
|
|
||||||
"/我的博客",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Application::Application(const std::string &path)
|
class ApplicationPrivate {
|
||||||
: ApplicationSettings(path), m_router{std::make_shared<boost::urls::router<RequestHandler>>()} {
|
public:
|
||||||
|
std::shared_ptr<boost::urls::router<Application::RequestHandler>> router;
|
||||||
|
std::shared_ptr<boost::asio::ip::tcp::acceptor> acceptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
Application::Application(const std::string &path) : ApplicationSettings(path), m_d{new ApplicationPrivate()} {
|
||||||
|
using namespace boost::urls;
|
||||||
|
m_d->router = std::make_shared<router<RequestHandler>>();
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
m_router->insert("/{path*}",[this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/{path*}",[this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
boost::urls::url_view view(request.target());
|
url_view view(request.target());
|
||||||
auto target = view.path();
|
auto target = view.path();
|
||||||
LOG(info) << target;
|
LOG(info) << target;
|
||||||
if (target.find("..") != boost::beast::string_view::npos) {
|
if (target.find("..") != boost::beast::string_view::npos) {
|
||||||
@ -65,12 +67,12 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(res));
|
session.reply(std::move(res));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/wechat/{session*}",[this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/wechat/{session*}",[this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
ServiceLogic::onWechat(shared_from_this(), request,
|
ServiceLogic::onWechat(shared_from_this(), request,
|
||||||
[&session](auto &&response) { session.reply(std::move(response)); });
|
[&session](auto &&response) { session.reply(std::move(response)); });
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/tasklist", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/tasklist", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
auto database = Database::session();
|
auto database = Database::session();
|
||||||
Tasks tasks = database->find<Task>();
|
Tasks tasks = database->find<Task>();
|
||||||
@ -86,7 +88,7 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) mutable {
|
m_d->router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const matches &matches) mutable {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
LOG(info) << "add task: " << request.body();
|
LOG(info) << "add task: " << request.body();
|
||||||
@ -118,7 +120,7 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/task/delete/{id}", [this](HttpSession &session, const Request &request,const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/task/delete/{id}", [this](HttpSession &session, const Request &request,const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
LOG(info) << "delete task: " << matches.at("id");
|
LOG(info) << "delete task: " << matches.at("id");
|
||||||
auto database = Database::session();;
|
auto database = Database::session();;
|
||||||
@ -139,14 +141,14 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/notify", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/notify", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
auto corp = Amass::Singleton<CorporationContext>::instance();
|
auto corp = Amass::Singleton<CorporationContext>::instance();
|
||||||
corp->notify(request);
|
corp->notify(request);
|
||||||
session.reply(
|
session.reply(
|
||||||
ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html"));
|
ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html"));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
auto rootJson = boost::json::parse(request.body());
|
auto rootJson = boost::json::parse(request.body());
|
||||||
auto &root = rootJson.as_object();
|
auto &root = rootJson.as_object();
|
||||||
@ -188,7 +190,7 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
int size = 5;
|
int size = 5;
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
@ -226,7 +228,7 @@ Application::Application(const std::string &path)
|
|||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
int size = 5;
|
int size = 5;
|
||||||
@ -265,7 +267,7 @@ Application::Application(const std::string &path)
|
|||||||
s.prepare_payload();
|
s.prepare_payload();
|
||||||
session.reply(std::move(s));
|
session.reply(std::move(s));
|
||||||
});
|
});
|
||||||
m_router->insert("/api/v1/search/reindex", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
m_d->router->insert("/api/v1/search/reindex", [this](HttpSession &session, const Request &request, const matches &matches) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
std::string authorizationHeader;
|
std::string authorizationHeader;
|
||||||
if (request.count(http::field::authorization)) {
|
if (request.count(http::field::authorization)) {
|
||||||
@ -326,24 +328,59 @@ Application::Application(const std::string &path)
|
|||||||
alarmTask();
|
alarmTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Application::~Application() {
|
||||||
|
if (m_d != nullptr) {
|
||||||
|
delete m_d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boost::asio::io_context &Application::ioContext() {
|
boost::asio::io_context &Application::ioContext() {
|
||||||
return *m_ioContext->ioContext();
|
return *m_ioContext->ioContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Application::RequestHandler *Application::find(boost::urls::segments_encoded_view path,
|
void Application::insertUrl(std::string_view url, RequestHandler &&handler) {
|
||||||
boost::urls::matches_base &matches) const noexcept {
|
m_d->router->insert(url, std::move(handler));
|
||||||
const Application::RequestHandler *ret = nullptr;
|
|
||||||
try {
|
|
||||||
ret = m_router->find(path, matches);
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
boost::stacktrace::stacktrace trace = boost::stacktrace::stacktrace::from_current_exception();
|
|
||||||
LOG(error) << e.what() << ", trace:\n" << trace;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::insertUrl(std::string_view url, RequestHandler &&handler) {
|
void Application::startAcceptHttpConnections(const std::string &address, uint16_t port) {
|
||||||
m_router->insert(url, std::move(handler));
|
m_d->acceptor = std::make_shared<boost::asio::ip::tcp::acceptor>(*m_ioContext->ioContext());
|
||||||
|
boost::beast::error_code error;
|
||||||
|
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address(address), port);
|
||||||
|
m_d->acceptor->open(endpoint.protocol(), error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_d->acceptor->set_option(boost::asio::socket_base::reuse_address(true), error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_d->acceptor->bind(endpoint, error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_d->acceptor->listen(boost::asio::socket_base::max_listen_connections, error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
asyncAcceptHttpConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::asyncAcceptHttpConnections() {
|
||||||
|
auto socket = std::make_shared<boost::asio::ip::tcp::socket>(boost::asio::make_strand(*m_ioContext->ioContext()));
|
||||||
|
m_d->acceptor->async_accept(*socket, [self{shared_from_this()}, socket](const boost::system::error_code &error) {
|
||||||
|
if (error) {
|
||||||
|
if (error == boost::asio::error::operation_aborted) return;
|
||||||
|
LOG(error) << error.message();
|
||||||
|
} else {
|
||||||
|
auto session = std::make_shared<HttpSession>(std::move(*socket), self->m_d->router);
|
||||||
|
session->run();
|
||||||
|
}
|
||||||
|
self->asyncAcceptHttpConnections();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int Application::exec() {
|
int Application::exec() {
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include "ApplicationSettings.h"
|
#include "ApplicationSettings.h"
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
#include "router.hpp"
|
|
||||||
#include <boost/asio/system_timer.hpp>
|
#include <boost/asio/system_timer.hpp>
|
||||||
#include <boost/beast/http/string_body.hpp>
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "matches.hpp"
|
||||||
|
|
||||||
class HttpSession;
|
class HttpSession;
|
||||||
class SystemUsage;
|
class SystemUsage;
|
||||||
@ -18,6 +18,7 @@ class Socket;
|
|||||||
}
|
}
|
||||||
} // namespace Nng
|
} // namespace Nng
|
||||||
|
|
||||||
|
class ApplicationPrivate;
|
||||||
class Application : public ApplicationSettings<Application>, public std::enable_shared_from_this<Application> {
|
class Application : public ApplicationSettings<Application>, public std::enable_shared_from_this<Application> {
|
||||||
public:
|
public:
|
||||||
using Pointer = std::shared_ptr<Application>;
|
using Pointer = std::shared_ptr<Application>;
|
||||||
@ -36,21 +37,23 @@ public:
|
|||||||
|
|
||||||
INITIALIZE_FIELDS(Server, Port, Threads, ApplicationRoot, DocumentRoot);
|
INITIALIZE_FIELDS(Server, Port, Threads, ApplicationRoot, DocumentRoot);
|
||||||
Application(const std::string &path);
|
Application(const std::string &path);
|
||||||
|
~Application();
|
||||||
boost::asio::io_context &ioContext();
|
boost::asio::io_context &ioContext();
|
||||||
int exec();
|
int exec();
|
||||||
|
|
||||||
const RequestHandler *find(boost::urls::segments_encoded_view path, boost::urls::matches_base &matches) const noexcept;
|
void startAcceptHttpConnections(const std::string &address, uint16_t port);
|
||||||
void insertUrl(std::string_view url, RequestHandler &&handler);
|
void insertUrl(std::string_view url, RequestHandler &&handler);
|
||||||
static void requetExit();
|
static void requetExit();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void alarmTask();
|
void alarmTask();
|
||||||
void startAcceptRequest();
|
void startAcceptRequest();
|
||||||
|
void asyncAcceptHttpConnections();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ApplicationPrivate *m_d = nullptr;
|
||||||
int m_status = 0;
|
int m_status = 0;
|
||||||
std::shared_ptr<IoContext> m_ioContext;
|
std::shared_ptr<IoContext> m_ioContext;
|
||||||
std::shared_ptr<boost::urls::router<RequestHandler>> m_router;
|
|
||||||
std::shared_ptr<boost::asio::system_timer> m_timer;
|
std::shared_ptr<boost::asio::system_timer> m_timer;
|
||||||
std::shared_ptr<SystemUsage> m_systemUsage;
|
std::shared_ptr<SystemUsage> m_systemUsage;
|
||||||
std::shared_ptr<Nng::Asio::Socket> m_replyer;
|
std::shared_ptr<Nng::Asio::Socket> m_replyer;
|
||||||
|
@ -5,7 +5,6 @@ add_subdirectory(WebRTC)
|
|||||||
add_executable(Server main.cpp
|
add_executable(Server main.cpp
|
||||||
Application.h Application.cpp
|
Application.h Application.cpp
|
||||||
HttpSession.h HttpSession.cpp
|
HttpSession.h HttpSession.cpp
|
||||||
Listener.h Listener.cpp
|
|
||||||
ResponseUtility.h ResponseUtility.cpp
|
ResponseUtility.h ResponseUtility.cpp
|
||||||
ServiceLogic.h ServiceLogic.inl ServiceLogic.cpp
|
ServiceLogic.h ServiceLogic.inl ServiceLogic.cpp
|
||||||
ServiceManager.h
|
ServiceManager.h
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "HttpSession.h"
|
#include "HttpSession.h"
|
||||||
#include "Application.h"
|
#include "BoostLog.h"
|
||||||
|
#include <boost/beast/http/read.hpp>
|
||||||
|
#include <boost/beast/version.hpp>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/stacktrace.hpp>
|
#include <boost/stacktrace.hpp>
|
||||||
#include <boost/url/parse_path.hpp>
|
#include <boost/url/parse_path.hpp>
|
||||||
@ -7,7 +9,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
HttpSession::HttpSession(boost::asio::ip::tcp::socket &&socket) : m_stream(std::move(socket)) {
|
HttpSession::HttpSession(boost::asio::ip::tcp::socket &&socket, const std::shared_ptr<boost::urls::router<RequestHandler>> &router)
|
||||||
|
: m_stream(std::move(socket)), m_router(router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpSession::run() {
|
void HttpSession::run() {
|
||||||
@ -18,6 +21,10 @@ boost::beast::tcp_stream::executor_type HttpSession::executor() {
|
|||||||
return m_stream.get_executor();
|
return m_stream.get_executor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::asio::ip::tcp::socket HttpSession::releaseSocket() {
|
||||||
|
return m_stream.release_socket();
|
||||||
|
}
|
||||||
|
|
||||||
void HttpSession::errorReply(const Request &request, boost::beast::http::status status, boost::beast::string_view message) {
|
void HttpSession::errorReply(const Request &request, boost::beast::http::status status, boost::beast::string_view message) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
// invalid route
|
// invalid route
|
||||||
@ -43,23 +50,25 @@ void HttpSession::doRead() {
|
|||||||
|
|
||||||
// Set the timeout.
|
// Set the timeout.
|
||||||
m_stream.expires_after(std::chrono::seconds(30));
|
m_stream.expires_after(std::chrono::seconds(30));
|
||||||
boost::beast::http::async_read(
|
// clang-format off
|
||||||
m_stream, m_buffer, *m_parser,
|
boost::beast::http::async_read(m_stream, m_buffer, *m_parser, [self{shared_from_this()}](const boost::system::error_code &ec, std::size_t bytes_transferred) {
|
||||||
[self{shared_from_this()}](const boost::system::error_code &ec, std::size_t bytes_transferred) {
|
self->onRead(ec, bytes_transferred);
|
||||||
self->onRead(ec, bytes_transferred);
|
});
|
||||||
});
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpSession::onRead(boost::beast::error_code ec, std::size_t) {
|
void HttpSession::onRead(const boost::beast::error_code &error, std::size_t) {
|
||||||
using namespace boost::beast;
|
using namespace boost::beast;
|
||||||
// This means they closed the connection
|
if (error) {
|
||||||
if (ec == http::error::end_of_stream) {
|
if (error == http::error::end_of_stream) {
|
||||||
m_stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
|
boost::beast::error_code e;
|
||||||
|
m_stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, e);
|
||||||
|
} else if (error != boost::asio::error::operation_aborted) {
|
||||||
|
LOG(info) << error << " : " << error.message();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
} else if (m_router.expired()) {
|
||||||
if (ec) {
|
LOG(error) << "router is null.";
|
||||||
if (ec == boost::asio::error::operation_aborted) return;
|
|
||||||
LOG(info) << ec << " : " << ec.message();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,11 +79,9 @@ void HttpSession::onRead(boost::beast::error_code ec, std::size_t) {
|
|||||||
errorReply(request, http::status::bad_request, "Illegal request-target");
|
errorReply(request, http::status::bad_request, "Illegal request-target");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto router = m_router.lock();
|
||||||
auto application = Amass::Singleton<Application>::instance();
|
|
||||||
|
|
||||||
boost::urls::matches matches;
|
boost::urls::matches matches;
|
||||||
auto handler = application->find(*path, matches);
|
auto handler = router->find(*path, matches);
|
||||||
if (handler) {
|
if (handler) {
|
||||||
try {
|
try {
|
||||||
(*handler)(*this, request, matches);
|
(*handler)(*this, request, matches);
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
#ifndef HTTPSESSION_H
|
#ifndef HTTPSESSION_H
|
||||||
#define HTTPSESSION_H
|
#define HTTPSESSION_H
|
||||||
|
|
||||||
#include "boost/beast.hpp"
|
#include "router.hpp"
|
||||||
|
#include <boost/beast/core/flat_buffer.hpp>
|
||||||
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
|
#include <boost/beast/http/parser.hpp>
|
||||||
|
#include <boost/beast/http/string_body.hpp>
|
||||||
|
#include <boost/beast/http/write.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -10,14 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
class HttpSession : public std::enable_shared_from_this<HttpSession> {
|
class HttpSession : public std::enable_shared_from_this<HttpSession> {
|
||||||
void doRead();
|
void doRead();
|
||||||
void onRead(boost::beast::error_code ec, std::size_t);
|
|
||||||
void onWrite(boost::beast::error_code ec, std::size_t, bool close);
|
void onWrite(boost::beast::error_code ec, std::size_t, bool close);
|
||||||
|
|
||||||
// void sendResponse(boost::beast::http::response<boost::beast::http::string_body> &&response);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Request = boost::beast::http::request<boost::beast::http::string_body>;
|
using Request = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
HttpSession(boost::asio::ip::tcp::socket &&socket);
|
using RequestHandler = std::function<void(HttpSession &, const Request &, const boost::urls::matches &)>;
|
||||||
|
HttpSession(boost::asio::ip::tcp::socket &&socket, const std::shared_ptr<boost::urls::router<RequestHandler>> &router);
|
||||||
template <typename Response>
|
template <typename Response>
|
||||||
void reply(Response &&response) {
|
void reply(Response &&response) {
|
||||||
using ResponseType = typename std::decay_t<decltype(response)>;
|
using ResponseType = typename std::decay_t<decltype(response)>;
|
||||||
@ -28,10 +31,15 @@ public:
|
|||||||
}
|
}
|
||||||
void errorReply(const Request &request, boost::beast::http::status status, boost::beast::string_view message);
|
void errorReply(const Request &request, boost::beast::http::status status, boost::beast::string_view message);
|
||||||
boost::beast::tcp_stream::executor_type executor();
|
boost::beast::tcp_stream::executor_type executor();
|
||||||
|
boost::asio::ip::tcp::socket releaseSocket();
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onRead(const boost::beast::error_code &error, std::size_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::beast::tcp_stream m_stream;
|
boost::beast::tcp_stream m_stream;
|
||||||
|
std::weak_ptr<boost::urls::router<RequestHandler>> m_router;
|
||||||
boost::beast::flat_buffer m_buffer{std::numeric_limits<std::uint32_t>::max()};
|
boost::beast::flat_buffer m_buffer{std::numeric_limits<std::uint32_t>::max()};
|
||||||
std::optional<boost::beast::http::request_parser<boost::beast::http::string_body>> m_parser;
|
std::optional<boost::beast::http::request_parser<boost::beast::http::string_body>> m_parser;
|
||||||
};
|
};
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
#include "Listener.h"
|
|
||||||
#include "HttpSession.h"
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
Listener::Listener(boost::asio::io_context &ioc, boost::asio::ip::tcp::endpoint endpoint)
|
|
||||||
: m_ioContext(ioc), m_acceptor(ioc) {
|
|
||||||
boost::beast::error_code ec;
|
|
||||||
|
|
||||||
// Open the acceptor
|
|
||||||
m_acceptor.open(endpoint.protocol(), ec);
|
|
||||||
if (ec) {
|
|
||||||
fail(ec, "open");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow address reuse
|
|
||||||
m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
|
|
||||||
if (ec) {
|
|
||||||
fail(ec, "set_option");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to the server address
|
|
||||||
m_acceptor.bind(endpoint, ec);
|
|
||||||
if (ec) {
|
|
||||||
fail(ec, "bind");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start listening for connections
|
|
||||||
m_acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
|
|
||||||
if (ec) {
|
|
||||||
fail(ec, "listen");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Listener::startAccept() {
|
|
||||||
// The new connection gets its own strand
|
|
||||||
auto client = std::make_shared<boost::asio::ip::tcp::socket>(boost::asio::make_strand(m_ioContext));
|
|
||||||
m_acceptor.async_accept(
|
|
||||||
*client, [self{shared_from_this()}, client](const boost::system::error_code &ec) { self->onAccept(ec, client); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void Listener::fail(boost::beast::error_code ec, char const *what) {
|
|
||||||
// Don't report on canceled operations
|
|
||||||
if (ec == boost::asio::error::operation_aborted) return;
|
|
||||||
std::cerr << what << ": " << ec.message() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle a connection
|
|
||||||
void Listener::onAccept(boost::beast::error_code ec, std::shared_ptr<boost::asio::ip::tcp::socket> socket) {
|
|
||||||
if (ec) {
|
|
||||||
if (ec == boost::asio::error::operation_aborted) return;
|
|
||||||
std::cerr << "accept: " << ec.message() << "\n";
|
|
||||||
|
|
||||||
} else { // Launch a new session for this connection
|
|
||||||
auto session = std::make_shared<HttpSession>(std::move(*socket));
|
|
||||||
session->run();
|
|
||||||
}
|
|
||||||
startAccept();
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef LISTENER_H
|
|
||||||
#define LISTENER_H
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/beast.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class Listener : public std::enable_shared_from_this<Listener> {
|
|
||||||
public:
|
|
||||||
Listener(boost::asio::io_context &ioc, boost::asio::ip::tcp::endpoint endpoint);
|
|
||||||
|
|
||||||
// Start accepting incoming connections
|
|
||||||
void startAccept();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void fail(boost::beast::error_code ec, char const *what);
|
|
||||||
void onAccept(boost::beast::error_code ec, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::asio::io_context &m_ioContext;
|
|
||||||
boost::asio::ip::tcp::acceptor m_acceptor;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // LISTENER_H
|
|
@ -1,4 +1,18 @@
|
|||||||
#include "SignalServer.h"
|
#include "SignalServer.h"
|
||||||
|
#include "../Application.h"
|
||||||
|
#include <boost/beast/websocket/rfc6455.hpp>
|
||||||
|
|
||||||
|
SignalServer::SignalServer(Application &app) {
|
||||||
|
using namespace boost::urls;
|
||||||
|
// clang-format off
|
||||||
|
app.insertUrl("/api/v1/webrtc/signal/{id}", [this](HttpSession &session, const Application::Request &request, const matches &matches) {
|
||||||
|
auto id = matches.at("id");
|
||||||
|
if (boost::beast::websocket::is_upgrade(request)) {
|
||||||
|
auto ws = std::make_shared<WebSocketSignalSession>();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
void SignalServer::join(const std::string &id, WebSocketSignalSession *client) {
|
void SignalServer::join(const std::string &id, WebSocketSignalSession *client) {
|
||||||
m_clients.insert({id, client});
|
m_clients.insert({id, client});
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class WebSocketSignalSession;
|
class WebSocketSignalSession;
|
||||||
|
class Application;
|
||||||
|
|
||||||
class SignalServer {
|
class SignalServer {
|
||||||
public:
|
public:
|
||||||
|
SignalServer(Application &app);
|
||||||
void join(const std::string &id, WebSocketSignalSession *client);
|
void join(const std::string &id, WebSocketSignalSession *client);
|
||||||
void leave(const std::string &id);
|
void leave(const std::string &id);
|
||||||
WebSocketSignalSession *client(const std::string &id);
|
WebSocketSignalSession *client(const std::string &id);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "BoostLog.h"
|
#include "BoostLog.h"
|
||||||
#include "Database/Session.h"
|
#include "Database/Session.h"
|
||||||
#include "IoContext.h"
|
#include "IoContext.h"
|
||||||
#include "Listener.h"
|
|
||||||
#include "Live2dBackend.h"
|
#include "Live2dBackend.h"
|
||||||
#include "MediaServer.h"
|
#include "MediaServer.h"
|
||||||
#include "ProxyListener.h"
|
#include "ProxyListener.h"
|
||||||
@ -10,6 +9,7 @@
|
|||||||
#include "WeChatContext/CorporationContext.h"
|
#include "WeChatContext/CorporationContext.h"
|
||||||
#include "WeChatContext/WeChatContext.h"
|
#include "WeChatContext/WeChatContext.h"
|
||||||
#include "WebApplication/Application.h"
|
#include "WebApplication/Application.h"
|
||||||
|
#include <boost/asio/signal_set.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <boost/property_tree/ini_parser.hpp>
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
@ -64,11 +64,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(!application->getServer().empty(), "server.empty() == true");
|
BOOST_ASSERT_MSG(!application->getServer().empty(), "server.empty() == true");
|
||||||
Database::initialize(std::format("{}/database.sqlite", application->getApplicationRoot()));
|
Database::initialize(std::format("{}/database.sqlite", application->getApplicationRoot()));
|
||||||
auto address = boost::asio::ip::make_address(application->getServer());
|
application->startAcceptHttpConnections(application->getServer(), application->getPort());
|
||||||
auto listener =
|
|
||||||
std::make_shared<Listener>(application->ioContext(), boost::asio::ip::tcp::endpoint{address, application->getPort()});
|
|
||||||
listener->startAccept();
|
|
||||||
|
|
||||||
auto wechatContext = Singleton<WeChatContext>::instance<Construct>(application->ioContext());
|
auto wechatContext = Singleton<WeChatContext>::instance<Construct>(application->ioContext());
|
||||||
auto corpContext = Singleton<CorporationContext>::instance<Construct>(application->ioContext());
|
auto corpContext = Singleton<CorporationContext>::instance<Construct>(application->ioContext());
|
||||||
corpContext->start();
|
corpContext->start();
|
||||||
|
Loading…
Reference in New Issue
Block a user