iu9-ca-web-chat/src/web_chat/iu9_ca_web_chat_lib/run.cpp

141 lines
6.4 KiB
C++
Raw Normal View History

#include "actions.h"
#include <engine_engine_number_9/baza_throw.h>
#include <engine_engine_number_9/running_mainloop.h>
#include <engine_engine_number_9/http_structures/response_gen.h>
#include <signal.h>
#include <engine_engine_number_9/connecting_assets/static_asset_manager.h>
#include <assert.h>
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
#include <new_york_transit_line/templater.h>
#include <sqlite3.h>
#include <engine_engine_number_9/socket_address.h>
#include "sqlite3_wrapper.h"
#include "str_fields.h"
#include "find_db.h"
namespace iu9cawebchat {
bool termination = false;
void sigterm_action(int) {
termination = true;
}
void run_website(const json::JSON& config) {
een9_ASSERT(config["assets"].g().isString(), "config[\"assets\"] is not string");
std::string assets_dir = config["assets"].g().asString();
een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory");
een9::StaticAssetManagerSlaveModule samI;
samI.update({
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
2024-08-23 13:54:52 +00:00
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/javascript"}} },
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {
{".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"}
} },
});
const json::JSON& config_presentation = config["presentation"].g();
int64_t slave_number = config["server"]["workers"].g().asInteger().get_int();
een9_ASSERT(slave_number > 0 && slave_number <= 200, "E");
std::string sqlite_db_path;
int ret = find_db_sqlite_file_path(config, sqlite_db_path);
een9_ASSERT(ret == 0, "Can't find database file");
struct WorkerGuestData {
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
std::unique_ptr<nytl::Templater> templater;
std::unique_ptr<SqliteConnection> db;
};
std::vector<WorkerGuestData> worker_guest_data(slave_number);
for (int i = 0; i < slave_number; i++) {
worker_guest_data[i].templater = std::make_unique<nytl::Templater>(
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
worker_guest_data[i].templater->update();
worker_guest_data[i].db = std::make_unique<SqliteConnection>(sqlite_db_path);
}
een9::MainloopParameters params;
params.guest_core = [&samI, &worker_guest_data, config_presentation]
(const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string {
een9_ASSERT_pl(0 <= worker_id && worker_id < worker_guest_data.size());
WorkerGuestData& wgd = worker_guest_data[worker_id];
nytl::Templater& templater = *wgd.templater;
een9::StaticAsset sa;
int ret;
auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string {
std::string page = templater.render(el_name,
pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{});
return een9::form_http_server_response_200("text/html", page);
};
if (req.uri_path == "/" || req.uri_path == "/list-rooms") {
2024-08-23 13:54:52 +00:00
return rteee("list-rooms", false);
}
if (req.uri_path == "/chat") {
return rteee("chat", false);
}
if (req.uri_path == "/profile") {
return rteee("profile", false);
}
if (req.uri_path == "/registration") {
return rteee("registration", false);
}
/* Trying to interpret request as asset lookup */
ret = samI.get_asset(req.uri_path, sa);
if (ret >= 0) {
return een9::form_http_server_response_200(sa.type, sa.content);
}
return een9::form_http_server_response_404("text/html", "<h1> Not found! </h1>");
};
params.guest_core_admin_control = [&worker_guest_data]
(const een9::SlaveTask& task, const std::string& req, een9::worker_id_t worker_id) -> std::string {
een9_ASSERT_pl(0 <= worker_id && worker_id < worker_guest_data.size());
WorkerGuestData& wgd = worker_guest_data[worker_id];
try {
if (req == "hello") {
return ":0 omg! hiii!! Hewwou :3 !!!!";
}
if (req == "8") {
termination = true;
return "Bye";
}
std::string updaterootpw_pref = "updaterootpw";
if (een9::beginsWith(req, "updaterootpw")) {
size_t nid = updaterootpw_pref.size();
if (nid >= req.size() || !isSPACE(req[nid]))
return "Bad command syntax. Missing whitespace";
std::string new_password = req.substr(nid + 1);
if (!check_password(new_password))
een9_THROW("Bad password");
sqlite_single_statement(wgd.db->hand,
"UPDATE `user` SET `password` = ?1 WHERE `id` = 0 ",
{}, {{1, new_password}});
return "Successul update";
}
return "Incorrect command";
} catch (std::exception& e) {
return std::string("Server error\n") + e.what();
}
};
params.slave_number = slave_number;
een9::SocketAddressParser sap;
auto translate_addr_list_conf = [&sap](std::vector<een9::SocketAddress>& dest, const std::vector<json::JSON>& source) {
size_t N = source.size();
dest.resize(N);
for (size_t i = 0; i < N; i++)
een9::parse_socket_address(source[i].asString(), dest[i], sap);
};
translate_addr_list_conf(params.client_regular_listened, config["server"]["http-listen"].g().asArray());
translate_addr_list_conf(params.admin_control_listened, config["server"]["admin-command-listen"].g().asArray());
signal(SIGINT, sigterm_action);
signal(SIGTERM, sigterm_action);
een9::electric_boogaloo(params, termination);
}
}