Compare commits

..

No commits in common. "6be78c15105dc9285b2318161ba52430619360c2" and "1aa95ad87e3f54f5163afc349c1bd9c22f87ab74" have entirely different histories.

31 changed files with 235 additions and 907 deletions

2
.gitignore vendored
View File

@ -13,4 +13,4 @@ compile_commands.json
local.sh local.sh
iu9-ca-web-chat.db iu9-ca-web-chat.db
log/ log

View File

@ -1,13 +1,13 @@
{% 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">
@ -49,6 +49,6 @@
</div> </div>
<script src="/assets/js/list-rooms.js"></script> <script src="/assets/js/list-rooms.js"></script>
</body> </body>
</html> </html>
{% ENDELDEF %} {% ENDELDEF %}

View File

@ -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++17", "-D", "_POSIX_C_SOURCE=200809L"}; std::vector<std::string> version_flags = {"--std", "c++14", "-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,8 +78,6 @@ 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",
"admin_control.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;
@ -95,8 +93,6 @@ 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;
@ -144,24 +140,11 @@ struct CAWebChat {
"find_db.cpp", "find_db.cpp",
}; };
for (std::string& u: T.units) for (std::string& u: T.units)
u = "web_chat/iu9_ca_web_chat_service/" + u; u = "web_chat/" + u;
T.include_pr = "web_chat"; T.include_pr = "web_chat";
T.installation_dir = ""; T.installation_dir = "";
my_targets.push_back(T); my_targets.push_back(T);
} }
{ CTarget T{"iu9-ca-web-chat-admin-cli", "executable"};
T.additional_compilation_flags = getSomeRadFlags();
T.proj_deps = {
CTargetDependenceOnProjectsLibrary{"engine_engine_number_9"},
};
T.units = {
"cli.cpp", // Main file
};
for (std::string& u: T.units)
u = "web_chat/iu9_ca_web_chat_admin_cli/" + u;
T.include_pr = "web_chat";
my_targets.push_back(T);
}
regular_ctargets_to_2bus_conversion(ext_targets, my_targets, runlevel_1, runlevel_2, regular_ctargets_to_2bus_conversion(ext_targets, my_targets, runlevel_1, runlevel_2,
cmd.project_root, cmd.installation_root); cmd.project_root, cmd.installation_root);
} }

View File

@ -31,6 +31,6 @@
"server": { "server": {
"workers": 8, "workers": 8,
"http-listen": ["127.0.0.1:1025"], "http-listen": ["127.0.0.1:1025"],
"admin-command-listen": ["127.0.0.1:1026"] "command-listen": []
} }
} }

View File

@ -1,62 +0,0 @@
#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 {
body += ch;
if (body.size() >= b_sz)
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 = ms;
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);
}
}

View File

@ -1,37 +0,0 @@
#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

View File

@ -28,30 +28,14 @@ namespace een9 {
return false; return false;
} }
bool endsWith(const std::string &a, const std::string &b) { bool endsIn(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;
}
} }

View File

@ -18,17 +18,11 @@ namespace een9 {
bool strIn(const std::string& str, const char* arr[]); bool strIn(const std::string& str, const char* arr[]);
// b is postfix of a bool endsIn(const std::string& a, const std::string& b);
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>;
} }

View File

@ -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 (endsWith(file, ext.required_postfix)) { if (endsIn(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);

View File

@ -5,12 +5,11 @@
#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() {
@ -107,10 +106,8 @@ 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)
status = -1; THROW("Message content is too big");
return status;
}
res.body.reserve(body_size); res.body.reserve(body_size);
} }
} }
@ -124,6 +121,7 @@ namespace een9 {
writeFile("log/req", header); writeFile("log/req", header);
#endif #endif
status = -1; status = -1;
THROW("bad request");
} }
} }
return status; return status;

View File

@ -37,6 +37,7 @@ 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;

View File

@ -25,6 +25,7 @@ namespace een9 {
} }
UniqueFdWrapper::~UniqueFdWrapper() { UniqueFdWrapper::~UniqueFdWrapper() {
// printf("DEBUG!!! Closing fd = %d\n", fd);
if (fd >= 0) if (fd >= 0)
close(fd); close(fd);
} }
@ -54,7 +55,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(result.data() + oldN, buf, ret); memcpy((void*)&result.c_str()[oldN], buf, ret);
} }
ASSERT_on_iret(ret, "Reading from " + description); ASSERT_on_iret(ret, "Reading from " + description);
} }

View File

@ -13,7 +13,6 @@
#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 {
@ -74,13 +73,11 @@ 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, const MainloopParameters& params): termination(term), WorkersEnvCommon(bool& term, guest_core_t g_c): termination(term), guest_core(std::move(g_c)){}
guest_core(params.guest_core), guest_core_admin_control(params.guest_core_admin_control){}
}; };
struct WorkersEnv { struct WorkersEnv {
@ -92,22 +89,25 @@ namespace een9 {
}; };
// todo: add timeout for multiple bytes, add more settings // todo: add timeout for multiple bytes, add more settings
ClientRequest process_http_connection_input(int fd, const EEN9_ServerTips& s_tips, WorkersEnv& wte) { ClientRequest process_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(parser.status == 0); ASSERT_pl(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++) {
if (parser.feedCharacter(buf[i]) != 0) /* Throws ServerError on bad input */
if (parser.feedCharacter(buf[i]) > 0) {
break; break;
} }
if (parser.status != 0) }
if (parser.status > 0)
break; break;
} }
ASSERT(parser.status == 1, "Incorrect request"); // todo: do the same thing everywhere else
ASSERT_on_iret(ret, "recv"); ASSERT_on_iret(ret, "recv");
ASSERT_pl(parser.status == 1);
// printf("Log: worker received clients request\n%s\n", client_request.toString().c_str());
return res; return res;
} }
@ -123,41 +123,10 @@ 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(pctx.status == 1, "Incorrect request");
ASSERT_on_iret(ret, "recv");
return pctx.body;
}
void process_connection(const SlaveTask& task, WorkersEnv& wte) { void process_connection(const SlaveTask& task, WorkersEnv& wte) {
if (task.conn_info.type == 0) { ClientRequest client_request = process_connection_input(task.fd(), task.s_tips, wte);
printf("%d::Got http reuest\n", wte.id);
ClientRequest client_request = process_http_connection_input(task.fd(), task.s_tips, wte);
printf("%d::Http request has been read\n", wte.id);
std::string server_response = wte.wtec.guest_core(task, client_request, wte.id); std::string server_response = wte.wtec.guest_core(task, client_request, wte.id);
process_connection_output(task.fd(), server_response); process_connection_output(task.fd(), server_response);
printf("%d::Http response has been sent\n", wte.id);
} else if (task.conn_info.type == 1) {
printf("%d::Got admin-cmd request\n", wte.id);
std::string admin_request = process_admin_control_connection_input(task.fd(), task.s_tips, wte);
printf("%d::Admin-cmd request has been read\n", wte.id);
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);
printf("%d::Admin-cmd response has been sent\n", wte.id);
}
} }
void* worker_func(void* wte_ptr) { void* worker_func(void* wte_ptr) {
@ -187,13 +156,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); WorkersEnvCommon wtec(termination_trigger, params.guest_core);
ASSERT(params.slave_number > 0, "No workers spawned"); ASSERT(params.slave_number > 0, "No workers spawned");
size_t CRL_Nip = params.client_regular_listened.size(); size_t Nip = params.ports_to_listen.size();
ASSERT(CRL_Nip > 0, "No open listeting addresses (http)"); ASSERT(Nip > 0, "No open listeting addresses");
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);
@ -204,49 +173,44 @@ 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;
struct Ear { std::vector<UniqueFdWrapper> listening_socks(Nip);
/* 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, "Can't set SO_REUSEADDR"); ASSERT_on_iret(ret, "setting SO_REUSEADDR befire binding to address");
bind_to_socket_address(listening_socket_fd, ears[i].my_addr); ret = bind(listening_socket(), (const sockaddr*)&listening_address, sizeof(listening_address));
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, "listen() listening for connections"); ASSERT_on_iret(ret, "listening for connections");
ears[i].listening_sock = std::move(listening_socket); printf("Listening socket succesfully started listening\n");
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 = ears[i].listening_sock(); pollfds[i].fd = listening_socks[i]();
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;
} }
@ -254,24 +218,21 @@ 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;
// todo: do not end program here (in the loop. Nothing in the loop should be able to end program) ASSERT_on_iret(ret, "polling");
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 {
int session_sock = accept(pollfds[i].fd, NULL, NULL); sockaddr client_address;
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{ SlaveTask task{ConnectionInfo{}, std::move(session_sock_fdw),
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));
} }

View File

@ -7,14 +7,12 @@
#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 {
SocketAddress server_name; // todo: add server address field
SocketAddress client_name; // todo: add client address field
/* 0 - http, 1 - 'een9::admin-control' protocol */ int type; // O_o why??
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
@ -35,8 +33,6 @@ 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;
@ -46,18 +42,14 @@ 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;
size_t slave_number = 2; bool open_admin_listener = true;
int mainloop_recheck_interval_us = 100; // todo: add support for unix socket address
uint16_t admin_listener_port = 12345;
/* Takes parsed http request object. Should return fully-prepared http response */
guest_core_t guest_core; guest_core_t guest_core;
/* Takes admin input. Returns only desired output message (without protocol header) */ size_t slave_number = 2;
guest_core_admin_control_t guest_core_admin_control; std::vector<uint16_t> ports_to_listen;
int mainloop_recheck_interval_us = 100;
ServersConfiguration s_conf; ServersConfiguration s_conf;
}; };

View File

@ -1,277 +0,0 @@
#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) {
sa_family_t f = addr.v.gen.sa_family;
if (f == AF_INET || f == AF_INET6 || f == AF_UNIX) {
int ret = bind(sockfd, &addr.v.gen, addr.addrLen);
ASSERT_on_iret(ret, "binding socket");
} else
THROW("binding socket to address of unsupported domain");
}
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;
}
void connect_to_socket_address(int sockfd, const SocketAddress& targ) {
int ret = connect(sockfd, &targ.v.gen, targ.addrLen);
ASSERT_on_iret(ret, "connect socket to addr");
}
}

View File

@ -1,53 +0,0 @@
#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&) = delete;
SocketAddressParser& operator=(const SocketAddressParser&) = delete;
~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);
void connect_to_socket_address(int sockfd, const SocketAddress& targ);
}
#endif

View File

@ -1,73 +0,0 @@
#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("127:0:0:1:1026", false, 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);
}

View File

@ -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(result.data() + oldN, buf, ret); memcpy((void*)&result.c_str()[oldN], buf, ret);
} }
if (ret < 0) { if (ret < 0) {
close(fd); close(fd);

View File

@ -0,0 +1,4 @@
AAA
{% FOR _:val IN cba %}
TUTUTUTUTUTUTUTUN {% PUT jesccomp val %}
{% ENDFOR %}

View File

@ -3,7 +3,7 @@
#include "str_fields_check.h" #include "str_fields_check.h"
#include <sqlite3.h> #include <sqlite3.h>
#include <engine_engine_number_9/os_utils.h> #include <engine_engine_number_9/os_utils.h>
#include "find_db.h" #include <find_db.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
@ -45,19 +45,19 @@ void sqlite_single_statement(sqlite3* db_hand, const std::string& req_statement)
printf("Values: | "); printf("Values: | ");
for (int i = 0; i < cc; i++) { for (int i = 0; i < cc; i++) {
if (types[i] == SQLITE_INTEGER) { if (types[i] == SQLITE_INTEGER) {
printf("%lld | ", sqlite3_column_int64(stmt_obj, i)); printf("%ld | ", sqlite3_column_int64(stmt_obj, i));
} else if (types[i] == SQLITE_FLOAT) { } else if (types[i] == SQLITE_FLOAT) {
printf("%lf | ", sqlite3_column_double(stmt_obj, i)); printf("%lf | ", sqlite3_column_double(stmt_obj, i));
} else if (types[i] == SQLITE_BLOB) { } else if (types[i] == SQLITE_BLOB) {
const void* blob = sqlite3_column_blob(stmt_obj, i); const void* blob = sqlite3_column_blob(stmt_obj, i);
een9_ASSERT(sqlite3_errcode(db_hand) == SQLITE_OK, "oom in sqlite3_column_blob"); een9_ASSERT(sqlite3_errcode(db_hand) == SQLITE_OK, "oom in sqlite3_column_blob");
size_t sz = sqlite3_column_bytes(stmt_obj, i); size_t sz = sqlite3_column_bytes(stmt_obj, i);
printf("Blob of size %lu | ", sz); printf("Blob of size %s | ", sz);
} else if (types[i] == SQLITE_NULL) { } else if (types[i] == SQLITE_NULL) {
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(text, "oom in sqlite3_column_text"); een9_ASSERT(sqlite3_errcode(db_hand) != SQLITE_NOMEM, "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
} }

View File

@ -1,81 +0,0 @@
#include <engine_engine_number_9/admin_control.h>
#include <engine_engine_number_9/socket_address.h>
#include <engine_engine_number_9/baza_throw.h>
#include <assert.h>
#include <engine_engine_number_9/os_utils.h>
/* This so called 'een9::admin-control' protocol is very simple:
* Admin sends request to server:
* <Magic constant string> <8 byte field: size of body> <body (string of any characters)>
* Server reads it to the end and sents response to admin:
* <Magic constant string> <8 byte field: size of body> <body (string of any characters)>
* More can be found in src/http_server/engine_engine_number_9/admin_control.cpp
*/
void send_request_msg(int fd, const std::string& request_msg) {
std::string str = een9::generate_admin_control_request(request_msg);
size_t N = str.size(), i = 0;
while (i < N) {
int written = (int)send(fd, &str[i], std::min(2048lu, N - i), MSG_NOSIGNAL);
een9_ASSERT_on_iret(written, "sending");
een9_ASSERT_pl(written > 0);
i += written;
}
}
std::string receive_response_msg(int fd) {
een9::AdminControlResponseRCtx 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;
}
een9_ASSERT(pctx.status == 1, "Received incorrect response");
een9_ASSERT_on_iret(ret, "recv");
return pctx.body;
}
void usage(char* za) {
printf("%s <address of servers admin cmd listener> <message> [<other parts of message> ...]\n", za);
exit(1);
}
int main(int argc, char** argv) {
if (argc < 1)
return 134;
if (argc < 3) {
usage(argv[0]);
}
try {
std::string conn_addr_targ = argv[1];
std::string msg;
for (int i = 2; i < argc; i++) {
if (!msg.empty())
msg += '\n';
msg += argv[i];
}
int ret;
een9::SocketAddressParser sap;
een9::SocketAddress addr;
ret = een9::parse_socket_address(conn_addr_targ, addr, sap);
een9_ASSERT(ret == 0, "Incorrect address");
int sock = socket(addr.v.gen.sa_family, SOCK_STREAM, 0);
een9_ASSERT_on_iret(sock, "creating socket to target server");
een9::UniqueFdWrapper sockGuard(sock);
een9::connect_to_socket_address(sock, addr);
printf("Ready to send request\n");
send_request_msg(sock, msg);
printf("Admin-cmd request has been sent\n");
std::string answer = receive_response_msg(sock);
printf("Admin-cmd response has been read\n");
printf("Successfull command\n%s", answer.c_str());
} catch (const std::exception& e) {
printf("%s\n", e.what());
}
}

View File

@ -1,109 +0,0 @@
#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>
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"}} },
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
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");
struct WorkerGuestData {
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
een9::uptr<nytl::Templater> templater;
};
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();
}
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());
nytl::Templater& templater = *worker_guest_data[worker_id].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") {
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.guest_core_admin_control = []
(const een9::SlaveTask& task, const std::string& req, een9::worker_id_t) -> std::string {
if (req == "hello") {
return ":0 omg! hiii!! Hewwou :3 !!!!";
} if (req == "8") {
termination = true;
return "Bye";
} else {
return "Incorrect command";
}
};
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);
}

View File

@ -5,21 +5,20 @@
#include "actions.h" #include "actions.h"
#include <stdexcept> #include <stdexcept>
void usage(char* argv0) { void usage(char** argv) {
printf("Usage: %s <file with settings> <run|initialize>\n", argv0); printf("Usage: %s <file with settings> <run|initialize>\n", argv[0]);
exit(1); exit(1);
} }
int main(int argc, char** argv){ int main(int argc, char** argv){
try { try {
if (argc < 1) een9_ASSERT_pl(argc > 0);
return 111;
if (argc != 1 + 2) if (argc != 1 + 2)
usage(argv[0]); usage(argv);
std::string config_file = argv[1]; std::string config_file = argv[1];
if (!een9::isRegularFile(config_file) || !een9::endsWith(config_file, ".json")) { if (!een9::isRegularFile(config_file) || !een9::endsIn(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[0]); usage(argv);
} }
std::string cmd = argv[2]; std::string cmd = argv[2];
std::string config_text; std::string config_text;

103
src/web_chat/run.cpp Normal file
View File

@ -0,0 +1,103 @@
#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>
bool termination = false;
void sigterm_action(int) {
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) {
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"}} },
een9::StaticAssetManagerRule{assets_dir + "/js", "/assets/js", {{".js", "text/js"}} },
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();
/* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */
std::vector<std::unique_ptr<nytl::Templater>> templaters_copies(8);
for (int i = 0; i < 8; i++) {
templaters_copies[i] = std::make_unique<nytl::Templater>(
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});
templaters_copies[i]->update();
}
// printf("%s\n", templaters_copies[0]->render("list-rooms", {&config_presentation}).c_str());
// return 0;
een9::MainloopParameters params;
params.guest_core = [&samI, &templaters_copies, 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 < templaters_copies.size());
nytl::Templater& templater = *templaters_copies[worker_id];
een9::StaticAsset sa;
int ret;
// printf("%s", unsafe_client_request_stringification(req).c_str());
// 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>");
};
params.ports_to_listen = {1025};
params.slave_number = 8;
params.open_admin_listener = false;
signal(SIGINT, sigterm_action);
signal(SIGTERM, sigterm_action);
een9::electric_boogaloo(params, termination);
}