fixed some bugs, made an utility to send admin commands to server, added both http listeners and admin-cmd listeners. Command "8" to shutdown the server. And the most important: IU9 CA Web Chat can now talk like a mentally ill teenager (command "hello" (gonna delete this later))

This commit is contained in:
Андреев Григорий 2024-08-20 00:07:17 +03:00
parent 4d18d13a93
commit 6be78c1510
15 changed files with 136 additions and 30 deletions

View File

@ -79,6 +79,7 @@ struct CAWebChat {
"running_mainloop.cpp", "running_mainloop.cpp",
"form_data_structure/urlencoded_query.cpp", "form_data_structure/urlencoded_query.cpp",
"socket_address.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;
@ -143,11 +144,24 @@ struct CAWebChat {
"find_db.cpp", "find_db.cpp",
}; };
for (std::string& u: T.units) for (std::string& u: T.units)
u = "web_chat/" + u; u = "web_chat/iu9_ca_web_chat_service/" + 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

@ -27,10 +27,10 @@ namespace een9 {
return status; return status;
} }
body.reserve(b_sz); body.reserve(b_sz);
} else if (body.size() < b_sz) {
body += ch;
} else { } else {
status = 1; body += ch;
if (body.size() >= b_sz)
status = 1;
} }
return status; return status;
} }
@ -42,7 +42,7 @@ namespace een9 {
} }
std::string generate_ac_msg_gen_case(const std::string& content, const char* ms) { std::string generate_ac_msg_gen_case(const std::string& content, const char* ms) {
std::string result; std::string result = ms;
uint64_t N = content.size(); uint64_t N = content.size();
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
result += (char)(uint8_t)((N & 0xff00000000000000) >> 56); result += (char)(uint8_t)((N & 0xff00000000000000) >> 56);

View File

@ -100,14 +100,14 @@ namespace een9 {
assert(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++) {
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(parser.status == 1, "Incorrect request"); // todo: do the same thing everywhere else
ASSERT_on_iret(ret, "recv"); ASSERT_on_iret(ret, "recv");
assert(parser.status == 1);
return res; return res;
} }
@ -130,27 +130,33 @@ namespace een9 {
assert(pctx.status == 0); assert(pctx.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 (pctx.feedCharacter(buf[i]) > 0) if (pctx.feedCharacter(buf[i]) != 0)
break; break;
} }
if (pctx.status > 0) if (pctx.status != 0)
break; break;
} }
ASSERT(pctx.status == 1, "Incorrect request");
ASSERT_on_iret(ret, "recv"); ASSERT_on_iret(ret, "recv");
assert(pctx.status == 1);
return pctx.body; 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) { if (task.conn_info.type == 0) {
printf("%d::Got http reuest\n", wte.id);
ClientRequest client_request = process_http_connection_input(task.fd(), task.s_tips, wte); 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) { } 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); 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_content = wte.wtec.guest_core_admin_control(task, admin_request, wte.id);
std::string server_response = generate_admin_control_response(server_response_content); std::string server_response = generate_admin_control_response(server_response_content);
process_connection_output(task.fd(), server_response); process_connection_output(task.fd(), server_response);
printf("%d::Admin-cmd response has been sent\n", wte.id);
} }
} }

View File

@ -254,16 +254,12 @@ namespace een9 {
} }
void bind_to_socket_address(int sockfd, const SocketAddress &addr) { void bind_to_socket_address(int sockfd, const SocketAddress &addr) {
int ret; sa_family_t f = addr.v.gen.sa_family;
if (addr.v.gen.sa_family == AF_INET) { if (f == AF_INET || f == AF_INET6 || f == AF_UNIX) {
ret = bind(sockfd, (const sockaddr*)&addr.v.sin, addr.addrLen); int ret = bind(sockfd, &addr.v.gen, addr.addrLen);
} else if (addr.v.gen.sa_family == AF_INET6) { ASSERT_on_iret(ret, "binding socket");
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 } else
THROW("binding socket to address of unsupported domain"); 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) { void get_peer_name_as_socket_address(int sockfd, SocketAddress &res) {
@ -273,4 +269,9 @@ namespace een9 {
assert(willbecome <= sizeof(res.v)); assert(willbecome <= sizeof(res.v));
res.addrLen = willbecome; 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

@ -32,8 +32,8 @@ namespace een9 {
void* opaque = NULL; void* opaque = NULL;
SocketAddressParser(); SocketAddressParser();
SocketAddressParser(const SocketAddressParser&) = default; SocketAddressParser(const SocketAddressParser&) = delete;
SocketAddressParser& operator=(const SocketAddressParser&) = default; SocketAddressParser& operator=(const SocketAddressParser&) = delete;
~SocketAddressParser(); ~SocketAddressParser();
}; };
@ -46,6 +46,8 @@ namespace een9 {
/* Throws ServerError on error */ /* Throws ServerError on error */
void get_peer_name_as_socket_address(int sockfd, SocketAddress& res); void get_peer_name_as_socket_address(int sockfd, SocketAddress& res);
void connect_to_socket_address(int sockfd, const SocketAddress& targ);
} }
#endif #endif

View File

@ -34,6 +34,7 @@ void test_dcs(const std::string& test, const std::string& need, SocketAddressPar
int main() { int main() {
SocketAddressParser parser; SocketAddressParser parser;
test("127:0:0:1:1026", false, parser);
test("[12::12:0:0:0]:600", true, parser); test("[12::12:0:0:0]:600", true, parser);
test("[12::12:0:FFFF:0]:600", true, parser); test("[12::12:0:FFFF:0]:600", true, parser);
test("[12::11:1]:600", true, parser); test("[12::11:1]:600", true, parser);

View File

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

@ -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,14 +45,14 @@ 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("%ld | ", sqlite3_column_int64(stmt_obj, i)); printf("%lld | ", 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 %s | ", sz); printf("Blob of size %lu | ", sz);
} else if (types[i] == SQLITE_NULL) { } else if (types[i] == SQLITE_NULL) {
printf("NULL | "); printf("NULL | ");
} else { } else {

View File

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

View File

@ -39,7 +39,7 @@ void run_website(const json::JSON& config) {
/* 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 */
een9::uptr<nytl::Templater> templater; een9::uptr<nytl::Templater> templater;
}; };
std::vector<WorkerGuestData> worker_guest_data; std::vector<WorkerGuestData> worker_guest_data(slave_number);
for (int i = 0; i < slave_number; i++) { for (int i = 0; i < slave_number; i++) {
worker_guest_data[i].templater = std::make_unique<nytl::Templater>( worker_guest_data[i].templater = std::make_unique<nytl::Templater>(
nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}});