Added server support for 'admin-control' protocol, added parsing of IP4/6/unix addresses, fixed some bugs, moved to C++17, config["server"] now actually does something
This commit is contained in:
parent
1aa95ad87e
commit
4d18d13a93
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,4 +13,4 @@ compile_commands.json
|
|||||||
local.sh
|
local.sh
|
||||||
|
|
||||||
iu9-ca-web-chat.db
|
iu9-ca-web-chat.db
|
||||||
log
|
log/
|
||||||
|
@ -1,54 +1,54 @@
|
|||||||
{% ELDEF main JSON pres %}
|
{% ELDEF main JSON pres %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% WRITE pres.phr.decl.list-of-chat-rooms %}</title>
|
<title>{% WRITE pres.phr.decl.list-of-chat-rooms %}</title>
|
||||||
<link rel="stylesheet" href="/assets/css/list-rooms.css">
|
<link rel="stylesheet" href="/assets/css/list-rooms.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 style="color: white;">{% WRITE pres.phr.decl.select-chat-room %}</h1>
|
<h1 style="color: white;">{% WRITE pres.phr.decl.select-chat-room %}</h1>
|
||||||
<ul class="room-list">
|
<ul class="room-list">
|
||||||
<!-- Здесь будет список комнат -->
|
<!-- Здесь будет список комнат -->
|
||||||
</ul>
|
</ul>
|
||||||
<button class="create-room-button" onclick="openCreateRoomModal()">{% WRITE pres.phr.act.create-room %}</button>
|
<button class="create-room-button" onclick="openCreateRoomModal()">{% WRITE pres.phr.act.create-room %}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="passwordModal" class="modal">
|
<div id="passwordModal" class="modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<span class="close" onclick="closeModal()">×</span>
|
<span class="close" onclick="closeModal()">×</span>
|
||||||
<h2>VVedite parol</h2> <!-- Nam ne nuzhen parol ot komnat -->
|
<h2>VVedite parol</h2> <!-- Nam ne nuzhen parol ot komnat -->
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<input type="password" id="roomPassword" placeholder="Пароль">
|
<input type="password" id="roomPassword" placeholder="Пароль">
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="join-button" onclick="validatePassword()">{% WRITE pres.phr.act.confirm %}</button>
|
<button class="join-button" onclick="validatePassword()">{% WRITE pres.phr.act.confirm %}</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Модальное окно для создания комнаты -->
|
<!-- Модальное окно для создания комнаты -->
|
||||||
<div id="createRoomModal" class="modal">
|
<div id="createRoomModal" class="modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<span class="close" onclick="closeCreateRoomModal()">×</span>
|
<span class="close" onclick="closeCreateRoomModal()">×</span>
|
||||||
<h2>{% WRITE pres.phr.decl.create-room %}</h2>
|
<h2>{% WRITE pres.phr.decl.create-room %}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<input type="text" id="newRoomName" placeholder="{% WRITE pres.phr.decl.name-of-room %}">
|
<input type="text" id="newRoomName" placeholder="{% WRITE pres.phr.decl.name-of-room %}">
|
||||||
<input type="password" id="newRoomPassword" placeholder="Пароль"> <!-- Fedya, nam ne nuzhen parol -->
|
<input type="password" id="newRoomPassword" placeholder="Пароль"> <!-- Fedya, nam ne nuzhen parol -->
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="join-button" onclick="createRoom()">{% WRITE pres.phr.act.create %}</button>
|
<button class="join-button" onclick="createRoom()">{% WRITE pres.phr.act.create %}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/assets/js/list-rooms.js"></script>
|
<script src="/assets/js/list-rooms.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{% ENDELDEF %}
|
{% ENDELDEF %}
|
||||||
|
@ -29,7 +29,7 @@ struct CAWebChat {
|
|||||||
|
|
||||||
std::vector<std::string> warning_flags = {"-Wall", "-Wno-unused-variable", "-Werror=return-type","-pedantic",
|
std::vector<std::string> warning_flags = {"-Wall", "-Wno-unused-variable", "-Werror=return-type","-pedantic",
|
||||||
"-Wno-unused-but-set-variable", "-Wno-reorder"};
|
"-Wno-unused-but-set-variable", "-Wno-reorder"};
|
||||||
std::vector<std::string> version_flags = {"--std", "c++14", "-D", "_POSIX_C_SOURCE=200809L"};
|
std::vector<std::string> version_flags = {"--std", "c++17", "-D", "_POSIX_C_SOURCE=200809L"};
|
||||||
std::vector<std::string> debug_defines_release = {"_GLIBCXX_DEBUG"};
|
std::vector<std::string> debug_defines_release = {"_GLIBCXX_DEBUG"};
|
||||||
std::vector<std::string> debug_defines_debug = {"_GLIBCXX_DEBUG", "DEBUG_ALLOW_LOUD"};
|
std::vector<std::string> debug_defines_debug = {"_GLIBCXX_DEBUG", "DEBUG_ALLOW_LOUD"};
|
||||||
std::vector<std::string> opt_flags_release = {"-g", "-O2"};
|
std::vector<std::string> opt_flags_release = {"-g", "-O2"};
|
||||||
@ -78,6 +78,7 @@ struct CAWebChat {
|
|||||||
"connecting_assets/static_asset_manager.cpp",
|
"connecting_assets/static_asset_manager.cpp",
|
||||||
"running_mainloop.cpp",
|
"running_mainloop.cpp",
|
||||||
"form_data_structure/urlencoded_query.cpp",
|
"form_data_structure/urlencoded_query.cpp",
|
||||||
|
"socket_address.cpp",
|
||||||
};
|
};
|
||||||
for (std::string& u: T.units)
|
for (std::string& u: T.units)
|
||||||
u = "http_server/engine_engine_number_9/" + u;
|
u = "http_server/engine_engine_number_9/" + u;
|
||||||
@ -93,6 +94,8 @@ struct CAWebChat {
|
|||||||
"http_structures/response_gen.h",
|
"http_structures/response_gen.h",
|
||||||
"running_mainloop.h",
|
"running_mainloop.h",
|
||||||
"form_data_structure/urlencoded_query.h",
|
"form_data_structure/urlencoded_query.h",
|
||||||
|
"socket_address.h",
|
||||||
|
"admin_control.h",
|
||||||
};
|
};
|
||||||
for (std::string& u: T.exported_headers)
|
for (std::string& u: T.exported_headers)
|
||||||
u = "engine_engine_number_9/" + u;
|
u = "engine_engine_number_9/" + u;
|
||||||
|
@ -31,6 +31,6 @@
|
|||||||
"server": {
|
"server": {
|
||||||
"workers": 8,
|
"workers": 8,
|
||||||
"http-listen": ["127.0.0.1:1025"],
|
"http-listen": ["127.0.0.1:1025"],
|
||||||
"command-listen": []
|
"admin-command-listen": ["127.0.0.1:1026"]
|
||||||
}
|
}
|
||||||
}
|
}
|
62
src/http_server/engine_engine_number_9/admin_control.cpp
Normal file
62
src/http_server/engine_engine_number_9/admin_control.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "admin_control.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace een9 {
|
||||||
|
static const char* admin_to_server_ms = "a6m1n 2 server request ~~~";
|
||||||
|
static const char* server_to_admin_ms = "server to 4dm1n r3sponse ~~~";
|
||||||
|
|
||||||
|
AdminControlProtMsgRecvCtx::AdminControlProtMsgRecvCtx(const char *ms): magic_string(ms) {
|
||||||
|
ms_size = strlen(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AdminControlProtMsgRecvCtx::feedCharacter(char ch) {
|
||||||
|
assert(status == 0);
|
||||||
|
if (magic_string_progress < ms_size) {
|
||||||
|
if (magic_string[magic_string_progress] != ch) {
|
||||||
|
status = -1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
magic_string_progress++;
|
||||||
|
} else if (body_size_progress < 8) {
|
||||||
|
uint64_t bt = (uint64_t)(uint8_t)ch;
|
||||||
|
b_sz = ((b_sz << 8) | bt);
|
||||||
|
body_size_progress++;
|
||||||
|
if (body_size_progress == 8 && b_sz > 100000000) {
|
||||||
|
status = -1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
body.reserve(b_sz);
|
||||||
|
} else if (body.size() < b_sz) {
|
||||||
|
body += ch;
|
||||||
|
} else {
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminControlRequestRCtx::AdminControlRequestRCtx(): AdminControlProtMsgRecvCtx(admin_to_server_ms) {
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminControlResponseRCtx::AdminControlResponseRCtx(): AdminControlProtMsgRecvCtx(server_to_admin_ms) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generate_ac_msg_gen_case(const std::string& content, const char* ms) {
|
||||||
|
std::string result;
|
||||||
|
uint64_t N = content.size();
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
result += (char)(uint8_t)((N & 0xff00000000000000) >> 56);
|
||||||
|
N <<= 8;
|
||||||
|
}
|
||||||
|
result += content;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generate_admin_control_request(const std::string &content) {
|
||||||
|
return generate_ac_msg_gen_case(content, admin_to_server_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generate_admin_control_response(const std::string &content) {
|
||||||
|
return generate_ac_msg_gen_case(content, server_to_admin_ms);
|
||||||
|
}
|
||||||
|
}
|
37
src/http_server/engine_engine_number_9/admin_control.h
Normal file
37
src/http_server/engine_engine_number_9/admin_control.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef ENGINE_ENGINE_NUMBER_9_ADMIN_CONTROL_H
|
||||||
|
#define ENGINE_ENGINE_NUMBER_9_ADMIN_CONTROL_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace een9 {
|
||||||
|
struct AdminControlProtMsgRecvCtx {
|
||||||
|
const char* magic_string;
|
||||||
|
size_t ms_size;
|
||||||
|
size_t magic_string_progress = 0;
|
||||||
|
size_t body_size_progress = 0;
|
||||||
|
uint64_t b_sz = 0;
|
||||||
|
std::string body;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
explicit AdminControlProtMsgRecvCtx(const char* ms);
|
||||||
|
|
||||||
|
int feedCharacter(char ch);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AdminControlRequestRCtx: public AdminControlProtMsgRecvCtx {
|
||||||
|
AdminControlRequestRCtx();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AdminControlResponseRCtx: public AdminControlProtMsgRecvCtx {
|
||||||
|
AdminControlResponseRCtx();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* From ADMIN to server (will begin with admin_to_server_ms)*/
|
||||||
|
std::string generate_admin_control_request(const std::string& content);
|
||||||
|
|
||||||
|
/* From SERVER to admin (will begin with server_to_admin_ms).*/
|
||||||
|
std::string generate_admin_control_response(const std::string& content);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -28,14 +28,30 @@ namespace een9 {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool endsIn(const std::string &a, const std::string &b) {
|
bool endsWith(const std::string &a, const std::string &b) {
|
||||||
if (b.size() > a.size())
|
if (b.size() > a.size())
|
||||||
return false;
|
return false;
|
||||||
return std::equal(a.end() - (ssize_t)b.size(), a.end(), b.begin());
|
return std::equal(a.end() - (ssize_t)b.size(), a.end(), b.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool beginsWith(const std::string &a, const std::string &b) {
|
||||||
|
if (b.size() > a.size())
|
||||||
|
return false;
|
||||||
|
return std::equal(a.begin(), a.begin() + (ssize_t)b.size(), b.begin());
|
||||||
|
}
|
||||||
|
|
||||||
std::string getSubstring(const std::string &str, size_t A, size_t B) {
|
std::string getSubstring(const std::string &str, size_t A, size_t B) {
|
||||||
ASSERT(A <= B && B <= str.size(), "Incorrect substring segment");
|
ASSERT(A <= B && B <= str.size(), "Incorrect substring segment");
|
||||||
return str.substr(A, B - A);
|
return str.substr(A, B - A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string make_uppercase(const std::string &source) {
|
||||||
|
std::string result(source);
|
||||||
|
for (size_t i = 0; i < source.size(); i++) {
|
||||||
|
char ch = source[i];
|
||||||
|
if ('a' <= ch && ch <= 'z')
|
||||||
|
result[i] = (char)(ch - 'a' + 'A');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,17 @@ namespace een9 {
|
|||||||
|
|
||||||
bool strIn(const std::string& str, const char* arr[]);
|
bool strIn(const std::string& str, const char* arr[]);
|
||||||
|
|
||||||
bool endsIn(const std::string& a, const std::string& b);
|
// b is postfix of a
|
||||||
|
bool endsWith(const std::string& a, const std::string& b);
|
||||||
|
|
||||||
|
// b is prefix of a
|
||||||
|
bool beginsWith(const std::string& a, const std::string& b);
|
||||||
|
|
||||||
/* In case of error, throws een9::ServerError */
|
/* In case of error, throws een9::ServerError */
|
||||||
std::string getSubstring(const std::string& str, size_t A, size_t B);
|
std::string getSubstring(const std::string& str, size_t A, size_t B);
|
||||||
|
|
||||||
|
std::string make_uppercase(const std::string &source);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using uptr = std::unique_ptr<T>;
|
using uptr = std::unique_ptr<T>;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace een9 {
|
|||||||
std::vector<std::string> c_files = detour_over_regular_folder(dir_rule.directory);
|
std::vector<std::string> c_files = detour_over_regular_folder(dir_rule.directory);
|
||||||
for (const std::string& file: c_files) {
|
for (const std::string& file: c_files) {
|
||||||
for (const StaticAssetManagerRulePostfixFilter& ext: dir_rule.postfix_rules_type_assign) {
|
for (const StaticAssetManagerRulePostfixFilter& ext: dir_rule.postfix_rules_type_assign) {
|
||||||
if (endsIn(file, ext.required_postfix)) {
|
if (endsWith(file, ext.required_postfix)) {
|
||||||
/* Found it! */
|
/* Found it! */
|
||||||
StaticAsset etot{ext.assigned_type, };
|
StaticAsset etot{ext.assigned_type, };
|
||||||
readFile(dir_rule.directory + "/" + file, etot.content);
|
readFile(dir_rule.directory + "/" + file, etot.content);
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
// Used for debug
|
// Used for debug
|
||||||
|
|
||||||
|
#ifdef DEBUG_ALLOW_LOUD
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "sys/dir.h"
|
#include "sys/dir.h"
|
||||||
#include "../os_utils.h"
|
#include "../os_utils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace een9 {
|
namespace een9 {
|
||||||
ClientRequestParser_CommonPrograms::ClientRequestParser_CommonPrograms() {
|
ClientRequestParser_CommonPrograms::ClientRequestParser_CommonPrograms() {
|
||||||
@ -106,8 +107,10 @@ namespace een9 {
|
|||||||
if (p.first == "Content-Length") {
|
if (p.first == "Content-Length") {
|
||||||
collecting_body = res.has_body = true;
|
collecting_body = res.has_body = true;
|
||||||
body_size = std::stoull(p.second);
|
body_size = std::stoull(p.second);
|
||||||
if (body_size > 100000000)
|
if (body_size > 100000000) {
|
||||||
THROW("Message content is too big");
|
status = -1;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
res.body.reserve(body_size);
|
res.body.reserve(body_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +124,6 @@ namespace een9 {
|
|||||||
writeFile("log/req", header);
|
writeFile("log/req", header);
|
||||||
#endif
|
#endif
|
||||||
status = -1;
|
status = -1;
|
||||||
THROW("bad request");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
@ -37,7 +37,6 @@ namespace een9 {
|
|||||||
explicit ClientRequestParser_WorkerBuffers(const ClientRequestParser_CommonPrograms& common_comp_program);
|
explicit ClientRequestParser_WorkerBuffers(const ClientRequestParser_CommonPrograms& common_comp_program);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Ou yeah, baby, it's time for more OOP */
|
|
||||||
struct ClientHttpRequestParser_Ctx {
|
struct ClientHttpRequestParser_Ctx {
|
||||||
ClientRequest& res;
|
ClientRequest& res;
|
||||||
regexis024::VirtualMachine& vm;
|
regexis024::VirtualMachine& vm;
|
||||||
|
@ -25,7 +25,6 @@ namespace een9 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniqueFdWrapper::~UniqueFdWrapper() {
|
UniqueFdWrapper::~UniqueFdWrapper() {
|
||||||
// printf("DEBUG!!! Closing fd = %d\n", fd);
|
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -55,7 +54,7 @@ namespace een9 {
|
|||||||
while ((ret = (int)read(fd, buf, 2048)) > 0) {
|
while ((ret = (int)read(fd, buf, 2048)) > 0) {
|
||||||
size_t oldN = result.size();
|
size_t oldN = result.size();
|
||||||
result.resize(oldN + ret);
|
result.resize(oldN + ret);
|
||||||
memcpy((void*)&result.c_str()[oldN], buf, ret);
|
memcpy(result.data() + oldN, buf, ret);
|
||||||
}
|
}
|
||||||
ASSERT_on_iret(ret, "Reading from " + description);
|
ASSERT_on_iret(ret, "Reading from " + description);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "http_structures/client_request_parse.h"
|
#include "http_structures/client_request_parse.h"
|
||||||
#include "http_structures/response_gen.h"
|
#include "http_structures/response_gen.h"
|
||||||
#include "baza_inter.h"
|
#include "baza_inter.h"
|
||||||
|
#include "admin_control.h"
|
||||||
|
|
||||||
namespace een9 {
|
namespace een9 {
|
||||||
struct QElementHttpConnections {
|
struct QElementHttpConnections {
|
||||||
@ -73,11 +74,13 @@ namespace een9 {
|
|||||||
WorkersTaskQueue queue;
|
WorkersTaskQueue queue;
|
||||||
bool& termination;
|
bool& termination;
|
||||||
guest_core_t guest_core;
|
guest_core_t guest_core;
|
||||||
|
guest_core_admin_control_t guest_core_admin_control;
|
||||||
|
|
||||||
/* Parser programs */
|
/* Parser programs */
|
||||||
ClientRequestParser_CommonPrograms parser_programs;
|
ClientRequestParser_CommonPrograms parser_programs;
|
||||||
|
|
||||||
WorkersEnvCommon(bool& term, guest_core_t g_c): termination(term), guest_core(std::move(g_c)){}
|
WorkersEnvCommon(bool& term, const MainloopParameters& params): termination(term),
|
||||||
|
guest_core(params.guest_core), guest_core_admin_control(params.guest_core_admin_control){}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorkersEnv {
|
struct WorkersEnv {
|
||||||
@ -89,25 +92,22 @@ namespace een9 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// todo: add timeout for multiple bytes, add more settings
|
// todo: add timeout for multiple bytes, add more settings
|
||||||
ClientRequest process_connection_input(int fd, const EEN9_ServerTips& s_tips, WorkersEnv& wte) {
|
ClientRequest process_http_connection_input(int fd, const EEN9_ServerTips& s_tips, WorkersEnv& wte) {
|
||||||
ClientRequest res;
|
ClientRequest res;
|
||||||
ClientHttpRequestParser_Ctx parser(res, wte.personal_parser_buffer, wte.wtec.parser_programs);
|
ClientHttpRequestParser_Ctx parser(res, wte.personal_parser_buffer, wte.wtec.parser_programs);
|
||||||
int ret;
|
int ret;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
ASSERT_pl(parser.status == 0);
|
assert(parser.status == 0);
|
||||||
while ((ret = (int)recv(fd, buf, 2048, 0)) > 0) {
|
while ((ret = (int)recv(fd, buf, 2048, 0)) > 0) {
|
||||||
for (size_t i = 0; i < ret; i++) {
|
for (size_t i = 0; i < ret; i++) {
|
||||||
/* Throws ServerError on bad input */
|
if (parser.feedCharacter(buf[i]) > 0)
|
||||||
if (parser.feedCharacter(buf[i]) > 0) {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (parser.status > 0)
|
if (parser.status > 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ASSERT_on_iret(ret, "recv");
|
ASSERT_on_iret(ret, "recv");
|
||||||
ASSERT_pl(parser.status == 1);
|
assert(parser.status == 1);
|
||||||
// printf("Log: worker received clients request\n%s\n", client_request.toString().c_str());
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,10 +123,35 @@ namespace een9 {
|
|||||||
printf("Log: worker: succesfully asnwered with response\n");
|
printf("Log: worker: succesfully asnwered with response\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string process_admin_control_connection_input(int fd, const EEN9_ServerTips& s_tips, WorkersEnv& wte) {
|
||||||
|
AdminControlRequestRCtx pctx;
|
||||||
|
int ret;
|
||||||
|
char buf[2048];
|
||||||
|
assert(pctx.status == 0);
|
||||||
|
while ((ret = (int)recv(fd, buf, 2048, 0)) > 0) {
|
||||||
|
for (size_t i = 0; i < ret; i++) {
|
||||||
|
if (pctx.feedCharacter(buf[i]) > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pctx.status > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT_on_iret(ret, "recv");
|
||||||
|
assert(pctx.status == 1);
|
||||||
|
return pctx.body;
|
||||||
|
}
|
||||||
|
|
||||||
void process_connection(const SlaveTask& task, WorkersEnv& wte) {
|
void process_connection(const SlaveTask& task, WorkersEnv& wte) {
|
||||||
ClientRequest client_request = process_connection_input(task.fd(), task.s_tips, wte);
|
if (task.conn_info.type == 0) {
|
||||||
std::string server_response = wte.wtec.guest_core(task, client_request, wte.id);
|
ClientRequest client_request = process_http_connection_input(task.fd(), task.s_tips, wte);
|
||||||
process_connection_output(task.fd(), server_response);
|
std::string server_response = wte.wtec.guest_core(task, client_request, wte.id);
|
||||||
|
process_connection_output(task.fd(), server_response);
|
||||||
|
} else if (task.conn_info.type == 1) {
|
||||||
|
std::string admin_request = process_admin_control_connection_input(task.fd(), task.s_tips, wte);
|
||||||
|
std::string server_response_content = wte.wtec.guest_core_admin_control(task, admin_request, wte.id);
|
||||||
|
std::string server_response = generate_admin_control_response(server_response_content);
|
||||||
|
process_connection_output(task.fd(), server_response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* worker_func(void* wte_ptr) {
|
void* worker_func(void* wte_ptr) {
|
||||||
@ -156,13 +181,13 @@ namespace een9 {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: retrieve address of connected client
|
|
||||||
|
|
||||||
void electric_boogaloo(const MainloopParameters& params, bool& termination_trigger) {
|
void electric_boogaloo(const MainloopParameters& params, bool& termination_trigger) {
|
||||||
WorkersEnvCommon wtec(termination_trigger, params.guest_core);
|
WorkersEnvCommon wtec(termination_trigger, params);
|
||||||
ASSERT(params.slave_number > 0, "No workers spawned");
|
ASSERT(params.slave_number > 0, "No workers spawned");
|
||||||
size_t Nip = params.ports_to_listen.size();
|
size_t CRL_Nip = params.client_regular_listened.size();
|
||||||
ASSERT(Nip > 0, "No open listeting addresses");
|
ASSERT(CRL_Nip > 0, "No open listeting addresses (http)");
|
||||||
|
size_t ACL_Nip = params.admin_control_listened.size();
|
||||||
|
size_t Nip = CRL_Nip + ACL_Nip;
|
||||||
|
|
||||||
std::vector<pthread_t> workers(params.slave_number);
|
std::vector<pthread_t> workers(params.slave_number);
|
||||||
std::vector<uptr<WorkersEnv>> wtes(params.slave_number);
|
std::vector<uptr<WorkersEnv>> wtes(params.slave_number);
|
||||||
@ -173,44 +198,49 @@ namespace een9 {
|
|||||||
pthread_create(&workers[i], NULL, worker_func, wtes[i].get());
|
pthread_create(&workers[i], NULL, worker_func, wtes[i].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: move this try block inside the loop
|
||||||
try {
|
try {
|
||||||
int ret;
|
int ret;
|
||||||
std::vector<UniqueFdWrapper> listening_socks(Nip);
|
struct Ear {
|
||||||
|
/* A copy from params */
|
||||||
|
SocketAddress my_addr;
|
||||||
|
UniqueFdWrapper listening_sock;
|
||||||
|
/* type 0 is for http protocol
|
||||||
|
* type 1 is for admin-cmd protocol */
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
std::vector<Ear> ears(Nip);
|
||||||
|
for (size_t i = 0; i < CRL_Nip; i++) {
|
||||||
|
ears[i].my_addr = params.client_regular_listened[i];
|
||||||
|
ears[i].type = 0;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ACL_Nip; i++) {
|
||||||
|
ears[i + CRL_Nip].my_addr = params.admin_control_listened[i];
|
||||||
|
ears[i + CRL_Nip].type = 1;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < Nip; i++) {
|
for (size_t i = 0; i < Nip; i++) {
|
||||||
printf("Creating listening socket\n");
|
|
||||||
uint16_t port = params.ports_to_listen[i];
|
|
||||||
int listening_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
int listening_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
ASSERT_on_iret(listening_socket_fd, "Listening socket creation");
|
ASSERT_on_iret(listening_socket_fd, "'Listening socket' creation");
|
||||||
UniqueFdWrapper listening_socket(listening_socket_fd);
|
UniqueFdWrapper listening_socket(listening_socket_fd);
|
||||||
printf("Listening socket created\n");
|
|
||||||
sockaddr_in listening_address;
|
|
||||||
listening_address.sin_family = AF_INET;
|
|
||||||
listening_address.sin_port = htons(port);
|
|
||||||
uint32_t lca = (127u << 24) | 1;
|
|
||||||
listening_address.sin_addr.s_addr = htonl(lca);
|
|
||||||
int reuseaddr_nozero_option_value = 1;
|
int reuseaddr_nozero_option_value = 1;
|
||||||
ret = setsockopt(listening_socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_nozero_option_value, sizeof(int));
|
ret = setsockopt(listening_socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_nozero_option_value, sizeof(int));
|
||||||
ASSERT_on_iret(ret, "setting SO_REUSEADDR befire binding to address");
|
ASSERT_on_iret(ret, "Can't set SO_REUSEADDR");
|
||||||
ret = bind(listening_socket(), (const sockaddr*)&listening_address, sizeof(listening_address));
|
bind_to_socket_address(listening_socket_fd, ears[i].my_addr);
|
||||||
ASSERT_on_iret(ret, "binding to INADDR_ANY:" + std::to_string(port));
|
|
||||||
printf("Binded socket to address\n");
|
|
||||||
ret = listen(listening_socket(), 128);
|
ret = listen(listening_socket(), 128);
|
||||||
ASSERT_on_iret(ret, "listening for connections");
|
ASSERT_on_iret(ret, "listen() listening for connections");
|
||||||
printf("Listening socket succesfully started listening\n");
|
ears[i].listening_sock = std::move(listening_socket);
|
||||||
listening_socks[i] = std::move(listening_socket);
|
|
||||||
}
|
}
|
||||||
std::vector<pollfd> pollfds(Nip);
|
std::vector<pollfd> pollfds(Nip);
|
||||||
for (size_t i = 0; i < Nip; i++) {
|
for (size_t i = 0; i < Nip; i++) {
|
||||||
pollfds[i].fd = listening_socks[i]();
|
pollfds[i].fd = ears[i].listening_sock();
|
||||||
pollfds[i].events = POLLRDNORM;
|
pollfds[i].events = POLLRDNORM;
|
||||||
}
|
}
|
||||||
printf("Entering mainloop\n");
|
|
||||||
ASSERT(params.mainloop_recheck_interval_us > 0, "Incorrect poll timeout");
|
ASSERT(params.mainloop_recheck_interval_us > 0, "Incorrect poll timeout");
|
||||||
while (true) {
|
while (true) {
|
||||||
MutexLockGuard lg1(wtec.corvee_bed, "poller termination check");
|
// MutexLockGuard lg1(wtec.corvee_bed, "poller termination check");
|
||||||
if (wtec.termination)
|
if (wtec.termination)
|
||||||
break;
|
break;
|
||||||
lg1.unlock();
|
// lg1.unlock();
|
||||||
for (size_t i = 0; i < Nip; i++) {
|
for (size_t i = 0; i < Nip; i++) {
|
||||||
pollfds[i].revents = 0;
|
pollfds[i].revents = 0;
|
||||||
}
|
}
|
||||||
@ -218,21 +248,24 @@ namespace een9 {
|
|||||||
ret = poll(pollfds.data(), Nip, params.mainloop_recheck_interval_us);
|
ret = poll(pollfds.data(), Nip, params.mainloop_recheck_interval_us);
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
break;
|
break;
|
||||||
ASSERT_on_iret(ret, "polling");
|
// todo: do not end program here (in the loop. Nothing in the loop should be able to end program)
|
||||||
|
ASSERT_on_iret(ret, "poll()");
|
||||||
for (size_t i = 0; i < Nip; i++) {
|
for (size_t i = 0; i < Nip; i++) {
|
||||||
if ((pollfds[i].revents & POLLRDNORM)) {
|
if ((pollfds[i].revents & POLLRDNORM)) {
|
||||||
try {
|
try {
|
||||||
sockaddr client_address;
|
int session_sock = accept(pollfds[i].fd, NULL, NULL);
|
||||||
socklen_t client_addr_len = sizeof(client_address);
|
|
||||||
int session_sock = accept(pollfds[i].fd, &client_address, &client_addr_len);
|
|
||||||
ASSERT_on_iret(session_sock, "Failed to accept incoming connection");
|
ASSERT_on_iret(session_sock, "Failed to accept incoming connection");
|
||||||
printf("Log: successful connection\n");
|
|
||||||
UniqueFdWrapper session_sock_fdw(session_sock);
|
UniqueFdWrapper session_sock_fdw(session_sock);
|
||||||
configure_socket_rcvsndtimeo(session_sock_fdw(), params.s_conf.request_timeout);
|
configure_socket_rcvsndtimeo(session_sock_fdw(), params.s_conf.request_timeout);
|
||||||
|
SocketAddress peer_addr;
|
||||||
|
get_peer_name_as_socket_address(session_sock, peer_addr);
|
||||||
{ MutexLockGuard lg2(wtec.corvee_bed, "poller adds connection");
|
{ MutexLockGuard lg2(wtec.corvee_bed, "poller adds connection");
|
||||||
SlaveTask task{ConnectionInfo{}, std::move(session_sock_fdw),
|
SlaveTask task{
|
||||||
|
ConnectionInfo{ears[i].my_addr, peer_addr, ears[i].type},
|
||||||
|
std::move(session_sock_fdw),
|
||||||
EEN9_ServerTips{wtec.queue.size(),
|
EEN9_ServerTips{wtec.queue.size(),
|
||||||
params.s_conf.critical_load_1, params.s_conf.request_timeout}};
|
params.s_conf.critical_load_1, params.s_conf.request_timeout}
|
||||||
|
};
|
||||||
if (wtec.queue.size() < params.s_conf.critical_load_2)
|
if (wtec.queue.size() < params.s_conf.critical_load_2)
|
||||||
wtec.queue.push_back(std::move(task));
|
wtec.queue.push_back(std::move(task));
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,14 @@
|
|||||||
#include "os_utils.h"
|
#include "os_utils.h"
|
||||||
#include "http_structures/client_request.h"
|
#include "http_structures/client_request.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "socket_address.h"
|
||||||
|
|
||||||
namespace een9 {
|
namespace een9 {
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
// todo: add server address field
|
SocketAddress server_name;
|
||||||
// todo: add client address field
|
SocketAddress client_name;
|
||||||
int type; // O_o why??
|
/* 0 - http, 1 - 'een9::admin-control' protocol */
|
||||||
|
int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure is passed to guest function. It contains server info that might be or might be not used
|
/* This structure is passed to guest function. It contains server info that might be or might be not used
|
||||||
@ -33,6 +35,8 @@ namespace een9 {
|
|||||||
|
|
||||||
/* guest_core function must not throw anything that is not derived from std::exception */
|
/* guest_core function must not throw anything that is not derived from std::exception */
|
||||||
typedef std::function<std::string(const SlaveTask&, const ClientRequest&, worker_id_t worker_id)> guest_core_t;
|
typedef std::function<std::string(const SlaveTask&, const ClientRequest&, worker_id_t worker_id)> guest_core_t;
|
||||||
|
/* same as gurst_core_t, but it used not for http, but for een9 specific "admin-cmd" protocol */
|
||||||
|
typedef std::function<std::string(const SlaveTask&, const std::string&, worker_id_t)> guest_core_admin_control_t;
|
||||||
|
|
||||||
struct ServersConfiguration {
|
struct ServersConfiguration {
|
||||||
size_t critical_load_1 = 90;
|
size_t critical_load_1 = 90;
|
||||||
@ -42,15 +46,19 @@ namespace een9 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct MainloopParameters {
|
struct MainloopParameters {
|
||||||
|
/* On which addresses should I listed for incoming HTTP connections */
|
||||||
|
std::vector<SocketAddress> client_regular_listened;
|
||||||
|
/* On which addresses should I listen for incoming administrative commands */
|
||||||
|
std::vector<SocketAddress> admin_control_listened;
|
||||||
bool do_logging = true;
|
bool do_logging = true;
|
||||||
bool open_admin_listener = true;
|
|
||||||
// todo: add support for unix socket address
|
|
||||||
uint16_t admin_listener_port = 12345;
|
|
||||||
guest_core_t guest_core;
|
|
||||||
size_t slave_number = 2;
|
size_t slave_number = 2;
|
||||||
std::vector<uint16_t> ports_to_listen;
|
|
||||||
int mainloop_recheck_interval_us = 100;
|
int mainloop_recheck_interval_us = 100;
|
||||||
|
|
||||||
|
/* Takes parsed http request object. Should return fully-prepared http response */
|
||||||
|
guest_core_t guest_core;
|
||||||
|
/* Takes admin input. Returns only desired output message (without protocol header) */
|
||||||
|
guest_core_admin_control_t guest_core_admin_control;
|
||||||
|
|
||||||
ServersConfiguration s_conf;
|
ServersConfiguration s_conf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
276
src/http_server/engine_engine_number_9/socket_address.cpp
Normal file
276
src/http_server/engine_engine_number_9/socket_address.cpp
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
#include "socket_address.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "baza.h"
|
||||||
|
#include "baza_inter.h"
|
||||||
|
#include <libregexis024tools/delayed_matching.h>
|
||||||
|
#include <libregexis024tools/stringmatching.h>
|
||||||
|
#include <libregexis024vm/libregexis024vm_interface.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace een9 {
|
||||||
|
struct regexp_cmp_out{
|
||||||
|
std::vector<uint8_t> prg;
|
||||||
|
regexis024::track_var_list vars;
|
||||||
|
};
|
||||||
|
regexp_cmp_out compile_regexp(const char* expr) {
|
||||||
|
regexp_cmp_out res;
|
||||||
|
std::string problem;
|
||||||
|
int ret = regexis024::compile(expr, res.vars, res.prg, problem);
|
||||||
|
ASSERT(ret == 0, "Can't compile regexp");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SocketAddressParser_Inner {
|
||||||
|
regexp_cmp_out prg;
|
||||||
|
regexis024::VirtualMachine vm;
|
||||||
|
regexis024::tai_t tdiff_k;
|
||||||
|
std::pair<regexis024::tai_t, regexis024::tai_t> i4_k;
|
||||||
|
std::pair<regexis024::tai_t, regexis024::tai_t> i6_k;
|
||||||
|
std::pair<regexis024::tai_t, regexis024::tai_t> ip_k;
|
||||||
|
regexis024::tai_t skip_k;
|
||||||
|
|
||||||
|
#define reg_int4 "#4(0|[1-9][0-9]!r{0;2})"
|
||||||
|
#define reg_int6 "#6(0|[1-9a-fA-F][0-9a-fA-F]!r{0;3})"
|
||||||
|
#define reg_6RHT_rep(mt) "(:|(:" reg_int6 ")!r{1;" #mt "})"
|
||||||
|
#define reg_6LFT_rep(ea) "(" reg_int6 ":)!r{" #ea "}"
|
||||||
|
#define reg_6zs "#s:0;"
|
||||||
|
#define reg_intp "#p(0|[1-9][0-9]!r{0;4})"
|
||||||
|
#define reg_addr_in4 "(#t:1;" reg_int4 "." reg_int4 "." reg_int4 "." reg_int4 ":" reg_intp ")"
|
||||||
|
#define reg_addr_in6_core "(" reg_6LFT_rep(7) reg_int6 "|" ":" reg_6zs reg_6RHT_rep(6) "|" \
|
||||||
|
reg_6LFT_rep(1) reg_6zs reg_6RHT_rep(5) "|" \
|
||||||
|
reg_6LFT_rep(2) reg_6zs reg_6RHT_rep(4) "|" \
|
||||||
|
reg_6LFT_rep(3) reg_6zs reg_6RHT_rep(3) "|" \
|
||||||
|
reg_6LFT_rep(4) reg_6zs reg_6RHT_rep(2) "|" \
|
||||||
|
reg_6LFT_rep(5) reg_6zs reg_6RHT_rep(1) "|" \
|
||||||
|
reg_6LFT_rep(6) reg_6zs ":" ")"
|
||||||
|
#define reg_addr_in6 "(#t:2;\\[" reg_addr_in6_core "\\]:" reg_intp ")"
|
||||||
|
SocketAddressParser_Inner(): prg(compile_regexp(
|
||||||
|
reg_addr_in4 "|" reg_addr_in6
|
||||||
|
)), vm(prg.prg.size(), prg.prg.data(), UINT64_MAX, UINT16_MAX, UINT32_MAX, UINT32_MAX, UINT64_MAX)
|
||||||
|
{
|
||||||
|
ASSERT_pl(vm.initialize() == 0);
|
||||||
|
tdiff_k = prg.vars.at("t").colarr_first;
|
||||||
|
skip_k = prg.vars.at("s").colarr_first;
|
||||||
|
auto obtain_range = [&](const std::string& name) -> std::pair<regexis024::tai_t, regexis024::tai_t> {
|
||||||
|
const regexis024::TrackingVariableInfo& vi = prg.vars.at(name);
|
||||||
|
assert(vi.colarr_first > 0 && vi.colarr_second > 0);
|
||||||
|
return {(regexis024::tai_t)vi.colarr_first, (regexis024::tai_t)vi.colarr_second};
|
||||||
|
};
|
||||||
|
i4_k = obtain_range("4");
|
||||||
|
i6_k = obtain_range("6");
|
||||||
|
ip_k = obtain_range("p");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketAddressParser::SocketAddressParser() {
|
||||||
|
opaque = new SocketAddressParser_Inner();
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketAddressParser::~SocketAddressParser() {
|
||||||
|
delete (SocketAddressParser_Inner*)opaque;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_socket_address(const std::string& addr, SocketAddress& res, SocketAddressParser& pdata) {
|
||||||
|
#define reveal (*(SocketAddressParser_Inner*)pdata.opaque)
|
||||||
|
reveal.vm.wipeToInit();
|
||||||
|
ASSERT_pl(reveal.vm.addNewMatchingThread() == 0);
|
||||||
|
int ret;
|
||||||
|
for (size_t i = 0; i < addr.size(); i++) {
|
||||||
|
ret = reveal.vm.feedCharacter((uint64_t)addr[i], 1);
|
||||||
|
// if (!reveal.vm.haveSurvivors()) {
|
||||||
|
// printf("DEBUG: died on %s\n", addr.substr(0, i + 1).c_str());
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
if (reveal.vm.isMatched()) {
|
||||||
|
std::vector<regexis024::CAEvent> ca = reveal.vm.getMatchedThreadCABranchReverse();
|
||||||
|
std::reverse(ca.begin(), ca.end());
|
||||||
|
size_t ci = 0;
|
||||||
|
#define curKey() ca[ci].key
|
||||||
|
#define curValue() ca[ci].value
|
||||||
|
auto extractRange = [&](std::pair<regexis024::tai_t, regexis024::tai_t> rk) -> std::string {
|
||||||
|
assert(ca[ci].key == rk.first && ca[ci + 1].key == rk.second);
|
||||||
|
size_t oci = ci;
|
||||||
|
ci += 2;
|
||||||
|
return getSubstring(addr, ca[oci].value, ca[oci + 1].value);
|
||||||
|
};
|
||||||
|
assert(curKey() == reveal.tdiff_k);
|
||||||
|
if (curValue() == 1) {
|
||||||
|
ci++;
|
||||||
|
uint32_t res_addr = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
std::string h = extractRange(reveal.i4_k);
|
||||||
|
uint32_t p = std::stoul(h);
|
||||||
|
if (p > 255)
|
||||||
|
return -1;
|
||||||
|
res_addr = ((res_addr << 8) | p);
|
||||||
|
}
|
||||||
|
uint32_t res_port = std::stoul(extractRange(reveal.ip_k));
|
||||||
|
if (res_port > 65535)
|
||||||
|
return -1;
|
||||||
|
res.v.gen.sa_family = AF_INET;
|
||||||
|
res.v.sin.sin_port = htons(res_port); // host to network short
|
||||||
|
res.v.sin.sin_addr.s_addr = htonl(res_addr); // host to network long
|
||||||
|
res.addrLen = sizeof(sockaddr_in);
|
||||||
|
} else if (curValue() == 2){
|
||||||
|
ci++;
|
||||||
|
int skipped = 8;
|
||||||
|
for (const regexis024::CAEvent& ev: ca) {
|
||||||
|
if (ev.key == reveal.i6_k.first)
|
||||||
|
skipped--;
|
||||||
|
}
|
||||||
|
assert(skipped == 0 || skipped >= 2);
|
||||||
|
uint16_t res_u6_addr16[8];
|
||||||
|
size_t bi = 0;
|
||||||
|
std::string h;
|
||||||
|
while (bi < 8) {
|
||||||
|
if (curKey() == reveal.i6_k.first) {
|
||||||
|
h = extractRange(reveal.i6_k);
|
||||||
|
assert(h.size() <= 4);
|
||||||
|
uint32_t v = 0;
|
||||||
|
for (char ch: h) {
|
||||||
|
v <<= 4;
|
||||||
|
if ('0' <= ch && ch <= '9') {
|
||||||
|
v |= (uint32_t)(ch - '0');
|
||||||
|
} else if ('a' <= ch && ch <= 'z') {
|
||||||
|
v |= (uint32_t)(ch - 'a' + 10);
|
||||||
|
} else if ('A' <= ch && ch <= 'Z') {
|
||||||
|
v |= (uint32_t)(ch - 'A' + 10);
|
||||||
|
} else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
assert(v <= UINT16_MAX);
|
||||||
|
res_u6_addr16[bi++] = (uint16_t)v;
|
||||||
|
} else if (curKey() == reveal.skip_k) {
|
||||||
|
ci++;
|
||||||
|
for (int j = 0; j < skipped; j++)
|
||||||
|
res_u6_addr16[bi++] = 0;
|
||||||
|
} else
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
assert(bi == 8);
|
||||||
|
uint32_t res_port = std::stoul(extractRange(reveal.ip_k));
|
||||||
|
if (res_port > 65535)
|
||||||
|
return -1;
|
||||||
|
res.v.gen.sa_family = AF_INET6;
|
||||||
|
res.v.sin6.sin6_port = htons(res_port);
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
res.v.sin6.sin6_addr.__in6_u.__u6_addr16[i] = htons(res_u6_addr16[i]);
|
||||||
|
res.addrLen = sizeof(sockaddr_in6);
|
||||||
|
} else
|
||||||
|
assert(false);
|
||||||
|
assert(ci == ca.size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const std::string& up = "unix:";
|
||||||
|
if (beginsWith(addr, up)) {
|
||||||
|
std::string path = addr.substr(up.size());
|
||||||
|
if (path.empty())
|
||||||
|
return -1;
|
||||||
|
if (path.back() == '/')
|
||||||
|
return -1;
|
||||||
|
for (char ch: path)
|
||||||
|
if (ch == 0)
|
||||||
|
return -1;
|
||||||
|
res.v.gen.sa_family = AF_UNIX;
|
||||||
|
if (sizeof(res.v.sun.sun_path) > path.size())
|
||||||
|
THROW("path is too big");
|
||||||
|
memcpy(res.v.sun.sun_path, path.c_str(), path.size());
|
||||||
|
res.addrLen = offsetof(sockaddr_un, sun_path) + path.size();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string short2hex(uint16_t v) {
|
||||||
|
if (v == 0)
|
||||||
|
return "0";
|
||||||
|
std::string result;
|
||||||
|
while (v) {
|
||||||
|
result += (char)((v & 0xf) > 9 ? (v & 0xf) - 10 + 'a' : (v & 0xf) + '0');
|
||||||
|
v >>= 4;
|
||||||
|
}
|
||||||
|
std::reverse(result.begin(), result.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string stringify_socket_address(const SocketAddress &addr) {
|
||||||
|
if (addr.v.gen.sa_family == AF_INET) {
|
||||||
|
char buf[22];
|
||||||
|
uint32_t IP = ntohl(addr.v.sin.sin_addr.s_addr);
|
||||||
|
uint16_t port = ntohs(addr.v.sin.sin_port);
|
||||||
|
snprintf(buf, 22, "%u.%u.%u.%u:%hu", (IP >> 24) & 0xff, (IP >> 16) & 0xff, (IP >> 8) & 0xff,
|
||||||
|
(IP >> 0) & 0xff, port);
|
||||||
|
return buf;
|
||||||
|
} else if (addr.v.gen.sa_family == AF_INET6) {
|
||||||
|
uint16_t IP[8];
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
IP[i] = ntohs(addr.v.sin6.sin6_addr.__in6_u.__u6_addr16[i]);
|
||||||
|
uint16_t port = ntohs(addr.v.sin6.sin6_port);
|
||||||
|
int largest_sz = 0;
|
||||||
|
int largest_start = 0;
|
||||||
|
int cur_sz = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (IP[i] == 0) {
|
||||||
|
cur_sz++;
|
||||||
|
if (largest_sz < cur_sz) {
|
||||||
|
largest_sz = cur_sz;
|
||||||
|
largest_start = i + 1 - cur_sz;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cur_sz = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string core;
|
||||||
|
for (int i = 0; i < 8;) {
|
||||||
|
if (largest_sz >= 2 && largest_start == i) {
|
||||||
|
i += largest_sz;
|
||||||
|
if (i == 8)
|
||||||
|
core += "::";
|
||||||
|
else
|
||||||
|
core += ":";
|
||||||
|
} else {
|
||||||
|
if (i > 0)
|
||||||
|
core += ":";
|
||||||
|
core += short2hex(IP[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(core.size() <= 39);
|
||||||
|
char buf[48];
|
||||||
|
snprintf(buf, 48, "[%s]:%hu", core.c_str(), port);
|
||||||
|
return buf;
|
||||||
|
} else if (addr.v.gen.sa_family == AF_UNIX) {
|
||||||
|
assert(addr.addrLen > offsetof(sockaddr_un, sun_path));
|
||||||
|
size_t path_len = addr.addrLen - offsetof(sockaddr_un, sun_path);
|
||||||
|
assert(path_len <= sizeof(addr.v.sun.sun_path));
|
||||||
|
std::string path(path_len, ')');
|
||||||
|
memcpy(path.data(), addr.v.sun.sun_path, path_len);
|
||||||
|
return "unix:" + path;
|
||||||
|
} else
|
||||||
|
return "Socket address of unknown domain";
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_to_socket_address(int sockfd, const SocketAddress &addr) {
|
||||||
|
int ret;
|
||||||
|
if (addr.v.gen.sa_family == AF_INET) {
|
||||||
|
ret = bind(sockfd, (const sockaddr*)&addr.v.sin, addr.addrLen);
|
||||||
|
} else if (addr.v.gen.sa_family == AF_INET6) {
|
||||||
|
ret = bind(sockfd, (const sockaddr*)&addr.v.sin6, addr.addrLen);
|
||||||
|
} else if (addr.v.gen.sa_family == AF_INET) {
|
||||||
|
ret = bind(sockfd, (const sockaddr*)&addr.v.sun, addr.addrLen);
|
||||||
|
} else
|
||||||
|
THROW("binding socket to address of unsupported domain");
|
||||||
|
ASSERT_on_iret(ret, "binding socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_peer_name_as_socket_address(int sockfd, SocketAddress &res) {
|
||||||
|
socklen_t willbecome = sizeof(res.v);
|
||||||
|
int ret = getpeername(sockfd, &res.v.gen, &willbecome);
|
||||||
|
ASSERT_on_iret(ret, "getpeername");
|
||||||
|
assert(willbecome <= sizeof(res.v));
|
||||||
|
res.addrLen = willbecome;
|
||||||
|
}
|
||||||
|
}
|
51
src/http_server/engine_engine_number_9/socket_address.h
Normal file
51
src/http_server/engine_engine_number_9/socket_address.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef ENGINE_ENGINE_NUMBER_9_SOCKET_ADDRESS_H
|
||||||
|
#define ENGINE_ENGINE_NUMBER_9_SOCKET_ADDRESS_H
|
||||||
|
|
||||||
|
#if defined(SOLARIS)
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#if defined(BSD)
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace een9 {
|
||||||
|
/* Right now een9 supports only IP4, IP6, unix domain. System service querying is not implemented yet *
|
||||||
|
* */
|
||||||
|
|
||||||
|
struct SocketAddress {
|
||||||
|
union {
|
||||||
|
sockaddr gen;
|
||||||
|
sockaddr_in sin;
|
||||||
|
sockaddr_in6 sin6;
|
||||||
|
sockaddr_un sun;
|
||||||
|
} v;
|
||||||
|
size_t addrLen = sizeof(sockaddr_in);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Not thread-safe. Use only from one thread (at a time) */
|
||||||
|
struct SocketAddressParser {
|
||||||
|
void* opaque = NULL;
|
||||||
|
|
||||||
|
SocketAddressParser();
|
||||||
|
SocketAddressParser(const SocketAddressParser&) = default;
|
||||||
|
SocketAddressParser& operator=(const SocketAddressParser&) = default;
|
||||||
|
~SocketAddressParser();
|
||||||
|
};
|
||||||
|
|
||||||
|
int parse_socket_address(const std::string& addr, SocketAddress& res, SocketAddressParser& pdata);
|
||||||
|
|
||||||
|
std::string stringify_socket_address(const SocketAddress& addr);
|
||||||
|
|
||||||
|
/* Throws ServerError on error */
|
||||||
|
void bind_to_socket_address(int sockfd, const SocketAddress& addr);
|
||||||
|
|
||||||
|
/* Throws ServerError on error */
|
||||||
|
void get_peer_name_as_socket_address(int sockfd, SocketAddress& res);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
72
src/http_server/misc_tests/sockaddr_parse_test.cpp
Normal file
72
src/http_server/misc_tests/sockaddr_parse_test.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include <engine_engine_number_9/socket_address.h>
|
||||||
|
#include <engine_engine_number_9/baza.h>
|
||||||
|
|
||||||
|
using namespace een9;
|
||||||
|
|
||||||
|
void test(const std::string& test, bool is_correct, SocketAddressParser& parser) {
|
||||||
|
#define fup printf("Test failed\n"); fflush(stdout); abort(); return;
|
||||||
|
SocketAddress addr;
|
||||||
|
int ret = parse_socket_address(test, addr, parser);
|
||||||
|
if ((ret == 0) != is_correct) {
|
||||||
|
fup
|
||||||
|
}
|
||||||
|
if (is_correct) {
|
||||||
|
std::string back = stringify_socket_address(addr);
|
||||||
|
if (make_uppercase(test) != make_uppercase(back)){
|
||||||
|
fup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Test passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_dcs(const std::string& test, const std::string& need, SocketAddressParser& parser) {
|
||||||
|
SocketAddress addr;
|
||||||
|
int ret = parse_socket_address(test, addr, parser);
|
||||||
|
if (ret != 0) {
|
||||||
|
fup
|
||||||
|
}
|
||||||
|
std::string right = stringify_socket_address(addr);
|
||||||
|
if (right != need) {
|
||||||
|
fup
|
||||||
|
}
|
||||||
|
printf("Test passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
SocketAddressParser parser;
|
||||||
|
test("[12::12:0:0:0]:600", true, parser);
|
||||||
|
test("[12::12:0:FFFF:0]:600", true, parser);
|
||||||
|
test("[12::11:1]:600", true, parser);
|
||||||
|
test("[::a::]:600", false, parser);
|
||||||
|
test("[FFd:1:1:1:1:FFd:1:f]:65535", true, parser);
|
||||||
|
test("[f:f:f:f:f:0:1:f]:65535", true, parser);
|
||||||
|
test("[1:1:1:1:1:0:1:0]:11212", true, parser);
|
||||||
|
test("[1:1:1:1:1:1:1:1]:1", true, parser);
|
||||||
|
test("[1:1:1:1:1:0:1:0]:65536", false, parser);
|
||||||
|
test("[1:1:1:1:1:0:1:0]:65535", true, parser);
|
||||||
|
test("[1:H:1:1:1:FFd:1:f]:65535", false, parser);
|
||||||
|
|
||||||
|
test("[::]:1", true, parser);
|
||||||
|
test("12.11.11.123:312", true, parser);
|
||||||
|
test("0.1.111.123:31212", true, parser);
|
||||||
|
test("0.1.111.123:65536", false, parser);
|
||||||
|
test("0.1.111.123:65535", true, parser);
|
||||||
|
test("0.1.111.255:65535", true, parser);
|
||||||
|
test("255.0.255.255:65535", true, parser);
|
||||||
|
test("255.0.256.0:65535", false, parser);
|
||||||
|
test("255.0.1000.0:65535", false, parser);
|
||||||
|
test("255.0.01.0:65535", false, parser);
|
||||||
|
test("255.0.1.0:605535", false, parser);
|
||||||
|
test("2.0.1.0:05535", false, parser);
|
||||||
|
test("255.0.1.0::65535", false, parser);
|
||||||
|
test(".255.0.1.0::65535", false, parser);
|
||||||
|
test("..0.1.0::65535", false, parser);
|
||||||
|
test("[FFFF0::]:0", false, parser);
|
||||||
|
test("[0::01:]:0", false, parser);
|
||||||
|
test("[0:fa:ffff::]:0", true, parser);
|
||||||
|
test("[::a:a:a:a:a:a:b]:10", false, parser);
|
||||||
|
test_dcs("[0:0:0:0:0:0:0:0]:413", "[::]:413", parser);
|
||||||
|
test_dcs("[::0:0:0:0]:413", "[::]:413", parser);
|
||||||
|
test_dcs("[::0:0:0:0:0:0]:413", "[::]:413", parser);
|
||||||
|
test_dcs("[::a:a:0:0:0:0]:413", "[0:0:a:a::]:413", parser);
|
||||||
|
}
|
@ -100,7 +100,7 @@ namespace nytl {
|
|||||||
while ((ret = (int)read(fd, buf, 2048)) > 0) {
|
while ((ret = (int)read(fd, buf, 2048)) > 0) {
|
||||||
size_t oldN = result.size();
|
size_t oldN = result.size();
|
||||||
result.resize(oldN + ret);
|
result.resize(oldN + ret);
|
||||||
memcpy((void*)&result.c_str()[oldN], buf, ret);
|
memcpy(result.data() + oldN, buf, ret);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
AAA
|
|
||||||
{% FOR _:val IN cba %}
|
|
||||||
TUTUTUTUTUTUTUTUN {% PUT jesccomp val %}
|
|
||||||
{% ENDFOR %}
|
|
@ -57,7 +57,7 @@ void sqlite_single_statement(sqlite3* db_hand, const std::string& req_statement)
|
|||||||
printf("NULL | ");
|
printf("NULL | ");
|
||||||
} else {
|
} else {
|
||||||
const unsigned char* text = sqlite3_column_text(stmt_obj, i);
|
const unsigned char* text = sqlite3_column_text(stmt_obj, i);
|
||||||
een9_ASSERT(sqlite3_errcode(db_hand) != SQLITE_NOMEM, "oom in sqlite3_column_text");
|
een9_ASSERT(text, "oom in sqlite3_column_text");
|
||||||
printf("%s | ", (const char*)text);
|
printf("%s | ", (const char*)text);
|
||||||
// todo: THIS F. B.S. IS NOT SAFE
|
// todo: THIS F. B.S. IS NOT SAFE
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ int main(int argc, char** argv){
|
|||||||
if (argc != 1 + 2)
|
if (argc != 1 + 2)
|
||||||
usage(argv);
|
usage(argv);
|
||||||
std::string config_file = argv[1];
|
std::string config_file = argv[1];
|
||||||
if (!een9::isRegularFile(config_file) || !een9::endsIn(config_file, ".json")) {
|
if (!een9::isRegularFile(config_file) || !een9::endsWith(config_file, ".json")) {
|
||||||
printf("\"%s\" is not a json file\n", argv[1]);
|
printf("\"%s\" is not a json file\n", argv[1]);
|
||||||
usage(argv);
|
usage(argv);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
|
#include <engine_engine_number_9/form_data_structure/urlencoded_query.h>
|
||||||
#include <new_york_transit_line/templater.h>
|
#include <new_york_transit_line/templater.h>
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
#include <engine_engine_number_9/socket_address.h>
|
||||||
|
|
||||||
bool termination = false;
|
bool termination = false;
|
||||||
|
|
||||||
@ -17,87 +17,93 @@ void sigterm_action(int) {
|
|||||||
termination = true;
|
termination = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string unsafe_client_request_stringification(const een9::ClientRequest& req) {
|
|
||||||
std::string text = "\n\nGot some cool stuff\n";
|
|
||||||
text += (req.method + " " + req.uri_path + " " + req.http_version + "\n");
|
|
||||||
for (auto& p: req.headers) {
|
|
||||||
text += p.first; text += ": "; text += p.second; text += "\n";
|
|
||||||
}
|
|
||||||
text += "Body\n"; text += req.body; text += "\n";
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void run_website(const json::JSON& config) {
|
void run_website(const json::JSON& config) {
|
||||||
een9_ASSERT(config["assets"].g().isString(), "config[\"\assets\"] is not string");
|
een9_ASSERT(config["assets"].g().isString(), "config[\"assets\"] is not string");
|
||||||
std::string assets_dir = config["assets"].g().asString();
|
std::string assets_dir = config["assets"].g().asString();
|
||||||
een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory");
|
een9_ASSERT(een9::isDirectory(assets_dir), "\"" + assets_dir + "\" is not a directory");
|
||||||
|
|
||||||
een9::StaticAssetManagerSlaveModule samI;
|
een9::StaticAssetManagerSlaveModule samI;
|
||||||
samI.update({
|
samI.update({
|
||||||
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
|
een9::StaticAssetManagerRule{assets_dir + "/css", "/assets/css", {{".css", "text/css"}} },
|
||||||
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
|
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
|
||||||
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {
|
een9::StaticAssetManagerRule{assets_dir + "/img", "/assets/img", {
|
||||||
{".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"}
|
{".jpg", "image/jpg"}, {".png", "image/png"}, {".svg", "image/svg+xml"}
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
|
|
||||||
const json::JSON& config_presentation = config["presentation"].g();
|
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");
|
||||||
|
|
||||||
|
struct WorkerGuestData {
|
||||||
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
|
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
|
||||||
std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8);
|
een9::uptr<nytl::Templater> templater;
|
||||||
for (int i = 0; i < 8; i++) {
|
};
|
||||||
templaters_copies[i] = std::make_unique<nytl::Templater>(
|
std::vector<WorkerGuestData> worker_guest_data;
|
||||||
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
|
for (int i = 0; i < slave_number; i++) {
|
||||||
templaters_copies[i]->update();
|
worker_guest_data[i].templater = std::make_unique<nytl::Templater>(
|
||||||
}
|
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
|
||||||
|
worker_guest_data[i].templater->update();
|
||||||
|
}
|
||||||
|
|
||||||
// printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
|
een9::MainloopParameters params;
|
||||||
// return 0;
|
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::MainloopParameters params;
|
een9_ASSERT_pl(0 <= worker_id && worker_id < worker_guest_data.size());
|
||||||
params.guest_core = [&samI, &templaters_copies, config_presentation]
|
nytl::Templater& templater = *worker_guest_data[worker_id].templater;
|
||||||
(const een9::SlaveTask& task, const een9::ClientRequest& req, een9::worker_id_t worker_id) -> std::string {
|
een9::StaticAsset sa;
|
||||||
een9_ASSERT_pl(0 <= worker_id && worker_id < templaters_copies.size());
|
int ret;
|
||||||
nytl::Templater& templater = *templaters_copies[worker_id];
|
auto rteee = [&](const std::string& el_name, bool pass_phr) -> std::string {
|
||||||
een9::StaticAsset sa;
|
std::string page = templater.render(el_name,
|
||||||
int ret;
|
pass_phr ? std::vector<const json::JSON*>{&config_presentation} : std::vector<const json::JSON*>{});
|
||||||
// printf("%s", unsafe_client_request_stringification(req).c_str());
|
return een9::form_http_server_response_200("text/html", page);
|
||||||
// if (req.uri_path == "/output") {
|
|
||||||
// std::string text = unsafe_client_request_stringification(req);
|
|
||||||
// return een9::form_http_server_response_200("text/plain", text);
|
|
||||||
// }
|
|
||||||
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") {
|
|
||||||
return rteee("list-rooms", true);
|
|
||||||
}
|
|
||||||
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>");
|
|
||||||
};
|
};
|
||||||
|
if (req.uri_path == "/" || req.uri_path == "/list-rooms") {
|
||||||
|
return rteee("list-rooms", true);
|
||||||
|
}
|
||||||
|
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.ports_to_listen = {1025};
|
params.guest_core_admin_control = []
|
||||||
params.slave_number = 8;
|
(const een9::SlaveTask& task, const std::string& req, een9::worker_id_t) -> std::string {
|
||||||
params.open_admin_listener = false;
|
if (req == "hello") {
|
||||||
|
return ":0 omg! hiii!! Hewwou :3 !!!!";
|
||||||
|
} if (req == "8") {
|
||||||
|
termination = true;
|
||||||
|
return "Bye";
|
||||||
|
} else {
|
||||||
|
return "Incorrect command";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
signal(SIGINT, sigterm_action);
|
params.slave_number = slave_number;
|
||||||
signal(SIGTERM, sigterm_action);
|
|
||||||
|
|
||||||
een9::electric_boogaloo(params, termination);
|
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);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user