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:
parent
4d18d13a93
commit
6be78c1510
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ namespace een9 {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
body.reserve(b_sz);
|
body.reserve(b_sz);
|
||||||
} else if (body.size() < b_sz) {
|
|
||||||
body += ch;
|
|
||||||
} else {
|
} else {
|
||||||
|
body += ch;
|
||||||
|
if (body.size() >= b_sz)
|
||||||
status = 1;
|
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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
81
src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp
Normal file
81
src/web_chat/iu9_ca_web_chat_admin_cli/cli.cpp
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -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 {
|
@ -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;
|
@ -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"}});
|
Loading…
Reference in New Issue
Block a user