From 6be78c15105dc9285b2318161ba52430619360c2 Mon Sep 17 00:00:00 2001 From: Andreev Gregory Date: Tue, 20 Aug 2024 00:07:17 +0300 Subject: [PATCH] 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)) --- building/main.cpp | 16 +++- .../engine_engine_number_9/admin_control.cpp | 8 +- .../running_mainloop.cpp | 18 +++-- .../engine_engine_number_9/socket_address.cpp | 17 ++-- .../engine_engine_number_9/socket_address.h | 6 +- .../misc_tests/sockaddr_parse_test.cpp | 1 + .../iu9_ca_web_chat_admin_cli/cli.cpp | 81 +++++++++++++++++++ .../{ => iu9_ca_web_chat_service}/actions.h | 0 .../{ => iu9_ca_web_chat_service}/find_db.cpp | 0 .../{ => iu9_ca_web_chat_service}/find_db.h | 0 .../initialize.cpp | 6 +- .../{ => iu9_ca_web_chat_service}/main.cpp | 11 +-- .../{ => iu9_ca_web_chat_service}/run.cpp | 2 +- .../str_fields_check.cpp | 0 .../str_fields_check.h | 0 15 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp rename src/web_chat/{ => iu9_ca_web_chat_service}/actions.h (100%) rename src/web_chat/{ => iu9_ca_web_chat_service}/find_db.cpp (100%) rename src/web_chat/{ => iu9_ca_web_chat_service}/find_db.h (100%) rename src/web_chat/{ => iu9_ca_web_chat_service}/initialize.cpp (96%) rename src/web_chat/{ => iu9_ca_web_chat_service}/main.cpp (90%) rename src/web_chat/{ => iu9_ca_web_chat_service}/run.cpp (98%) rename src/web_chat/{ => iu9_ca_web_chat_service}/str_fields_check.cpp (100%) rename src/web_chat/{ => iu9_ca_web_chat_service}/str_fields_check.h (100%) diff --git a/building/main.cpp b/building/main.cpp index fd1f100..23ac7ff 100644 --- a/building/main.cpp +++ b/building/main.cpp @@ -79,6 +79,7 @@ struct CAWebChat { "running_mainloop.cpp", "form_data_structure/urlencoded_query.cpp", "socket_address.cpp", + "admin_control.cpp", }; for (std::string& u: T.units) u = "http_server/engine_engine_number_9/" + u; @@ -143,11 +144,24 @@ struct CAWebChat { "find_db.cpp", }; 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.installation_dir = ""; 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, cmd.project_root, cmd.installation_root); } diff --git a/src/http_server/engine_engine_number_9/admin_control.cpp b/src/http_server/engine_engine_number_9/admin_control.cpp index 1577fb8..3876084 100644 --- a/src/http_server/engine_engine_number_9/admin_control.cpp +++ b/src/http_server/engine_engine_number_9/admin_control.cpp @@ -27,10 +27,10 @@ namespace een9 { return status; } body.reserve(b_sz); - } else if (body.size() < b_sz) { - body += ch; } else { - status = 1; + body += ch; + if (body.size() >= b_sz) + status = 1; } return status; } @@ -42,7 +42,7 @@ namespace een9 { } 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(); for (int i = 0; i < 8; i++) { result += (char)(uint8_t)((N & 0xff00000000000000) >> 56); diff --git a/src/http_server/engine_engine_number_9/running_mainloop.cpp b/src/http_server/engine_engine_number_9/running_mainloop.cpp index 1b5b626..8de860f 100644 --- a/src/http_server/engine_engine_number_9/running_mainloop.cpp +++ b/src/http_server/engine_engine_number_9/running_mainloop.cpp @@ -100,14 +100,14 @@ namespace een9 { assert(parser.status == 0); while ((ret = (int)recv(fd, buf, 2048, 0)) > 0) { for (size_t i = 0; i < ret; i++) { - if (parser.feedCharacter(buf[i]) > 0) + if (parser.feedCharacter(buf[i]) != 0) break; } - if (parser.status > 0) + if (parser.status != 0) break; } + ASSERT(parser.status == 1, "Incorrect request"); // todo: do the same thing everywhere else ASSERT_on_iret(ret, "recv"); - assert(parser.status == 1); return res; } @@ -130,27 +130,33 @@ namespace een9 { 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) + if (pctx.feedCharacter(buf[i]) != 0) break; } - if (pctx.status > 0) + if (pctx.status != 0) break; } + ASSERT(pctx.status == 1, "Incorrect request"); ASSERT_on_iret(ret, "recv"); - assert(pctx.status == 1); return pctx.body; } void process_connection(const SlaveTask& task, WorkersEnv& wte) { 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); + printf("%d::Http request has been read\n", wte.id); std::string server_response = wte.wtec.guest_core(task, client_request, wte.id); 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); } } diff --git a/src/http_server/engine_engine_number_9/socket_address.cpp b/src/http_server/engine_engine_number_9/socket_address.cpp index eb65dfd..b9e8c7a 100644 --- a/src/http_server/engine_engine_number_9/socket_address.cpp +++ b/src/http_server/engine_engine_number_9/socket_address.cpp @@ -254,16 +254,12 @@ namespace een9 { } 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); + 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"); - ASSERT_on_iret(ret, "binding socket"); } void get_peer_name_as_socket_address(int sockfd, SocketAddress &res) { @@ -273,4 +269,9 @@ namespace een9 { 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"); + } } diff --git a/src/http_server/engine_engine_number_9/socket_address.h b/src/http_server/engine_engine_number_9/socket_address.h index 50511df..e4063ef 100644 --- a/src/http_server/engine_engine_number_9/socket_address.h +++ b/src/http_server/engine_engine_number_9/socket_address.h @@ -32,8 +32,8 @@ namespace een9 { void* opaque = NULL; SocketAddressParser(); - SocketAddressParser(const SocketAddressParser&) = default; - SocketAddressParser& operator=(const SocketAddressParser&) = default; + SocketAddressParser(const SocketAddressParser&) = delete; + SocketAddressParser& operator=(const SocketAddressParser&) = delete; ~SocketAddressParser(); }; @@ -46,6 +46,8 @@ namespace een9 { /* 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 diff --git a/src/http_server/misc_tests/sockaddr_parse_test.cpp b/src/http_server/misc_tests/sockaddr_parse_test.cpp index 39a44a2..618ce5b 100644 --- a/src/http_server/misc_tests/sockaddr_parse_test.cpp +++ b/src/http_server/misc_tests/sockaddr_parse_test.cpp @@ -34,6 +34,7 @@ void test_dcs(const std::string& test, const std::string& need, SocketAddressPar 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); diff --git a/src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp b/src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp new file mode 100644 index 0000000..fb520f8 --- /dev/null +++ b/src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +/* This so called 'een9::admin-control' protocol is very simple: + * Admin sends request to server: + * <8 byte field: size of body> + * Server reads it to the end and sents response to admin: + * <8 byte field: size of body> + * 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
[ ...]\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()); + } +} \ No newline at end of file diff --git a/src/web_chat/actions.h b/src/web_chat/iu9_ca_web_chat_service/actions.h similarity index 100% rename from src/web_chat/actions.h rename to src/web_chat/iu9_ca_web_chat_service/actions.h diff --git a/src/web_chat/find_db.cpp b/src/web_chat/iu9_ca_web_chat_service/find_db.cpp similarity index 100% rename from src/web_chat/find_db.cpp rename to src/web_chat/iu9_ca_web_chat_service/find_db.cpp diff --git a/src/web_chat/find_db.h b/src/web_chat/iu9_ca_web_chat_service/find_db.h similarity index 100% rename from src/web_chat/find_db.h rename to src/web_chat/iu9_ca_web_chat_service/find_db.h diff --git a/src/web_chat/initialize.cpp b/src/web_chat/iu9_ca_web_chat_service/initialize.cpp similarity index 96% rename from src/web_chat/initialize.cpp rename to src/web_chat/iu9_ca_web_chat_service/initialize.cpp index 80e90ba..c224c15 100644 --- a/src/web_chat/initialize.cpp +++ b/src/web_chat/iu9_ca_web_chat_service/initialize.cpp @@ -3,7 +3,7 @@ #include "str_fields_check.h" #include #include -#include +#include "find_db.h" #include #include @@ -45,14 +45,14 @@ void sqlite_single_statement(sqlite3* db_hand, const std::string& req_statement) printf("Values: | "); for (int i = 0; i < cc; i++) { 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) { printf("%lf | ", sqlite3_column_double(stmt_obj, i)); } else if (types[i] == SQLITE_BLOB) { const void* blob = sqlite3_column_blob(stmt_obj, i); een9_ASSERT(sqlite3_errcode(db_hand) == SQLITE_OK, "oom in sqlite3_column_blob"); 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) { printf("NULL | "); } else { diff --git a/src/web_chat/main.cpp b/src/web_chat/iu9_ca_web_chat_service/main.cpp similarity index 90% rename from src/web_chat/main.cpp rename to src/web_chat/iu9_ca_web_chat_service/main.cpp index ad794a1..a067dfa 100644 --- a/src/web_chat/main.cpp +++ b/src/web_chat/iu9_ca_web_chat_service/main.cpp @@ -5,20 +5,21 @@ #include "actions.h" #include -void usage(char** argv) { - printf("Usage: %s \n", argv[0]); +void usage(char* argv0) { + printf("Usage: %s \n", argv0); exit(1); } int main(int argc, char** argv){ try { - een9_ASSERT_pl(argc > 0); + if (argc < 1) + return 111; if (argc != 1 + 2) - usage(argv); + usage(argv[0]); std::string config_file = argv[1]; if (!een9::isRegularFile(config_file) || !een9::endsWith(config_file, ".json")) { printf("\"%s\" is not a json file\n", argv[1]); - usage(argv); + usage(argv[0]); } std::string cmd = argv[2]; std::string config_text; diff --git a/src/web_chat/run.cpp b/src/web_chat/iu9_ca_web_chat_service/run.cpp similarity index 98% rename from src/web_chat/run.cpp rename to src/web_chat/iu9_ca_web_chat_service/run.cpp index 87a558a..f132e5b 100644 --- a/src/web_chat/run.cpp +++ b/src/web_chat/iu9_ca_web_chat_service/run.cpp @@ -39,7 +39,7 @@ void run_website(const json::JSON& config) { /* Because templaters use libjsonincpp, they can't be READ by two thread simultaneously */ een9::uptr templater; }; - std::vector worker_guest_data; + std::vector worker_guest_data(slave_number); for (int i = 0; i < slave_number; i++) { worker_guest_data[i].templater = std::make_unique( nytl::TemplaterSettings{nytl::TemplaterDetourRules{assets_dir + "/HypertextPages"}}); diff --git a/src/web_chat/str_fields_check.cpp b/src/web_chat/iu9_ca_web_chat_service/str_fields_check.cpp similarity index 100% rename from src/web_chat/str_fields_check.cpp rename to src/web_chat/iu9_ca_web_chat_service/str_fields_check.cpp diff --git a/src/web_chat/str_fields_check.h b/src/web_chat/iu9_ca_web_chat_service/str_fields_check.h similarity index 100% rename from src/web_chat/str_fields_check.h rename to src/web_chat/iu9_ca_web_chat_service/str_fields_check.h