From 41d2f5a44784a9f94f2e543df47d9e007492e473 Mon Sep 17 00:00:00 2001 From: Dulana Peiris Date: Tue, 10 Oct 2023 12:28:07 +0530 Subject: [PATCH 01/23] Added basic shell command I/O functionality --- src/msg/bson/usrmsg_bson.cpp | 33 +++++++++++++++++++++++++++++++++ src/msg/bson/usrmsg_bson.hpp | 2 ++ src/msg/json/usrmsg_json.cpp | 32 ++++++++++++++++++++++++++++++++ src/msg/json/usrmsg_json.hpp | 2 ++ src/msg/usrmsg_common.hpp | 2 ++ src/msg/usrmsg_parser.cpp | 8 ++++++++ src/msg/usrmsg_parser.hpp | 2 ++ src/usr/usr.cpp | 16 ++++++++++++++++ 8 files changed, 97 insertions(+) diff --git a/src/msg/bson/usrmsg_bson.cpp b/src/msg/bson/usrmsg_bson.cpp index 7b7e26df..7f8eb79c 100644 --- a/src/msg/bson/usrmsg_bson.cpp +++ b/src/msg/bson/usrmsg_bson.cpp @@ -497,6 +497,39 @@ namespace msg::usrmsg::bson return 0; } + /** + * Extracts a contract shell input message sent by user. + * + * @param extracted_content The content to be passed to the contract, extracted from the message. + * @param d The bson document holding the shell input message. + * Accepted signed input container format: + * { + * "type": "contract_shell_input", + * "id": "", + * "content": + * } + * @return 0 on successful extraction. -1 for failure. + */ + int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d) + { + if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) + { + LOG_DEBUG << "Shell input 'id' field missing or invalid."; + return -1; + } + + if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is_byte_string_view()) + { + LOG_DEBUG << "Shell input 'content' field missing or invalid."; + return -1; + } + + extracted_id = d[msg::usrmsg::FLD_ID].as(); + const jsoncons::byte_string_view &bsv = d[msg::usrmsg::FLD_CONTENT].as_byte_string_view(); + extracted_content = std::string_view(reinterpret_cast(bsv.data()), bsv.size()); + return 0; + } + /** * Extracts a signed input container message sent by user. * diff --git a/src/msg/bson/usrmsg_bson.hpp b/src/msg/bson/usrmsg_bson.hpp index e5ac95dd..9a511f36 100644 --- a/src/msg/bson/usrmsg_bson.hpp +++ b/src/msg/bson/usrmsg_bson.hpp @@ -43,6 +43,8 @@ namespace msg::usrmsg::bson int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); + int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); + int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::ojson &d); diff --git a/src/msg/json/usrmsg_json.cpp b/src/msg/json/usrmsg_json.cpp index a4d5b7af..a867e99d 100644 --- a/src/msg/json/usrmsg_json.cpp +++ b/src/msg/json/usrmsg_json.cpp @@ -872,6 +872,38 @@ namespace msg::usrmsg::json return 0; } + /** + * Extracts a contract shell input message sent by user. + * + * @param extracted_content The content to be passed to the contract, extracted from the message. + * @param d The json document holding the shell input message. + * Accepted signed input container format: + * { + * "type": "contract_shell_input", + * "id": "", + * "content": "" + * } + * @return 0 on successful extraction. -1 for failure. + */ + int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d) + { + if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) + { + LOG_DEBUG << "Shell input 'id' field missing or invalid."; + return -1; + } + + if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is()) + { + LOG_DEBUG << "Shell input 'content' field missing or invalid."; + return -1; + } + + extracted_id = d[msg::usrmsg::FLD_ID].as(); + extracted_content = d[msg::usrmsg::FLD_CONTENT].as(); + return 0; + } + /** * Extracts a signed input container message sent by user. * diff --git a/src/msg/json/usrmsg_json.hpp b/src/msg/json/usrmsg_json.hpp index f959b8be..eef0e06c 100644 --- a/src/msg/json/usrmsg_json.hpp +++ b/src/msg/json/usrmsg_json.hpp @@ -47,6 +47,8 @@ namespace msg::usrmsg::json int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); + int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); + int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::json &d); diff --git a/src/msg/usrmsg_common.hpp b/src/msg/usrmsg_common.hpp index 3a6ca510..d8682e49 100644 --- a/src/msg/usrmsg_common.hpp +++ b/src/msg/usrmsg_common.hpp @@ -80,6 +80,8 @@ namespace msg::usrmsg constexpr const char *MSGTYPE_SERVER_CHALLENGE_RESPONSE = "server_challenge_response"; constexpr const char *MSGTYPE_CONTRACT_READ_REQUEST = "contract_read_request"; constexpr const char *MSGTYPE_CONTRACT_READ_RESPONSE = "contract_read_response"; + constexpr const char *MSGTYPE_CONTRACT_SHELL_INPUT = "contract_shell_input"; + constexpr const char *MSGTYPE_CONTRACT_SHELL_OUTPUT = "contract_shell_output"; constexpr const char *MSGTYPE_CONTRACT_INPUT = "contract_input"; constexpr const char *MSGTYPE_CONTRACT_INPUT_STATUS = "contract_input_status"; constexpr const char *MSGTYPE_CONTRACT_OUTPUT = "contract_output"; diff --git a/src/msg/usrmsg_parser.cpp b/src/msg/usrmsg_parser.cpp index 48a0b8ba..d87822f4 100644 --- a/src/msg/usrmsg_parser.cpp +++ b/src/msg/usrmsg_parser.cpp @@ -121,6 +121,14 @@ namespace msg::usrmsg return busrmsg::extract_read_request(extracted_id, extracted_content, bdoc); } + int usrmsg_parser::extract_shell_input(std::string &extracted_id, std::string &extracted_content) const + { + if (protocol == util::PROTOCOL::JSON) + return jusrmsg::extract_shell_input(extracted_id, extracted_content, jdoc); + else + return busrmsg::extract_shell_input(extracted_id, extracted_content, bdoc); + } + int usrmsg_parser::extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const { if (protocol == util::PROTOCOL::JSON) diff --git a/src/msg/usrmsg_parser.hpp b/src/msg/usrmsg_parser.hpp index 51ca0af9..8d721416 100644 --- a/src/msg/usrmsg_parser.hpp +++ b/src/msg/usrmsg_parser.hpp @@ -49,6 +49,8 @@ namespace msg::usrmsg int extract_read_request(std::string &extracted_id, std::string &extracted_content) const; + int extract_shell_input(std::string &extracted_id, std::string &extracted_content) const; + int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const; int extract_input_container(std::string &input, uint64_t &nonce, diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 061f48e8..c7d672fb 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -272,6 +272,22 @@ namespace usr user.session.send(resp); return 0; } + else if (msg_type == msg::usrmsg::MSGTYPE_CONTRACT_SHELL_INPUT) + { + std::string id, content; + if (parser.extract_shell_input(id, content) != -1){ + LOG_INFO << "Received Shell Input."; + LOG_INFO << "User PubKey:" << user.pubkey; + LOG_INFO << "ID:" << id; + LOG_INFO << "Content:" << content; + return 0; + } + else + { + send_input_status(parser, user.session, msg::usrmsg::STATUS_REJECTED, msg::usrmsg::REASON_BAD_MSG_FORMAT, ""); + return -1; + } + } else { LOG_DEBUG << "Invalid user message type: " << msg_type; From 5bdda39a7b9f041f8588a1b1ff6a6867fa0ba3e4 Mon Sep 17 00:00:00 2001 From: supunvindula Date: Thu, 12 Oct 2023 13:03:50 +0530 Subject: [PATCH 02/23] added basic hpsh filepath and structure --- CMakeLists.txt | 4 ++-- src/conf.cpp | 8 +++++--- src/conf.hpp | 1 + src/usr/usr.cpp | 7 +++++++ test/bin/hpsh | Bin 0 -> 17320 bytes 5 files changed, 15 insertions(+), 5 deletions(-) create mode 100755 test/bin/hpsh diff --git a/CMakeLists.txt b/CMakeLists.txt index 91e2711a..fec3fbf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ target_link_libraries(hpcore add_custom_command(TARGET hpcore POST_BUILD # COMMAND strip ./build/hpcore - COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./build/ + COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ ) target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) @@ -87,7 +87,7 @@ target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) add_custom_target(docker COMMAND mkdir -p ./test/local-cluster/bin COMMAND cp ./build/hpcore ./test/local-cluster/bin/ - COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/local-cluster/bin/ + COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./test/local-cluster/bin/ COMMAND docker build -t hpcore:latest -t hpcore:0.6.4 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/ ) set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/src/conf.cpp b/src/conf.cpp index 47e6e696..68d1dd01 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -242,6 +242,7 @@ namespace conf ctx.hpws_exe_path = ctx.exe_dir + "/" + "hpws"; ctx.hpfs_exe_path = ctx.exe_dir + "/" + "hpfs"; + ctx.hpsh_exe_path = ctx.exe_dir + "/" + "hpsh"; ctx.contract_dir = basedir; ctx.config_dir = basedir + "/cfg"; @@ -709,7 +710,7 @@ namespace conf */ int validate_contract_dir_paths() { - const std::string paths[8] = { + const std::string paths[9] = { ctx.contract_dir, ctx.config_file, ctx.contract_hpfs_dir, @@ -717,7 +718,8 @@ namespace conf ctx.tls_key_file, ctx.tls_cert_file, ctx.hpfs_exe_path, - ctx.hpws_exe_path}; + ctx.hpws_exe_path, + ctx.hpsh_exe_path}; for (const std::string &path : paths) { @@ -729,7 +731,7 @@ namespace conf << "openssl req -newkey rsa:2048 -new -nodes -x509 -days 365 -keyout tlskey.pem -out tlscert.pem\n" << "and add it to " + ctx.config_dir << std::endl; } - else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path) + else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path || path == ctx.hpsh_exe_path) { std::cerr << path << " binary does not exist.\n"; } diff --git a/src/conf.hpp b/src/conf.hpp index 242d8d43..a29a6294 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -263,6 +263,7 @@ namespace conf std::string exe_dir; // HotPocket executable dir. std::string hpws_exe_path; // hpws executable file path. std::string hpfs_exe_path; // hpfs executable file path. + std::string hpsh_exe_path; // hpsh executable path file std::string contract_dir; // Contract base directory full path. std::string contract_hpfs_dir; // Contract hpfs metadata dir (The location of hpfs log file). diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index c7d672fb..5a562926 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -274,12 +274,19 @@ namespace usr } else if (msg_type == msg::usrmsg::MSGTYPE_CONTRACT_SHELL_INPUT) { + // char const **argv_pass = NULL; + // argv_pass[0] = "./" + conf::ctx.hpsh_exe_path.data(); + // // argv_pass[1] = conf::ctx.hpsh_exe_path.data(); + + char *args[] = { conf::ctx.hpsh_exe_path.data(), NULL }; + std::string id, content; if (parser.extract_shell_input(id, content) != -1){ LOG_INFO << "Received Shell Input."; LOG_INFO << "User PubKey:" << user.pubkey; LOG_INFO << "ID:" << id; LOG_INFO << "Content:" << content; + execv(conf::ctx.hpsh_exe_path.data(),args); return 0; } else diff --git a/test/bin/hpsh b/test/bin/hpsh new file mode 100755 index 0000000000000000000000000000000000000000..d74fbc228ba26e50cf538d7f21807acfa3116a28 GIT binary patch literal 17320 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 TrM**S{a0?WB-XnWTut#WXMCs9 literal 0 HcmV?d00001 From 6c8ca8c409454e2f1c44c1fc02f55995fe84f0c9 Mon Sep 17 00:00:00 2001 From: supunvindula Date: Fri, 13 Oct 2023 11:28:06 +0530 Subject: [PATCH 03/23] make execv run inside the child process --- src/usr/usr.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 5a562926..d1af77a5 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -204,7 +204,7 @@ namespace usr const int nonce_status = nonce_map.check(user.pubkey, nonce, sig, max_ledger_seq_no, true); if (nonce_status == 0) { - //Add to the submitted input list. + // Add to the submitted input list. user.submitted_inputs.push_back(submitted_user_input{ std::move(input_container), std::move(sig), @@ -278,15 +278,33 @@ namespace usr // argv_pass[0] = "./" + conf::ctx.hpsh_exe_path.data(); // // argv_pass[1] = conf::ctx.hpsh_exe_path.data(); - char *args[] = { conf::ctx.hpsh_exe_path.data(), NULL }; + std::string id, content; - if (parser.extract_shell_input(id, content) != -1){ + if (parser.extract_shell_input(id, content) != -1) + { LOG_INFO << "Received Shell Input."; LOG_INFO << "User PubKey:" << user.pubkey; LOG_INFO << "ID:" << id; LOG_INFO << "Content:" << content; - execv(conf::ctx.hpsh_exe_path.data(),args); + int pid = fork(); + if (pid == 0) + { + // int socket[2] = {-1, -1}; + // // Create the socket of given type. + // if (socket(AF_UNIX, SOCK_STREAM, 0, socket) == -1) + // { + // LOG_ERROR << errno << ": Error when creating domain socket."; + // return -1; + // } + // char *args[] = {conf::ctx.hpsh_exe_path.data(), socket, NULL}; + char *args[] = {conf::ctx.hpsh_exe_path.data() , NULL}; + if (execv(conf::ctx.hpsh_exe_path.data(), args) == -1) + { + perror("execv inside hpsh"); + } + } + return 0; } else @@ -371,7 +389,7 @@ namespace usr /** * Adds the user denoted by specified session id and public key to the global authed user list. * This should get called after the challenge handshake is verified. - * + * * @param session User socket session. * @param user_pubkey_hex User's hex public key. * @param protocol_code Messaging protocol used by user. @@ -420,7 +438,7 @@ namespace usr /** * Removes the specified public key from the global user list. * This must get called when an authenticated user disconnects from HP. - * + * * @param pubkey User pubkey. * @return 0 on successful removals. -1 on failure. */ From ed5186759be7652f6942d3a35f4ed6553a528bc6 Mon Sep 17 00:00:00 2001 From: Dulana Peiris Date: Tue, 17 Oct 2023 14:51:02 +0530 Subject: [PATCH 04/23] Added one way pipe communication and argument passing --- CMakeLists.txt | 2 +- src/usr/usr.cpp | 89 +++++++++++++++++++++++++++++++++++------------- test/bin/hpsh | Bin 17320 -> 18128 bytes 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fec3fbf3..0319c611 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ target_link_libraries(hpcore add_custom_command(TARGET hpcore POST_BUILD # COMMAND strip ./build/hpcore - COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ + COMMAND rm -f ./build/hpws ./build/hpfs ./build/hpsh && cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ ) target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index d1af77a5..c661600e 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -274,35 +274,78 @@ namespace usr } else if (msg_type == msg::usrmsg::MSGTYPE_CONTRACT_SHELL_INPUT) { - // char const **argv_pass = NULL; - // argv_pass[0] = "./" + conf::ctx.hpsh_exe_path.data(); - // // argv_pass[1] = conf::ctx.hpsh_exe_path.data(); - - - std::string id, content; if (parser.extract_shell_input(id, content) != -1) { - LOG_INFO << "Received Shell Input."; - LOG_INFO << "User PubKey:" << user.pubkey; - LOG_INFO << "ID:" << id; - LOG_INFO << "Content:" << content; - int pid = fork(); - if (pid == 0) + + int fd[2]; + if (pipe(fd) == -1) { - // int socket[2] = {-1, -1}; - // // Create the socket of given type. - // if (socket(AF_UNIX, SOCK_STREAM, 0, socket) == -1) - // { - // LOG_ERROR << errno << ": Error when creating domain socket."; - // return -1; - // } - // char *args[] = {conf::ctx.hpsh_exe_path.data(), socket, NULL}; - char *args[] = {conf::ctx.hpsh_exe_path.data() , NULL}; - if (execv(conf::ctx.hpsh_exe_path.data(), args) == -1) + perror("Error when creating pipe"); + return 1; + } + pid_t pid = -1; + + pid = fork(); + + if (pid < 0) + { + perror("Error occurred when forking"); + return -1; + } + else if (pid != 0) + { + // parent process + close(fd[0]); + LOG_INFO << "parent: Received Shell Input.\n"; + LOG_INFO << "parent: User PubKey:" << user.pubkey << "\n"; + LOG_INFO << "parent: ID:" << id << "\n"; + LOG_INFO << "parent: Content:" << content << "\n"; + LOG_INFO << "parent: writing content to pipe\n"; + ssize_t bytes_written = write(fd[1], content.c_str(), content.size()); + if (bytes_written == -1) { - perror("execv inside hpsh"); + perror("write to pipe failed"); + // handle the error appropriately } + + LOG_INFO << "parent: closing pipe\n"; + close(fd[1]); + LOG_INFO << "parent: closed\n"; + } + else + { + // child process + close(fd[1]); + std::string receivedContent; + LOG_INFO << "child: reading from pipe:\n"; + const int BUFFER_SIZE = 1024; + char buffer[BUFFER_SIZE]; + + ssize_t bytes_read = read(fd[0], buffer, BUFFER_SIZE); + if (bytes_read == -1) + { + perror("read from pipe failed"); + // handle the error appropriately + } + else + { + buffer[bytes_read] = '\0'; // Null-terminate the string + receivedContent = buffer; + LOG_INFO << "child: Content:" << receivedContent << "\n"; + } + + receivedContent = "\"" + receivedContent + "\""; + + char *passed_command = new char[receivedContent.length() + 1]; + std::strcpy(passed_command, receivedContent.c_str()); + + char *args[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), passed_command, NULL}; + if (execv(conf::ctx.hpsh_exe_path.c_str(), args) == -1) + { + perror("Error when executing HPSH"); + } + close(fd[0]); } return 0; diff --git a/test/bin/hpsh b/test/bin/hpsh index d74fbc228ba26e50cf538d7f21807acfa3116a28..70e195a73e3cb47c638c08f540cefa8f24722b48 100755 GIT binary patch literal 18128 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 W{tP59Ibo!`&G+GM+g+4x^M3(zpEQdA From 11a8d7abda5a9c2c3391c8e45d624a60718975cc Mon Sep 17 00:00:00 2001 From: supunvindula Date: Wed, 18 Oct 2023 08:12:29 +0530 Subject: [PATCH 05/23] did changes for unix socket and two way communication --- src/usr/usr.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index c661600e..aa141d26 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -278,31 +278,34 @@ namespace usr if (parser.extract_shell_input(id, content) != -1) { - int fd[2]; - if (pipe(fd) == -1) - { - perror("Error when creating pipe"); - return 1; - } + int p1[2] ; // 0,1 are hpcore to hphs + int p2[2] ; // 2,3 are hpsh to hpcore + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, p1)) + perror("could not create unix domain socket pair"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, p2)) + perror("could not create unix domain socket pair"); + pid_t pid = -1; pid = fork(); - if (pid < 0) + if (pid == -1) { perror("Error occurred when forking"); return -1; } - else if (pid != 0) + if (pid != 0) { // parent process - close(fd[0]); + close(p1[0]); + close(p2[1]); LOG_INFO << "parent: Received Shell Input.\n"; LOG_INFO << "parent: User PubKey:" << user.pubkey << "\n"; LOG_INFO << "parent: ID:" << id << "\n"; LOG_INFO << "parent: Content:" << content << "\n"; LOG_INFO << "parent: writing content to pipe\n"; - ssize_t bytes_written = write(fd[1], content.c_str(), content.size()); + ssize_t bytes_written = write(p1[1], content.c_str(), content.size()); if (bytes_written == -1) { perror("write to pipe failed"); @@ -310,19 +313,21 @@ namespace usr } LOG_INFO << "parent: closing pipe\n"; - close(fd[1]); + close(p1[1]); + close(p2[0]); LOG_INFO << "parent: closed\n"; } else { // child process - close(fd[1]); + close(p1[1]); + close(p2[0]); std::string receivedContent; LOG_INFO << "child: reading from pipe:\n"; const int BUFFER_SIZE = 1024; char buffer[BUFFER_SIZE]; - ssize_t bytes_read = read(fd[0], buffer, BUFFER_SIZE); + ssize_t bytes_read = read(p1[0], buffer, BUFFER_SIZE); if (bytes_read == -1) { perror("read from pipe failed"); @@ -345,7 +350,8 @@ namespace usr { perror("Error when executing HPSH"); } - close(fd[0]); + close(p1[0]); + close(p2[1]); } return 0; From b1acd8e89728f2aee977ddccd9dbfb23ed45712b Mon Sep 17 00:00:00 2001 From: supunvindula Date: Thu, 19 Oct 2023 10:49:35 +0530 Subject: [PATCH 06/23] attach sockets as an arguments to the hpsh --- src/usr/usr.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index aa141d26..8a514ee2 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -311,6 +311,11 @@ namespace usr perror("write to pipe failed"); // handle the error appropriately } + char buffer[1024] = {0}; + if(read(p2[0], &buffer, sizeof(buffer))==-1){ + perror("Error in reading to the fd"); + } + std::cout <<"bufferread"<< buffer << std::endl; LOG_INFO << "parent: closing pipe\n"; close(p1[1]); @@ -319,9 +324,14 @@ namespace usr } else { + // child process close(p1[1]); close(p2[0]); + char read_end[16]; + snprintf(read_end, sizeof(read_end), "%d", p1[0]); + char write_end[16]; + snprintf(write_end, sizeof(write_end), "%d", p2[1]); std::string receivedContent; LOG_INFO << "child: reading from pipe:\n"; const int BUFFER_SIZE = 1024; @@ -345,7 +355,7 @@ namespace usr char *passed_command = new char[receivedContent.length() + 1]; std::strcpy(passed_command, receivedContent.c_str()); - char *args[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), passed_command, NULL}; + char *args[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), passed_command,read_end, write_end, NULL}; if (execv(conf::ctx.hpsh_exe_path.c_str(), args) == -1) { perror("Error when executing HPSH"); From 172195f1f63f71db27ee40f9408f2d2a4b46f1fe Mon Sep 17 00:00:00 2001 From: supunvindula Date: Thu, 19 Oct 2023 10:50:06 +0530 Subject: [PATCH 07/23] new build file --- test/bin/hpsh | Bin 18128 -> 18496 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/bin/hpsh b/test/bin/hpsh index 70e195a73e3cb47c638c08f540cefa8f24722b48..cffa8ef387521885579789b3568c67f9f81e85db 100755 GIT binary patch delta 4387 zcmZ`+eQ;FO6~A{slFcR|yPFL!8w}Y*5+ITdyW|6e47*7-eT)IpT9l#1glR$v1q1m| z9ATo3RM&Jd;n0dBwsb%X4r(AcFfwQm3*#RGX^}E@>cozAHe#oI1d0{sqs^$% zW(K?YG57hK&%V5TzkBAbyTQ9f z!k|R~)shP_b1p9-#CMDQtjOOL^0}5={-MB^fTMnkWiH>3xSUTB+;c+fGIFxg0*6ydV1MckS65qiPkSrd)YjSA(aF|!bp8zdwgN|M&!zzDdaA3tZ6jOL-O&!q zZNV(|y~ZWAbt_jk&+}FI0)F_7&GV>Po*=K$|iuP74+UQB;B)j+Q>2$CxPovi782WMUb_ zn&EDm;xV>?V2>q8bD+$wc&6&=BEOm-&4tw{^(06gK^@R?b3)XvY`iZ)+7i-%70I*& z{(Pg(ROFGROu+;`4p}^@34A#_By0j_y5d=xAT_qGuxx=)x{|prL284Ob_KSkXJl?k z;M(CI*ejgcczPj0ngRLg3LHY4-3i<&uoPR)id!&tAVKPYZ77u!M@q*Nq;7aCUE#{` zX!_HposJ@#shqLvTCo{Q9q(;eM}Ax%_iLIqa3gE_zt?35To}i=cu?+)<0%63I3}O2 zk6-(bw5K(Bef*0!b_zU7c&Ah8{iKYstb%&Rs4?{74@vlB5`H%czm=bocWJj!u_a5Gn)meIfbL9 z`E%@k zWS*c6IR0bI)o6I18aW%=Mymbc0kv<$ruN&^=!$)6v^PAWM$VDAfW(ICjk{E?bn6Wj zlLsTj!iJ(`AX?dBaQdyg9*8%6keGTS4z(X0Ive{tvLfOA1~=E>UJ%>^y|LIG5+CZ@ zc8Fzde+`}f;0n%7>pjXXEfosHx0D(;}z6;wWfqo-YYx<5P=Ir9PaGM0n7 z{o$hs>2!&u2zcOql41M*LYw~Zf%i#a z)3*_xz*=ZXaTLzRmfnFUvI`c9;r%_;8@WvEZ?H)FPK}(FnrZi>=dc)y5bpbE9bCws zIpYKka1U{!ISr*$edPg~&3@}FLRjPF?_ipH`oguotb*sr0k&40BB4hcqcvAb7z;hJ zByuUVVoBs?=!c=mofT@d>`P=n+&KHL+V_nucK+Mp4)xeEq^(G2 z+=3UqCDTXHjCKL5Po;B;&A`6`e-*2r%i)~2XnNCCO%pPbV{+r)jlYU~FNZ0G`HMfD zj^SlmMyhRqYDO9T9`vLbr_yo^L3oPe7pA(*lyINfte8*}FG9$^i2u|HSYJ5ZR5t-H zB2g#c&BBIRnA?@l-~B87XD2WhA%3sj~8-7mN@mBi#k#-e5QCo^J-1 z&*$_S0mo>W4Z-()1+Fn8%2D8@G+>9H`<9h4!x;BV2eFMR84j_)BQ)ihz9l?(xB$k| z7jXxy31q{F$pV|oSNg{cZ?8(PDb8SW7}RUfxdsiws6QL)sQ}yDs~*`Y-A2#N%*I9_ zqF8+l_re+mccWy%0Rh5IIeG%oY^Pc=jWb^4DRsQt@=) zW^|coqT*svI3;vG75TWx&9J6Q;ZIWT*@GUsaJ1#Li<1WJB0}e!$iESJ3LLIh{6(lw zp5z86x8fr{USNX;-yuc|PZhE<{n`T8t9*PP6jm$z9b$Pd8V%!QiPUD)_a#ZeG2a45 ztKBBW3YtI1#O6V0zQP}(+|x!KMVB`jmhuqlA*pGXVX;r3V*=%|QB)%L`lhW)#QZrwN zA=-|0{X5_9d!6?=*THR+-eTvUpC z1WnYDI5e3ewKzUy4$(|qO-QbKp-|BE=mBTfil zHEb!C%Z^?6#pxpzL*F{TXpeD{j5zxUJY{%bNf8FsTSv$U@ne%2$BG-?G}J(;v6Oxa z)F{%&A#4<3*jPGhEQLv9h;C8|pQ)6-%M4(LDMXu8ZXCG*wKi=k1xH?p?uK|?koq%w z^2RA_HNOrkEnfJhW$l0z36pi59WAZNWOuDpr`5Y7^J)>Po;Alnj6}fCp#Ds1jSXr( z%35z3GObo9c5DSI*c|xq+gQC1=PsX&@S&k-NeNV2T?5Cs*`C`+ux2DDx!k*K)XWlR z=3E3Ka~(@kymP0W5ED7axxTWU7J`j~;~JLiWXZ ztOcUToPh>let01#)zOT)#jL+%FrdswCLwTJq>ETmy32KA=MMO&l@B z?Lym|!*V(r$BLXbt!B`4yVorbnLfu|FF%v*wJ6ht6$jCryu}giovMAkRf5l4<-)}P zSc;Y`s|uk}--<4IF!}>_WXP#cdTsJh^aT`h`~IUSxgJGP-Zss`hN9|$Wa_{vIn_7T zBM%v?9#G8_xo}oa*Kfi#j5!W7w{7S)c;FNrh@fJfrbuJ*oQw)Nb)GeJB}?_TocbWw zisTz?SzbTH0;Ut^8^8f`rC=DocbeEuVrd(TBO$NZ`#xr zm{<#@XSGCW=AdTz180Uzz4ubTgX9~Slx0Q3OS%482)iqq)fPObdQ39<1FW)@AgA8a zE$i-SU&m_hX(kU|NWzf2X6X-EXLmCu?WQbUy8dxC_(P^^D-bZ^wY%`X+uOh=hsBP6 zy)zxXhGQCkv?KL?ysIPi@AxC})ZH#Q9r!EKU+Y{pD-V8V&i(vOCRlRCk{PpS>8P)H z1EJ-H=8f11JT=J2|5TKx5l_x2$|=O(B3?l3`In-67jgX!MY)T3s;XmVSlHpyi(d};aROfd zlC__B2`MkP<(r2wG7G`J4s6LoEaUG`NGx(37Fz9ji9v&54Mj^r79;&<{GPZ0`~6KY+xOjLo*%I^Sh*Z;(cKz zuiktX4#$d4iu^X~+7Uxc5)ZcBbi=@I>$ z$Gd1#t%O5*s8%e~Cr3BhhZV{aM&Werma;$bH^h3bzr$nrieY)3B;57GH|nIhCygGY z6^_+ac=TtF&NittU4nhMQYU)!D^=HSMlHo@PXev4sh`Em-$%*_iRpR`_oJ1Qb`d{Vvo+4j^XygQ`3LhA%7{6pl5>Aws*j>JpbetuJO*?LY;xw* zYGo^X1JV8L-$R)Vj<5c%R5vMFeXiQn!bpQiA6EaLVE^HtU|(3?(%Ahmf$^lA#5nKZ zt$mq!33m*zt5NcpF_{C67CINh!;PY+i8m$2o4cK7=wMo5ml2e(TOfy-M1Q4voZ%kh z+(TdXmsO8XRSyHX#XTKxWtB*4Aihc*Z8~b)v3u_hc(&=IMco}6y7%_>?0mAjZ}0XV zxW0N4t~dV-wwN0;*)>Zk+={+p>h5@CeK)+CSCV<}!C%wN!Pr(x9dI=sbm@CdN8Hbq zEs|5;YC5ijZ7o5ozR}nQZfUUgvlA8zZtJO*2B*H;bu@#&b%18!YHI~#TOHPEemqV) zV5+sjIm1OA$5q2vo5QJ3rjBmd))utt%K-Q4@wRr_3|HHNmU|C(PomK>>{Hu=`}eU# zqjPTm@_p=q6N#WzU+bX&OeGpD`r|MLp7utIzD;C!ti5sWP)qVv^&*^TS8&`;tZTF; US81s_P4KsM4Z_JNl*!fq1@REsga7~l From a133fb48eb74c204100f57e04bf0ec7df8965b8d Mon Sep 17 00:00:00 2001 From: Dulana Peiris Date: Mon, 23 Oct 2023 23:11:05 +0530 Subject: [PATCH 08/23] Added HPSH init, deinit and serve. Fixed socket communication issues --- CMakeLists.txt | 1 + src/hpsh/hpsh.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++ src/hpsh/hpsh.hpp | 14 +++++++ src/main.cpp | 5 ++- src/usr/usr.cpp | 89 ++------------------------------------------ test/bin/hpsh | Bin 18496 -> 19592 bytes 6 files changed, 115 insertions(+), 86 deletions(-) create mode 100644 src/hpsh/hpsh.cpp create mode 100644 src/hpsh/hpsh.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0319c611..8d75b111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ add_executable(hpcore src/status.cpp src/consensus.cpp src/main.cpp + src/hpsh/hpsh.cpp ) target_link_libraries(hpcore killswitch diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp new file mode 100644 index 00000000..e7b5e30b --- /dev/null +++ b/src/hpsh/hpsh.cpp @@ -0,0 +1,92 @@ +#include "../conf.hpp" +#include "../util/util.hpp" + +namespace hpsh +{ + pid_t hpsh_pid; + static int fd1[2]; + static int fd2[2]; + + int deinit() + { + //kill(hpsh_pid, SIGTERM); + close(fd1[0]); + close(fd1[1]); + close(fd2[0]); + close(fd1[1]); + + LOG_INFO << "HPSH stopped."; + + return 0; + } + int init() + { + LOG_INFO << "Initializing HPSH"; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd1) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, fd2) == -1) + { + return -1; + } + + pid_t pid = fork(); + if (pid == -1) + { + return -1; + } + + if (pid == 0) + { + hpsh_pid = getpid(); + char cfd1[10], cfd2[10]; + snprintf(cfd1, 10, "%d", fd1[0]); + snprintf(cfd2, 10, "%d", fd2[1]); + + char *argv[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), (char *)("-s1"), cfd1, (char *)("-s2"), cfd2, NULL}; + LOG_DEBUG << "Starting HPSH Executable"; + execv(argv[0], argv); + LOG_DEBUG << "Failed to execute hpsh"; + exit(EXIT_FAILURE); + } + else + { + close(fd1[0]); + close(fd2[1]); + + return 0; + } + } + + std::string serve(const char *message) + { + char buffer[1024]; + + ssize_t bytes_written = write(fd1[1], message, strlen(message)); + if (bytes_written == -1) { + perror("Error when writing to HPSH socket"); + } + + LOG_DEBUG << "\nMessage sent from hpcore: " << message; + + while (true) + { + int bytesRead; + bytesRead = read(fd2[0], buffer, sizeof(buffer)); + if (bytesRead < 0) + { + // Handle read error + perror("read"); + return "error when reading"; + } + + + buffer[bytesRead] = '\0'; // Null-terminate the buffer + + LOG_DEBUG << "\nMessage received in hpcore: " << buffer; + if(bytesRead<1024){ + break; + } + + } + return buffer; + } +} \ No newline at end of file diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp new file mode 100644 index 00000000..4d9bad19 --- /dev/null +++ b/src/hpsh/hpsh.hpp @@ -0,0 +1,14 @@ +#ifndef HPSH_H +#define HPSH_H + +#include "../conf.hpp" +#include "../util/util.hpp" + +namespace hpsh +{ + int deinit(); + int init(); + std::string serve(const char* command); +} + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bc711b27..4f50fae1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "ledger/ledger.hpp" #include "unl.hpp" #include "killswitch/killswitch.h" +#include "hpsh/hpsh.hpp" /** * Parses CLI args and extracts HotPocket command and parameters given. @@ -75,6 +76,7 @@ void deinit() sc::deinit(); ledger::deinit(); conf::deinit(); + hpsh::deinit(); } void sig_exit_handler(int signum) @@ -213,7 +215,8 @@ int main(int argc, char **argv) consensus::init() == -1 || read_req::init() == -1 || p2p::init() == -1 || - usr::init() == -1) + usr::init() == -1 || + hpsh::init() == -1) { deinit(); return -1; diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 8a514ee2..87655008 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -17,6 +17,7 @@ #include "user_input.hpp" #include "read_req.hpp" #include "input_nonce_map.hpp" +#include "../hpsh/hpsh.hpp" namespace usr { @@ -278,91 +279,9 @@ namespace usr if (parser.extract_shell_input(id, content) != -1) { - int p1[2] ; // 0,1 are hpcore to hphs - int p2[2] ; // 2,3 are hpsh to hpcore - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, p1)) - perror("could not create unix domain socket pair"); - - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, p2)) - perror("could not create unix domain socket pair"); - - pid_t pid = -1; - - pid = fork(); - - if (pid == -1) - { - perror("Error occurred when forking"); - return -1; - } - if (pid != 0) - { - // parent process - close(p1[0]); - close(p2[1]); - LOG_INFO << "parent: Received Shell Input.\n"; - LOG_INFO << "parent: User PubKey:" << user.pubkey << "\n"; - LOG_INFO << "parent: ID:" << id << "\n"; - LOG_INFO << "parent: Content:" << content << "\n"; - LOG_INFO << "parent: writing content to pipe\n"; - ssize_t bytes_written = write(p1[1], content.c_str(), content.size()); - if (bytes_written == -1) - { - perror("write to pipe failed"); - // handle the error appropriately - } - char buffer[1024] = {0}; - if(read(p2[0], &buffer, sizeof(buffer))==-1){ - perror("Error in reading to the fd"); - } - std::cout <<"bufferread"<< buffer << std::endl; - - LOG_INFO << "parent: closing pipe\n"; - close(p1[1]); - close(p2[0]); - LOG_INFO << "parent: closed\n"; - } - else - { - - // child process - close(p1[1]); - close(p2[0]); - char read_end[16]; - snprintf(read_end, sizeof(read_end), "%d", p1[0]); - char write_end[16]; - snprintf(write_end, sizeof(write_end), "%d", p2[1]); - std::string receivedContent; - LOG_INFO << "child: reading from pipe:\n"; - const int BUFFER_SIZE = 1024; - char buffer[BUFFER_SIZE]; - - ssize_t bytes_read = read(p1[0], buffer, BUFFER_SIZE); - if (bytes_read == -1) - { - perror("read from pipe failed"); - // handle the error appropriately - } - else - { - buffer[bytes_read] = '\0'; // Null-terminate the string - receivedContent = buffer; - LOG_INFO << "child: Content:" << receivedContent << "\n"; - } - - receivedContent = "\"" + receivedContent + "\""; - - char *passed_command = new char[receivedContent.length() + 1]; - std::strcpy(passed_command, receivedContent.c_str()); - - char *args[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), passed_command,read_end, write_end, NULL}; - if (execv(conf::ctx.hpsh_exe_path.c_str(), args) == -1) - { - perror("Error when executing HPSH"); - } - close(p1[0]); - close(p2[1]); - } + LOG_INFO << "shell input received:" << content; + std::string response = hpsh::serve(content.c_str()); + LOG_INFO << "response: " << response; return 0; } diff --git a/test/bin/hpsh b/test/bin/hpsh index cffa8ef387521885579789b3568c67f9f81e85db..d58f320b1776018bb9269b44b6390f3965c3abaa 100755 GIT binary patch literal 19592 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 delta 4591 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 KCUbDRB;&uy0WF9C From 23ee18e4543dc5392850102e576ac611d9b095df Mon Sep 17 00:00:00 2001 From: supunvindula Date: Tue, 31 Oct 2023 10:02:42 +0530 Subject: [PATCH 09/23] included the basic architecture for hpsh implementation --- src/hpsh/hpsh.cpp | 288 ++++++++++++++++++++++++++++++++++++---------- src/hpsh/hpsh.hpp | 52 ++++++++- src/hpsh/util.cpp | 45 ++++++++ src/hpsh/util.hpp | 30 +++++ src/usr/usr.cpp | 8 +- test/bin/hpsh | Bin 19592 -> 34032 bytes 6 files changed, 352 insertions(+), 71 deletions(-) create mode 100644 src/hpsh/util.cpp create mode 100644 src/hpsh/util.hpp diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index e7b5e30b..e6994e59 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -1,92 +1,254 @@ -#include "../conf.hpp" -#include "../util/util.hpp" +#include "hpsh.hpp" namespace hpsh { - pid_t hpsh_pid; - static int fd1[2]; - static int fd2[2]; + constexpr const char *HPSH_EXEC_PATH = "./executable/hpsh"; + constexpr int MAX_BUFFER_LEN = 1024; + constexpr int POLL_TIMEOUT = 1000; + constexpr uint32_t READ_BUFFER_SIZE = 128 * 1024; - int deinit() + hpsh_context ctx; + + int init() { - //kill(hpsh_pid, SIGTERM); - close(fd1[0]); - close(fd1[1]); - close(fd2[0]); - close(fd1[1]); + std::cout << "Initializing hpsh process.." << std::endl; - LOG_INFO << "HPSH stopped."; + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctx.control_fds) == -1) + { + std::cerr << errno << "Error initializing socket pair." << std::endl; + return -1; + } + + ctx.hpsh_pid = fork(); + if (ctx.hpsh_pid == -1) + { + std::cerr << errno << "Error forking." << std::endl; + close(ctx.control_fds[0]); + close(ctx.control_fds[1]); + return -1; + } + else if (ctx.hpsh_pid > 0) + { + close(ctx.control_fds[0]); + + ctx.watcher_thread = std::thread(response_watcher); + } + else if (ctx.hpsh_pid == 0) + { + util::fork_detach(); + + close(ctx.control_fds[1]); + + std::cout << "Starting hpsh process... " << std::endl; + + std::string fd_str; + fd_str.resize(10); + snprintf(fd_str.data(), sizeof(fd_str), "%d", ctx.control_fds[0]); + + char *argv[] = {(char *)HPSH_EXEC_PATH, (char *)("-s1"), fd_str.data(), NULL}; + execv(argv[0], argv); + + std::cerr << errno << "Error executing hpfs." << std::endl; + + close(ctx.control_fds[0]); + exit(EXIT_FAILURE); + } return 0; } - int init() + + void deinit() { - LOG_INFO << "Initializing HPSH"; + std::cout << "De-initializing hpsh process.." << std::endl; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd1) == -1 || socketpair(AF_UNIX, SOCK_STREAM, 0, fd2) == -1) + ctx.is_shutting_down = true; + + if (ctx.hpsh_pid > 0) + kill(ctx.hpsh_pid, SIGTERM); + + // Joining consensus processing thread. + if (ctx.watcher_thread.joinable()) + ctx.watcher_thread.join(); + + // close sockets. + close(ctx.control_fds[0]); + for (const auto &command : ctx.commands) { - return -1; + close(command.child_fds[0]); + close(command.child_fds[1]); } - pid_t pid = fork(); - if (pid == -1) + if (ctx.hpsh_pid > 0) { - return -1; + // Check if the hpsh has exited voluntarily. + if (check_hpsh_exited(false) == 0) + { + // Issue kill signal to kill the hpsh process. + kill(ctx.hpsh_pid, SIGKILL); + check_hpsh_exited(true); // Blocking wait until exit. + } } - if (pid == 0) - { - hpsh_pid = getpid(); - char cfd1[10], cfd2[10]; - snprintf(cfd1, 10, "%d", fd1[0]); - snprintf(cfd2, 10, "%d", fd2[1]); + std::cout << "Stopped hpsh process.." << std::endl; + } - char *argv[] = {const_cast(conf::ctx.hpsh_exe_path.c_str()), (char *)("-s1"), cfd1, (char *)("-s2"), cfd2, NULL}; - LOG_DEBUG << "Starting HPSH Executable"; - execv(argv[0], argv); - LOG_DEBUG << "Failed to execute hpsh"; - exit(EXIT_FAILURE); - } - else - { - close(fd1[0]); - close(fd2[1]); + int check_hpsh_exited(const bool block) + { + int scstatus = 0; + const int wait_res = waitpid(ctx.hpsh_pid, &scstatus, block ? 0 : WNOHANG); + if (wait_res == 0) // Child still running. + { return 0; } + if (wait_res == -1) + { + std::cerr << errno << ": hpsh process waitpid error. pid:" << ctx.hpsh_pid << std::endl; + ctx.hpsh_pid = 0; + return -1; + } + else // Child has exited + { + ctx.hpsh_pid = 0; + + if (WIFEXITED(scstatus)) + { + std::cerr << "Contract process ended normally." << std::endl; + return 1; + } + else + { + std::cerr << "Contract process ended prematurely. Exit code " << WEXITSTATUS(scstatus) << std::endl; + return -1; + } + } } - std::string serve(const char *message) + int execute(std::string_view pubkey, std::string_view message) { - char buffer[1024]; + if (ctx.is_shutting_down) + return -1; - ssize_t bytes_written = write(fd1[1], message, strlen(message)); - if (bytes_written == -1) { - perror("Error when writing to HPSH socket"); - } - - LOG_DEBUG << "\nMessage sent from hpcore: " << message; - - while (true) + int child_fds[2]; + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, child_fds) == -1) { - int bytesRead; - bytesRead = read(fd2[0], buffer, sizeof(buffer)); - if (bytesRead < 0) - { - // Handle read error - perror("read"); - return "error when reading"; - } - - - buffer[bytesRead] = '\0'; // Null-terminate the buffer - - LOG_DEBUG << "\nMessage received in hpcore: " << buffer; - if(bytesRead<1024){ - break; - } - + std::cerr << errno << "Error initializing socket pair." << std::endl; + return -1; + } + + struct msghdr msg = {0}; + struct cmsghdr *cmsg; + char iobuf[1]; + struct iovec io = { + .iov_base = iobuf, + .iov_len = sizeof(iobuf)}; + union + { /* Ancillary data buffer, wrapped in a union + in order to ensure it is suitably aligned */ + char buf[CMSG_SPACE(sizeof(int))]; + struct cmsghdr align; + } u; + + msg.msg_iov = &io; + msg.msg_iovlen = 1; + msg.msg_control = u.buf; + msg.msg_controllen = sizeof(u.buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), child_fds, sizeof(int)); + + if (sendmsg(ctx.control_fds[1], &msg, 0) < 0) + { + std::cerr << errno << "Error writing to control fd." << std::endl; + close(child_fds[0]); + close(child_fds[1]); + return -1; + } + + if (write(child_fds[1], message.data(), sizeof(message)) < 0) + { + std::cerr << errno << "Error writing to child fd." << std::endl; + close(child_fds[0]); + close(child_fds[1]); + return -1; + } + + { + std::scoped_lock lock(ctx.command_mutex); + ctx.commands.push_back(command_context{std::string(pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); + } + + return 0; + } + + void response_watcher() + { + util::mask_signal(); + + while (!ctx.is_shutting_down) + { + if (ctx.commands.size() > 0) + { + auto itr = ctx.commands.begin(); + while (itr != ctx.commands.end()) + { + if (ctx.is_shutting_down) + break; + + struct pollfd pfd; + pfd.fd = itr->child_fds[1]; + pfd.events = POLLIN; + + if (poll(&pfd, 1, POLL_TIMEOUT) == -1) + { + std::cerr << errno << "Error in poll" << std::endl; + continue; + } + else if (pfd.revents & POLLIN) + { + itr->response.resize(READ_BUFFER_SIZE); + const int res = read(pfd.fd, itr->response.data(), READ_BUFFER_SIZE); + + if (res > 0) + itr->response.resize(res); // Resize back to the actual bytes read. + else if (res == -1) + { + // Assuming that EPIPE or ECONNRESET resulted from contract termination, consider this as a neutral read. + if (errno == EPIPE || errno == ECONNRESET) + itr->read_completed = true; + else + std::cerr << errno << "Error reading from fd" << std::endl; + } + } + else + { + itr->read_completed = true; + } + + // Send command back to user; + if (itr->read_completed) + { + std::cout << "Received full output for user " << itr->pubkey << std::endl; + std::cout << itr->response.data() << std::endl; + + std::list collected_commands; + { + std::scoped_lock lock(ctx.command_mutex); + itr = ctx.commands.erase(itr); + } + } + else + { + itr++; + } + } + } + else + { + util::sleep(1000); + } } - return buffer; } } \ No newline at end of file diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index 4d9bad19..db41dfd3 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -1,14 +1,54 @@ -#ifndef HPSH_H -#define HPSH_H +#ifndef _HP_HPSH_ +#define _HP_HPSH_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "util.hpp" -#include "../conf.hpp" -#include "../util/util.hpp" namespace hpsh { - int deinit(); + struct command_context + { + std::string pubkey; + int child_fds[2]; + std::string response; + bool read_completed = false; + }; + + struct hpsh_context + { + std::mutex command_mutex; + std::list commands; + int control_fds[2]; + int hpsh_pid; + std::thread watcher_thread; + bool is_shutting_down; + }; + + extern hpsh_context ctx; + int init(); - std::string serve(const char* command); + + void deinit(); + + int check_hpsh_exited(const bool block); + + int execute(std::string_view pubkey, std::string_view message); + + void response_watcher(); } #endif \ No newline at end of file diff --git a/src/hpsh/util.cpp b/src/hpsh/util.cpp new file mode 100644 index 00000000..2e9d97a0 --- /dev/null +++ b/src/hpsh/util.cpp @@ -0,0 +1,45 @@ +#include "util.hpp" + +namespace util +{ + constexpr mode_t DIR_PERMS = 0755; + + /** + * Sleeps the current thread for specified no. of milliseconds. + */ + void sleep(const uint64_t milliseconds) + { + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); + } + + // Applies signal mask to the calling thread. + void mask_signal() + { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &mask, NULL); + } + + /** + * Clears signal mask and signal handlers from the caller. + * Called by other processes forked from hpcore threads so they get detatched from + * the hpcore signal setup. + */ + void fork_detach() + { + // Restore signal handlers to defaults. + signal(SIGINT, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGABRT, SIG_DFL); + + // Remove any signal masks applied by hpcore. + sigset_t mask; + sigemptyset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, NULL); + + // Set process group id (so the terminal doesn't send kill signals to forked children). + setpgrp(); + } +} // namespace util diff --git a/src/hpsh/util.hpp b/src/hpsh/util.hpp new file mode 100644 index 00000000..beb9833f --- /dev/null +++ b/src/hpsh/util.hpp @@ -0,0 +1,30 @@ +#ifndef _HP_UTIL_UTIL_ +#define _HP_UTIL_UTIL_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Contains helper functions and data structures used by multiple other subsystems. + */ + +namespace util +{ + void sleep(const uint64_t milliseconds); + + void mask_signal(); + + void fork_detach(); + +} // namespace util + +#endif diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 87655008..6871841c 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -280,8 +280,12 @@ namespace usr { LOG_INFO << "shell input received:" << content; - std::string response = hpsh::serve(content.c_str()); - LOG_INFO << "response: " << response; + // std::string response = hpsh::serve(content.c_str()); + if (hpsh::execute(std::string("user_").append(std::to_string(1)), content.c_str()) == -1) + { + std::cout << "\nError sending message:" << content.c_str() << std::endl; + } + // LOG_INFO << "response: " << response; return 0; } diff --git a/test/bin/hpsh b/test/bin/hpsh index d58f320b1776018bb9269b44b6390f3965c3abaa..cf4cd294fed5b325afc51a1f7a4991fb72754f66 100755 GIT binary patch literal 34032 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 literal 19592 zcmeHPeQ;aVmA|rLVn||(kWe=iB0^vjAd2NUA%RViV=H+kPB3v?vT5NVONy<=l8p2e z9G1{zj2X1XZD`9hI}5v^vjwJQr=gS1WSIg^1BC7ZYi8ReZRs|<16{dLHn^ot%ZK)N z?z`vty=Og!ul}>+>ygeqzkANP=YG9+b>BPwQnY=2mCq+Q`Nd}iaW|b~A`w+^SF6f^ zM8s+_2j4-lP@DmNhQ!SBh)GatrV~|8TBC43DCyNxrULzp2@9s|AyLxvN)2^p2~!a; zdD5$K*w@C%sAOjY_9bru?GrBE2!C zH>UKM22_7C<^H5Tq0ee%*G+>cqZE|iLb&y|DLprBRq{-!4oaP`8i|imUx(6rBq+@Y zH@(Az1yio?I_Ocqe9*+hyhYXLH4d6;H&YsKO3V9F-K(0G_a&C~r80$qWdo~MEnC$T z%4b83vYh;)I%xPdZ0-^mmQli#IXM>d6i?-iZ{ODca?A6-+Sb@N`{u@zSAFs7oeS9p z)k!jxNM8-H#V^u_7fE%Oh|ZjoSxukXR=+zR+U54;N% zR+8_AjY{};JnY=>A^(bp{pUUG!1W?;B;uD{M%Rc{Lf3oJ*^Hhy zVmU+Ch2FMxlb%TCl0B)sk<4w~)Y6yDB)7)8`;ul^<&y22J7aC}XlppSOX%A>jizKK z(bpF5G{WI{Z!D)9xme1`Ln68b*oy90J{8xqc_WvMrQ5dZTO0If=PJ|=)y5`WH+pl~ zTl7?BSFA6U&||rtLOPi-IyS~3vANT@Lf7L11L1JE(KG}*sZ39$>ZDiEmT(lhTQ+vC zpekTsbt;?Jp_^=K%cKnD_2$lOUq0HgeoJSzQ;(X>h$nM7>Y{-Gy+4`DXESif*sbqs zkanoauuVV4UG%t&Q3 z0+S{o5{3RoaSLWue<~s3ec3$br&QjNqCvVfNhagzexT%!n&9bJDkCZ(!G_E4}a@X#MhCIOLk+YH&gi4joODgXlYY<1fPHZ?oQm&&k(avPMERu ztJo^d5a%lX=F@bg^@~N8ewBzT`w$oNQmHw#D+nw3!h+P9)TXPHJnsW}{}rK40@A43 z=P};-X%m0eg$pHL6EVwKp83(MO`LjVk(rg>&)RVA8!8yH;qz_sCv5lv8-CJ;pKrrU zHv9q`e#(X~wBe_1_=Pq+5HT4V6V(M0h$x))TeRol#MfuSFJch%^k+?GCWyLpn}Dj9 za15K3YHYX~Dp?k=;Zz5wdK+%vmj-P()xl|r4d*eVvIZNDiDISIHvB9L#T>Qa>L-gV z)ol1|n|y~2$HcVKHXB}Rp+ekb!_`kIS=wvEXlJBLGiShp`m&^MlPYY~f{6&kW zg*7pL)Z%GDO^iQk@pJ*27=OUxX<<35Y0g)lMx=6l>;S^#Lj#nZ$` z`z@X(Jlb#ZG||z1i>C>W_FFt%c+q}~r-_dCTRcs0wBO=sVx#@cV|3nHMx)azk)UHlDpKKz@u;)^$G#sAg@UpdvWwSA=ebC|)}$edqdVrwI7 ztFV5`^S40dcl*KaLq;2^zLm(D)5d%(%@F0WG|w!btXsGjqc4sr3i<1#{K{*HEPYQa zp3;uKakX~zv|sZ*qrLc^F%Jf+m4TY_$sKZBS)bPL-nB_AZc(_bOB-DK?aPqWimw{8 zwc)kD0#o|icgy8c0*m39>a~#b-2h#ye$pSm1%;I9f*vj=f#RNbw2_sMV%fpHpOKCE zn5$axhw!8mtX6zRE51|;0DO`fQ(BK48|c*bz21xdDL#JRA4uu@`#}=g@QjO>NYA3B z@F=X`jXIyCg<1L|{5wAM2&5<-A39{^4kJg`rr{wnHCXbk86v1|WC-Z6%xedZ@d?MjN?T%8v|< zO0^eAGX;Y%M95=wrFufvj)IqQoh-_RsA7`->vyCySNl5H@yDQH)$QT_Hkc;;S<3x8 zo$j{+woH5|_rGmAG}Zm{rTf(THurzUxRxKP4}wcPid`k&vZe#w?u)% z)jKd{6?hTAQU<1qLqCA2!N=)a)D3-?#^t!24aiaUSt>BIW0TnvoE@otjIJI%KmE$Ea}*&@U2t zKF}kytX{juGgL~fb6&m;LIZb0xSc;am(0I%GN9Mn92^uxBvVo@LaP=YL zP`5xG`+sB^dxBI|ub~GWwFI@|p3_>faH`n#x;7j|_IN3Vx-iv;HxY8Gx%jMBJc>%< z*bSkQi&Q0FL4W?}nA~^q<(6!f{Lmf_kgZ~%^n3Kiaq4*if2PX5M8hM7MhkOF&r!b( zcby)dTMXEIm+sNPe+i$mwkCS|_E|?@ZZBnTn<*FHYt@8^$#!+3`+A{y1Pwc+6}ukR zikl9$7Nhq~xq3&(sKKjYdbsO8ZDi94`2BGEa1@$!iEPFWv=}`J@C536xPV(x6b6r% zZiKg`PfPCyPcJg4xhDya!V;#f!!Pib-X+wvkS#`ktPSotD2%z%_GMAHh-*vqpjHeF z-|%B?#B}UmF-bAWh6^-Jo6Ko?@oN`Yv(1$H7ENVyF8+%Aicwb%KGlo)v?Elv@DA!6 zxgTr3zI|lv#tVgL{#;w}KbpJRif=VD)b^j+G6m$JWug`@BKjfLT# ztNVL7n*NqzOh+9w!>K;?cAlWw6C{z z^3t8@ujw9`?t$qZuzJA9r(k&_n*yqJbZWs|GM-HBN+yDMRFTHHFC7mD)j9LBd{`{Y zH=2T-+4#<+5#%Qc!E`F0$0GxA)}~}WAL~g@T1sVtWctdW!1IA#u`Di@cc(JTB}2}{ zv*~m!lL*qOH7Z^f%w&T&;Fbn)HZ4!LedqbF+6!6Q^&9_NE*}P+_hz~LGU#H^-+>;U zD3|X8z5lo6^5xj@{3mEH=yu!z>Txdd5a?>qQPA1IXVX0!bT#N9&^YKA=mF4Epog(p z_yXi@csgwy#^0QD~i6|FPnG1+2doA5dEM!9?ta-ue{ zzPA3Fx>>i>>=jopxbo5!ix&Zv`du!8#`@E6BXl>xm zs+KutRIP(Yc&~!W@JYd+W_vmEq)W+nYe&0m#mv7u6KA&Paa+h|`edMc+YFq3x1eIS zuMPVBJ7>r`WP4F$zz6)Qo0RF6#j>6Tl<$3?@(z>_qg)>Sa~*xAKKVdxIEeDOkel%f zTOCpOF~ev1aRB94{=Qt^1QE;Es#aMZ1VlTQ9+b;7Wv-{gtcO%u@p&0C9hetM0@l|C zzEagzTmNN$v^F?0BU-!U?&{XshC9#DYF7`=+)x|I)UIx>ZD_7tvaU9`uC{(%ZD3t( zjeKUX81rNRcI@ZH_#t{h$yfcg8nLgc`t6zGA%FFAHDc6XeYi&4JL3d;84_n**H!Y7 z068$7rh8zz2c~;qx(B9vV7dpUdtkZ;>^%^njWH6xC&3$YY~f^bQ+fx4665sF2Bq01 zF<cUdqIg+QrhuYBMH>{2DB7XuO^Ws_ zx>wQtiXK$-kfQE(eN?_C;?%^;TvrB{bafXpMj^N+)D&u17A{CGe0yUXPqfK7nj;^OzzZ7}AvU+{bAPJD*At)iW3YkfK8&k($>ocK(^>(7bT2%eWt z{7k{~*@>Sec-=VhS%TM>6UUNI z@%7CqkE?IQj+lAB?fqPPsoy&Jm_+F^H$%KBAGl4T=6#_GgSFrOk`e^y)eyo*T{v|M z;d~!rTUQ|CgFpT2OoZyAv>qQ{g?>l_Cp&z9BUwtj@$reN{doX*CI7!E<>!i;ATmf? z@8dFmp19fN&vU@3-ZRtybX;Ko=* zcW2kSh)VlY=gDSi=iDjtN>{jh9_FN-sq^YC;P&^`(0rL51ilE)yrMclo_C?-Prw6W zfvAs|a{TS9s%$5V4L}g`!XgQf+(A1?B+b2IQoT$zoINcn*H8+GHS^E*mk z^|13Z5Bv?_XICu{?)$>q9`du$4|CBIZK~d8vs!T}uGf|N(*S-U><1#IAnzyk1E+pI z;_BySY*gk}O}&o2;$i=f9{3#eMVmB zSAo;GxaZrO9`f@&@M`#9DURVYvR$e%Hj)NT^ISx1AhO#r?g3oi2G%+8TRrT2*#rNk z2Y%QC|0Qs$*WC}VdB_KFJ(1(3Ht5fIlsQ|f&ZJb)2G(mMx{0n3zO{E zDf{xA9%Xj{uM{8i55Oz6_j?|=i06#FQNR=IxR{KO(T%i@;Dbyuk2r%wR`2P{cE|ek zgptkV^;ltm9vAiZC5>bvw7OvxA|)yb=?Ga!A<88e+pQzaCAVAb$i>o0JyA%fcSFU- zAtokeI7EB<^S$9vydQxM2%c#VujxFc*NZ;I;C&8-wlq$5^Pk7^3kTDJ(j^{+NJZ)$5nnWG^ICm@57tXi*KzrHhy7@_8M z?NPGoj0TBBWbB3t%h0!P-@FF#I++4R2(6+|sjI5*hL2geX$UiO|S>gm^DyM1?6)H`@c& zrj~LZjM-9gTuw*K za4{!FVPQ^$-1UrMb5x3!cjxn}LOFq_hSj+hWLQ}|UyzqFbj>F_A7xl!g}}o|#1^*p z30G={0KQ)Ys3Xu19ik%XsK+=M(zBcBE{A@0MdK-P>-zn%F5fUeHJa5kV%3TxZK8Kd zqFXj@?$keMNNKbqjmCWZF>lbfP)sESLax#~iA4Jl2YN*+Vni zqqeYAXFtmb$SHkUDbm%cCqnt%X(QGRiU>?edpSow$b zT}a_y4_ zL`d#fLdb@CvS2BbPsT+EF`{7QqzdJ-@)jLR_NvWNZvxhsLp6w1O%BA9{f3S478I?^g|cKvPm{Yi=GVw1JL@w3d4+Q8ZM`J9t!&>>A{KF)MKSiIhn z<@O&`^)qcy;`o^&liU9oPNpPx(6yJIB6`h331l%HonL?*If zPd9_1X9cX!=det#QNrv$%Q3wj<@D@C;avxBdgbs885FesY;fQGV{E&?)189}4XHL8Zs^psT}O z=EXxU{ZVzk%#`K1e&(4Ta_RH=G*kP#Yh;7+rV!LF=i?a&{<(Al|mlEr-U*7>n{m1(Jyx=57wjl+n(3V)AX+6sA`XZu) zRmbr xTj}}j3VhgqZWlf0W#6Tu`r3P?nR$s76wdXsEL|=t>0jSsO3=Hw_T*y4{{e4tm4g5P From f84a02ce09a985c4245190d0f94599e6a3e8ddae Mon Sep 17 00:00:00 2001 From: chalith Date: Tue, 31 Oct 2023 13:35:37 +0530 Subject: [PATCH 10/23] Implementation for message handling --- CMakeLists.txt | 4 +- examples/js_client/text-client.js | 3 + examples/nodejs_contract/echo_contract.js | 37 ++++++++++ src/conf.cpp | 32 +++++++++ src/conf.hpp | 7 ++ src/hpsh/hpsh.cpp | 76 +++++++++++++------- src/hpsh/hpsh.hpp | 23 ++---- src/hpsh/util.cpp | 45 ------------ src/hpsh/util.hpp | 30 -------- src/msg/bson/usrmsg_bson.cpp | 51 ++++++++++---- src/msg/bson/usrmsg_bson.hpp | 4 +- src/msg/json/usrmsg_json.cpp | 82 +++++++++++++++++----- src/msg/json/usrmsg_json.hpp | 4 +- src/msg/usrmsg_common.hpp | 4 +- src/msg/usrmsg_parser.cpp | 14 +++- src/msg/usrmsg_parser.hpp | 4 +- src/usr/usr.cpp | 14 ++-- test/bin/hpsh | Bin 34032 -> 33952 bytes 18 files changed, 265 insertions(+), 169 deletions(-) delete mode 100644 src/hpsh/util.cpp delete mode 100644 src/hpsh/util.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d75b111..b2e8590c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,10 +59,10 @@ add_executable(hpcore src/ledger/ledger_sync.cpp src/ledger/ledger_serve.cpp src/ledger/ledger.cpp + src/hpsh/hpsh.cpp src/status.cpp src/consensus.cpp src/main.cpp - src/hpsh/hpsh.cpp ) target_link_libraries(hpcore killswitch @@ -78,7 +78,7 @@ target_link_libraries(hpcore add_custom_command(TARGET hpcore POST_BUILD # COMMAND strip ./build/hpcore - COMMAND rm -f ./build/hpws ./build/hpfs ./build/hpsh && cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ + COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ ) target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) diff --git a/examples/js_client/text-client.js b/examples/js_client/text-client.js index 1c3a61d4..d402ac47 100644 --- a/examples/js_client/text-client.js +++ b/examples/js_client/text-client.js @@ -123,6 +123,9 @@ async function main() { else if (inp === "stat") { hpc.getStatus().then(stat => console.log(stat)); } + else if (inp.startsWith("hpsh ")) { + hpc.submitHpshRequest(inp.substr(5)).then(reply => console.log(reply)); + } else { if (inp.startsWith("upload ")) { diff --git a/examples/nodejs_contract/echo_contract.js b/examples/nodejs_contract/echo_contract.js index 7b152b55..8c2be74f 100644 --- a/examples/nodejs_contract/echo_contract.js +++ b/examples/nodejs_contract/echo_contract.js @@ -84,5 +84,42 @@ const echoContract = async (ctx) => { // await ctx.updateConfig(config); } +const fallback = async (ctx) => { + console.log("This is fallback mode"); + + const hpconfig = await ctx.getConfig(); + + for (const u of ctx.unl.list()) { + const gap = Math.abs(u.activeOn - ctx.timestamp); + // If last active timestamp is before the twice of roundtime, This node must be active. + if (u.activeOn && gap > (hpconfig.consensus.roundtime * 4)) { + console.log("Updating patch config", u); + hpconfig.unl = hpconfig.unl.filter(e => e !== u.publicKey); + await ctx.updateConfig(hpconfig); + } + } + + // NPL messages example. + // Start listening to incoming NPL messages before we send ours. + const promise = new Promise((resolve, reject) => { + let timeout = setTimeout(() => { + reject('NPL timeout.'); + }, 4000); + + let list = []; + ctx.unl.onMessage((node, msg) => { + console.log(`${node.publicKey} said ${msg} to me.`); + list.push(msg); + if (list.length == ctx.unl.list().length) { + clearTimeout(timeout); + resolve(); + } + }); + }); + + await ctx.unl.send("Hello"); + await promise; +} + const hpc = new HotPocket.Contract(); hpc.init(echoContract); \ No newline at end of file diff --git a/src/conf.cpp b/src/conf.cpp index 68d1dd01..227b62d8 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -194,6 +194,8 @@ namespace conf cfg.log.loggers.emplace("console"); cfg.log.loggers.emplace("file"); + cfg.hpsh.enabled = false; + // Save the default settings into the config file. if (write_config(cfg) != 0) return -1; @@ -512,6 +514,28 @@ namespace conf } } + // hpsh + { + jpath = "hpsh"; + + try + { + const jsoncons::ojson &hpsh = d["hpsh"]; + cfg.hpsh.enabled = hpsh["enabled"].as(); + + if (cfg.hpsh.run_as.from_string(hpsh["run_as"].as()) == -1) + { + std::cerr << "Invalid format for hpsh run as config (\"uid>0:gid>0\" expected).\n"; + return -1; + } + } + catch (const std::exception &e) + { + print_missing_field_error(jpath, e); + return -1; + } + } + return 0; } @@ -624,6 +648,14 @@ namespace conf d.insert_or_assign("log", log_config); } + // hpsh configs + { + jsoncons::ojson hpsh_config; + hpsh_config.insert_or_assign("enabled", cfg.hpsh.enabled); + hpsh_config.insert_or_assign("run_as", cfg.hpsh.run_as.to_string()); + d.insert_or_assign("hpsh", hpsh_config); + } + return write_json_file(ctx.config_file, d); } diff --git a/src/conf.hpp b/src/conf.hpp index a29a6294..b91764f4 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -208,6 +208,12 @@ namespace conf std::vector runtime_env_args; // Contract environment variables. }; + struct hpsh_config + { + bool enabled = false; // Whether or not to enable hpsh. + ugid run_as; // The user/groups id to execute the hpsh as. + }; + struct user_config { uint16_t port = 0; // Listening port for public user connections @@ -317,6 +323,7 @@ namespace conf hpfs_config hpfs; log_config log; health_config health; // For debugging only. Not included in the config file. + hpsh_config hpsh; }; // Global contract context struct exposed to the application. diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index e6994e59..50ac92e3 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -2,27 +2,27 @@ namespace hpsh { - constexpr const char *HPSH_EXEC_PATH = "./executable/hpsh"; - constexpr int MAX_BUFFER_LEN = 1024; - constexpr int POLL_TIMEOUT = 1000; + constexpr uint32_t POLL_TIMEOUT = 1000; constexpr uint32_t READ_BUFFER_SIZE = 128 * 1024; hpsh_context ctx; int init() { - std::cout << "Initializing hpsh process.." << std::endl; + // Do not initialize if disabled in config. + if (!conf::cfg.hpsh.enabled) + return 0; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctx.control_fds) == -1) { - std::cerr << errno << "Error initializing socket pair." << std::endl; + LOG_ERROR << errno << ": Error initializing socket pair."; return -1; } ctx.hpsh_pid = fork(); if (ctx.hpsh_pid == -1) { - std::cerr << errno << "Error forking." << std::endl; + LOG_ERROR << errno << ": Error forking."; close(ctx.control_fds[0]); close(ctx.control_fds[1]); return -1; @@ -39,27 +39,41 @@ namespace hpsh close(ctx.control_fds[1]); - std::cout << "Starting hpsh process... " << std::endl; - std::string fd_str; fd_str.resize(10); snprintf(fd_str.data(), sizeof(fd_str), "%d", ctx.control_fds[0]); + char *argv[] = {(char *)conf::ctx.hpsh_exe_path.data(), fd_str.data(), NULL}; + + // Just before we execv the hpsh binary, we set user execution user/group if specified in hp config. + // (Must set gid before setting uid) + if (!conf::cfg.hpsh.run_as.empty() && (setgid(conf::cfg.hpsh.run_as.gid) == -1 || setuid(conf::cfg.hpsh.run_as.uid) == -1)) + { + std::cerr << errno << ": Hpsh process setgid/uid failed." + << "\n"; + exit(1); + } - char *argv[] = {(char *)HPSH_EXEC_PATH, (char *)("-s1"), fd_str.data(), NULL}; execv(argv[0], argv); - std::cerr << errno << "Error executing hpfs." << std::endl; + std::cerr << errno << ": Error executing hpsh." + << "\n"; close(ctx.control_fds[0]); - exit(EXIT_FAILURE); + exit(1); } + ctx.is_initialized = true; + + LOG_INFO << "Hpsh handler started."; + return 0; } void deinit() { - std::cout << "De-initializing hpsh process.." << std::endl; + // This is not initialized if disabled in config. + if (!conf::cfg.hpsh.enabled) + return; ctx.is_shutting_down = true; @@ -89,7 +103,7 @@ namespace hpsh } } - std::cout << "Stopped hpsh process.." << std::endl; + LOG_INFO << "Hpsh handler stopped."; } int check_hpsh_exited(const bool block) @@ -103,7 +117,7 @@ namespace hpsh } if (wait_res == -1) { - std::cerr << errno << ": hpsh process waitpid error. pid:" << ctx.hpsh_pid << std::endl; + LOG_ERROR << errno << ": Hpsh process waitpid error. pid:" << ctx.hpsh_pid; ctx.hpsh_pid = 0; return -1; } @@ -113,18 +127,18 @@ namespace hpsh if (WIFEXITED(scstatus)) { - std::cerr << "Contract process ended normally." << std::endl; + LOG_DEBUG << "Hpsh process ended normally."; return 1; } else { - std::cerr << "Contract process ended prematurely. Exit code " << WEXITSTATUS(scstatus) << std::endl; + LOG_WARNING << "Hpsh process ended prematurely. Exit code " << WEXITSTATUS(scstatus); return -1; } } } - int execute(std::string_view pubkey, std::string_view message) + int execute(std::string_view id, std::string_view pubkey, std::string_view message) { if (ctx.is_shutting_down) return -1; @@ -132,7 +146,7 @@ namespace hpsh int child_fds[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, child_fds) == -1) { - std::cerr << errno << "Error initializing socket pair." << std::endl; + LOG_ERROR << errno << ": Error initializing socket pair."; return -1; } @@ -161,7 +175,7 @@ namespace hpsh if (sendmsg(ctx.control_fds[1], &msg, 0) < 0) { - std::cerr << errno << "Error writing to control fd." << std::endl; + LOG_ERROR << errno << ": Error writing to control fd."; close(child_fds[0]); close(child_fds[1]); return -1; @@ -169,7 +183,7 @@ namespace hpsh if (write(child_fds[1], message.data(), sizeof(message)) < 0) { - std::cerr << errno << "Error writing to child fd." << std::endl; + LOG_ERROR << errno << ": Error writing to child fd."; close(child_fds[0]); close(child_fds[1]); return -1; @@ -177,7 +191,7 @@ namespace hpsh { std::scoped_lock lock(ctx.command_mutex); - ctx.commands.push_back(command_context{std::string(pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); + ctx.commands.push_back(command_context{std::string(id), std::string(pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); } return 0; @@ -203,7 +217,7 @@ namespace hpsh if (poll(&pfd, 1, POLL_TIMEOUT) == -1) { - std::cerr << errno << "Error in poll" << std::endl; + LOG_ERROR << errno << ": Error in poll"; continue; } else if (pfd.revents & POLLIN) @@ -219,7 +233,7 @@ namespace hpsh if (errno == EPIPE || errno == ECONNRESET) itr->read_completed = true; else - std::cerr << errno << "Error reading from fd" << std::endl; + LOG_ERROR << errno << ": Error reading from fd"; } } else @@ -230,10 +244,20 @@ namespace hpsh // Send command back to user; if (itr->read_completed) { - std::cout << "Received full output for user " << itr->pubkey << std::endl; - std::cout << itr->response.data() << std::endl; + { + std::scoped_lock lock(usr::ctx.users_mutex); - std::list collected_commands; + // Find the user session by user pubkey. + const auto user_itr = usr::ctx.users.find(itr->pubkey); + if (user_itr != usr::ctx.users.end()) // match found + { + const usr::connected_user &user = user_itr->second; + msg::usrmsg::usrmsg_parser parser(user.protocol); + std::vector msg; + parser.create_hpsh_response_container(msg, itr->id, itr->response); + user.session.send(msg); + } + } { std::scoped_lock lock(ctx.command_mutex); itr = ctx.commands.erase(itr); diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index db41dfd3..7f902cf2 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -1,27 +1,15 @@ #ifndef _HP_HPSH_ #define _HP_HPSH_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "util.hpp" - +#include "../pchheader.hpp" +#include "../conf.hpp" +#include "../usr/usr.hpp" namespace hpsh { struct command_context { + std::string id; std::string pubkey; int child_fds[2]; std::string response; @@ -36,6 +24,7 @@ namespace hpsh int hpsh_pid; std::thread watcher_thread; bool is_shutting_down; + bool is_initialized = false; }; extern hpsh_context ctx; @@ -46,7 +35,7 @@ namespace hpsh int check_hpsh_exited(const bool block); - int execute(std::string_view pubkey, std::string_view message); + int execute(std::string_view id, std::string_view pubkey, std::string_view message); void response_watcher(); } diff --git a/src/hpsh/util.cpp b/src/hpsh/util.cpp deleted file mode 100644 index 2e9d97a0..00000000 --- a/src/hpsh/util.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "util.hpp" - -namespace util -{ - constexpr mode_t DIR_PERMS = 0755; - - /** - * Sleeps the current thread for specified no. of milliseconds. - */ - void sleep(const uint64_t milliseconds) - { - std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); - } - - // Applies signal mask to the calling thread. - void mask_signal() - { - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGPIPE); - pthread_sigmask(SIG_BLOCK, &mask, NULL); - } - - /** - * Clears signal mask and signal handlers from the caller. - * Called by other processes forked from hpcore threads so they get detatched from - * the hpcore signal setup. - */ - void fork_detach() - { - // Restore signal handlers to defaults. - signal(SIGINT, SIG_DFL); - signal(SIGSEGV, SIG_DFL); - signal(SIGABRT, SIG_DFL); - - // Remove any signal masks applied by hpcore. - sigset_t mask; - sigemptyset(&mask); - pthread_sigmask(SIG_SETMASK, &mask, NULL); - - // Set process group id (so the terminal doesn't send kill signals to forked children). - setpgrp(); - } -} // namespace util diff --git a/src/hpsh/util.hpp b/src/hpsh/util.hpp deleted file mode 100644 index beb9833f..00000000 --- a/src/hpsh/util.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _HP_UTIL_UTIL_ -#define _HP_UTIL_UTIL_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Contains helper functions and data structures used by multiple other subsystems. - */ - -namespace util -{ - void sleep(const uint64_t milliseconds); - - void mask_signal(); - - void fork_detach(); - -} // namespace util - -#endif diff --git a/src/msg/bson/usrmsg_bson.cpp b/src/msg/bson/usrmsg_bson.cpp index 7f8eb79c..2505e734 100644 --- a/src/msg/bson/usrmsg_bson.cpp +++ b/src/msg/bson/usrmsg_bson.cpp @@ -161,6 +161,31 @@ namespace msg::usrmsg::bson encoder.flush(); } + /** + * Constructs a hpsh response message. + * @param msg Buffer to construct the generated bson message into. + * Message format: + * { + * "type": "hpsh_response", + * "reply_for": "", + * "content": + * } + * @param content The contract binary output content to be put in the message. + */ + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) + { + jsoncons::bson::bson_bytes_encoder encoder(msg); + encoder.begin_object(); + encoder.key(msg::usrmsg::FLD_TYPE); + encoder.string_value(msg::usrmsg::MSGTYPE_HPSH_RESPONSE); + encoder.key(msg::usrmsg::FLD_REPLY_FOR); + encoder.string_value(reply_for); + encoder.key(msg::usrmsg::FLD_CONTENT); + encoder.byte_string_value(content); + encoder.end_object(); + encoder.flush(); + } + /** * Constructs a contract read response message. * @param msg Buffer to construct the generated bson message into. @@ -196,7 +221,7 @@ namespace msg::usrmsg::bson * "ledger_hash": , * "outputs": [, , ...], // The output order is the hash generation order. * "output_hash": , [output hash = hash(pubkey+all outputs for the user)] - * "hash_tree": [], // Collapsed merkle tree with user's hash element marked as null. + * "hash_tree": [], // Collapsed merkle tree with user's hash element marked as null. * "unl_sig": [["", ""], ...] // Binary UNL pubkeys and signatures of root hash. * } * @param hash This user's combined output hash. [output hash = hash(pubkey+all outputs for the user)] @@ -466,7 +491,7 @@ namespace msg::usrmsg::bson /** * Extracts a contract read request message sent by user. - * + * * @param extracted_content The content to be passed to the contract, extracted from the message. * @param d The bson document holding the read request message. * Accepted signed input container format: @@ -497,30 +522,30 @@ namespace msg::usrmsg::bson return 0; } - /** - * Extracts a contract shell input message sent by user. - * - * @param extracted_content The content to be passed to the contract, extracted from the message. - * @param d The bson document holding the shell input message. + /** + * Extracts a hpsh input message sent by user. + * + * @param extracted_content The content to be passed to the hpsh, extracted from the message. + * @param d The bson document holding the hpsh input message. * Accepted signed input container format: * { - * "type": "contract_shell_input", + * "type": "hpsh_request", * "id": "", * "content": * } * @return 0 on successful extraction. -1 for failure. */ - int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d) + int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d) { if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) { - LOG_DEBUG << "Shell input 'id' field missing or invalid."; + LOG_DEBUG << "Hpsh input 'id' field missing or invalid."; return -1; } if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is_byte_string_view()) { - LOG_DEBUG << "Shell input 'content' field missing or invalid."; + LOG_DEBUG << "Hpsh input 'content' field missing or invalid."; return -1; } @@ -532,9 +557,9 @@ namespace msg::usrmsg::bson /** * Extracts a signed input container message sent by user. - * + * * @param extracted_input_container The input container extracted from the message. - * @param extracted_sig The binary signature extracted from the message. + * @param extracted_sig The binary signature extracted from the message. * @param d The bson document holding the input container. * Accepted signed input container format: * { diff --git a/src/msg/bson/usrmsg_bson.hpp b/src/msg/bson/usrmsg_bson.hpp index 9a511f36..cc06be4f 100644 --- a/src/msg/bson/usrmsg_bson.hpp +++ b/src/msg/bson/usrmsg_bson.hpp @@ -17,6 +17,8 @@ namespace msg::usrmsg::bson void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); + void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); void create_contract_output_container(std::vector &msg, std::string_view hash, const ::std::vector &outputs, @@ -43,7 +45,7 @@ namespace msg::usrmsg::bson int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); - int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); + int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::ojson &d); diff --git a/src/msg/json/usrmsg_json.cpp b/src/msg/json/usrmsg_json.cpp index a867e99d..58d271cb 100644 --- a/src/msg/json/usrmsg_json.cpp +++ b/src/msg/json/usrmsg_json.cpp @@ -34,7 +34,7 @@ namespace msg::usrmsg::json * Constructs user challenge message json and the challenge string required for * initial user challenge handshake. This gets called when a user establishes * a web socket connection to HP. - * + * * @param msg Buffer to construct the generated json message string into. * Message format: * { @@ -84,7 +84,7 @@ namespace msg::usrmsg::json /** * Constructs server challenge response message json. This gets sent when we receive * a challenge from the user. - * + * * @param msg Buffer to construct the generated json message string into. * Message format: * { @@ -325,6 +325,52 @@ namespace msg::usrmsg::json msg += "\"}"; } + /** + * Constructs a hpsh response message. + * @param msg Buffer to construct the generated json message string into. + * Message format: + * { + * "type": "hpsh_response", + * "reply_for": "", + * "content": "" + * } + * @param content The contract binary output content to be put in the message. + */ + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) + { + msg.reserve(content.size() + 256); + msg += "{\""; + msg += msg::usrmsg::FLD_TYPE; + msg += SEP_COLON; + msg += msg::usrmsg::MSGTYPE_HPSH_RESPONSE; + msg += SEP_COMMA; + msg += msg::usrmsg::FLD_REPLY_FOR; + msg += SEP_COLON; + msg += reply_for; + msg += SEP_COMMA; + msg += msg::usrmsg::FLD_CONTENT; + msg += SEP_COLON_NOQUOTE; + + if (is_json_string(content)) + { + // Process the final string using jsoncons. + jsoncons::json jstring = content; + jsoncons::json_options options; + options.escape_all_non_ascii(true); + + std::string escaped_content; + jstring.dump(escaped_content); + + msg += escaped_content; + } + else + { + msg += content; + } + + msg += "}"; + } + /** * Constructs a contract read response message. * @param msg Buffer to construct the generated json message string into. @@ -381,7 +427,7 @@ namespace msg::usrmsg::json * "ledger_hash": "", * "outputs": ["", "", ...], // The output order is the hash generation order. * "output_hash": "", [output hash = hash(pubkey+all outputs for the user)] - * "hash_tree": [], // Collapsed merkle tree with user's hash element marked as null. + * "hash_tree": [], // Collapsed merkle tree with user's hash element marked as null. * "unl_sig": [["", ""], ...] // UNL pubkeys and signatures of root hash. * } * @param hash This user's combined output hash. [output hash = hash(pubkey+all outputs for the user)] @@ -566,12 +612,12 @@ namespace msg::usrmsg::json * { * "type": "health_event", * "event": "proposal" | "connectivity", - * + * * // proposal * "comm_latency": {min:0, max:0, avg:0}, * "read_latency": {min:0, max:0, avg:0} * "batch_size": 0 - * + * * // connectivity * "peer_count": 0, * "weakly_connected": true | false @@ -697,7 +743,7 @@ namespace msg::usrmsg::json /** * Verifies the user handshake response with the original challenge issued to the user * and the user public key contained in the response. - * + * * @param extracted_pubkeyhex The hex public key extracted from the response. * @param extracted_protocol The protocol code extracted from the response. * @param extracted_server_challenge Any server challenge issued by user. @@ -842,7 +888,7 @@ namespace msg::usrmsg::json /** * Extracts a contract read request message sent by user. - * + * * @param extracted_content The content to be passed to the contract, extracted from the message. * @param d The json document holding the read request message. * Accepted signed input container format: @@ -872,30 +918,30 @@ namespace msg::usrmsg::json return 0; } - /** - * Extracts a contract shell input message sent by user. - * - * @param extracted_content The content to be passed to the contract, extracted from the message. - * @param d The json document holding the shell input message. + /** + * Extracts a hpsh input message sent by user. + * + * @param extracted_content The content to be passed to the, extracted from the message. + * @param d The json document holding the hpsh input message. * Accepted signed input container format: * { - * "type": "contract_shell_input", + * "type": "hpsh_request", * "id": "", * "content": "" * } * @return 0 on successful extraction. -1 for failure. */ - int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d) + int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d) { if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) { - LOG_DEBUG << "Shell input 'id' field missing or invalid."; + LOG_DEBUG << "Hpsh input 'id' field missing or invalid."; return -1; } if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is()) { - LOG_DEBUG << "Shell input 'content' field missing or invalid."; + LOG_DEBUG << "Hpsh input 'content' field missing or invalid."; return -1; } @@ -906,9 +952,9 @@ namespace msg::usrmsg::json /** * Extracts a signed input container message sent by user. - * + * * @param extracted_input_container The input container extracted from the message. - * @param extracted_sig The binary signature extracted from the message. + * @param extracted_sig The binary signature extracted from the message. * @param d The json document holding the input container. * Accepted signed input container format: * { diff --git a/src/msg/json/usrmsg_json.hpp b/src/msg/json/usrmsg_json.hpp index eef0e06c..ff5c827d 100644 --- a/src/msg/json/usrmsg_json.hpp +++ b/src/msg/json/usrmsg_json.hpp @@ -21,6 +21,8 @@ namespace msg::usrmsg::json void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); + void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); void create_contract_output_container(std::vector &msg, std::string_view hash, const ::std::vector &outputs, @@ -47,7 +49,7 @@ namespace msg::usrmsg::json int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); - int extract_shell_input(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); + int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::json &d); diff --git a/src/msg/usrmsg_common.hpp b/src/msg/usrmsg_common.hpp index d8682e49..6844e578 100644 --- a/src/msg/usrmsg_common.hpp +++ b/src/msg/usrmsg_common.hpp @@ -80,8 +80,8 @@ namespace msg::usrmsg constexpr const char *MSGTYPE_SERVER_CHALLENGE_RESPONSE = "server_challenge_response"; constexpr const char *MSGTYPE_CONTRACT_READ_REQUEST = "contract_read_request"; constexpr const char *MSGTYPE_CONTRACT_READ_RESPONSE = "contract_read_response"; - constexpr const char *MSGTYPE_CONTRACT_SHELL_INPUT = "contract_shell_input"; - constexpr const char *MSGTYPE_CONTRACT_SHELL_OUTPUT = "contract_shell_output"; + constexpr const char *MSGTYPE_HPSH_REQUEST = "hpsh_request"; + constexpr const char *MSGTYPE_HPSH_RESPONSE = "hpsh_response"; constexpr const char *MSGTYPE_CONTRACT_INPUT = "contract_input"; constexpr const char *MSGTYPE_CONTRACT_INPUT_STATUS = "contract_input_status"; constexpr const char *MSGTYPE_CONTRACT_OUTPUT = "contract_output"; diff --git a/src/msg/usrmsg_parser.cpp b/src/msg/usrmsg_parser.cpp index d87822f4..69a3e4bd 100644 --- a/src/msg/usrmsg_parser.cpp +++ b/src/msg/usrmsg_parser.cpp @@ -38,6 +38,14 @@ namespace msg::usrmsg busrmsg::create_contract_input_status(msg, status, reason, input_hash, ledger_seq_no, ledger_hash); } + void usrmsg_parser::create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const + { + if (protocol == util::PROTOCOL::JSON) + jusrmsg::create_hpsh_response_container(msg, reply_for, content); + else + busrmsg::create_hpsh_response_container(msg, reply_for, content); + } + void usrmsg_parser::create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const { if (protocol == util::PROTOCOL::JSON) @@ -121,12 +129,12 @@ namespace msg::usrmsg return busrmsg::extract_read_request(extracted_id, extracted_content, bdoc); } - int usrmsg_parser::extract_shell_input(std::string &extracted_id, std::string &extracted_content) const + int usrmsg_parser::extract_hpsh_request(std::string &extracted_id, std::string &extracted_content) const { if (protocol == util::PROTOCOL::JSON) - return jusrmsg::extract_shell_input(extracted_id, extracted_content, jdoc); + return jusrmsg::extract_hpsh_request(extracted_id, extracted_content, jdoc); else - return busrmsg::extract_shell_input(extracted_id, extracted_content, bdoc); + return busrmsg::extract_hpsh_request(extracted_id, extracted_content, bdoc); } int usrmsg_parser::extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const diff --git a/src/msg/usrmsg_parser.hpp b/src/msg/usrmsg_parser.hpp index 8d721416..8ca9ce2d 100644 --- a/src/msg/usrmsg_parser.hpp +++ b/src/msg/usrmsg_parser.hpp @@ -26,6 +26,8 @@ namespace msg::usrmsg void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash) const; + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const; + void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const; void create_contract_output_container(std::vector &msg, std::string_view hash, const ::std::vector &outputs, @@ -49,7 +51,7 @@ namespace msg::usrmsg int extract_read_request(std::string &extracted_id, std::string &extracted_content) const; - int extract_shell_input(std::string &extracted_id, std::string &extracted_content) const; + int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content) const; int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const; diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 6871841c..096646dd 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -273,19 +273,13 @@ namespace usr user.session.send(resp); return 0; } - else if (msg_type == msg::usrmsg::MSGTYPE_CONTRACT_SHELL_INPUT) + else if (msg_type == msg::usrmsg::MSGTYPE_HPSH_REQUEST) { std::string id, content; - if (parser.extract_shell_input(id, content) != -1) + if (hpsh::ctx.is_initialized && parser.extract_hpsh_request(id, content) != -1) { - - LOG_INFO << "shell input received:" << content; - // std::string response = hpsh::serve(content.c_str()); - if (hpsh::execute(std::string("user_").append(std::to_string(1)), content.c_str()) == -1) - { - std::cout << "\nError sending message:" << content.c_str() << std::endl; - } - // LOG_INFO << "response: " << response; + if (hpsh::execute(id, user.pubkey, content.c_str()) == -1) + return -1; return 0; } diff --git a/test/bin/hpsh b/test/bin/hpsh index cf4cd294fed5b325afc51a1f7a4991fb72754f66..eb008ec0da3b9d4a9102b07d8298226fcf14cb78 100755 GIT binary patch delta 7699 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 delta 7697 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 From bc37c76a93234c23bfb260b9066b9d1429900cc8 Mon Sep 17 00:00:00 2001 From: chalith Date: Tue, 31 Oct 2023 14:04:24 +0530 Subject: [PATCH 11/23] Updated hpsh binary --- test/bin/hpsh | Bin 33952 -> 18752 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/bin/hpsh b/test/bin/hpsh index eb008ec0da3b9d4a9102b07d8298226fcf14cb78..83eb98762dfb435a71ee8253cf86f28388699370 100755 GIT binary patch literal 18752 zcmeHPeRNyJl^
_B2Ul#f7I@(2QwhA6h<1SgP2a_r=pD#4ANhNZxZBFVN6`Y_TH zI4n@Jb|Au0nzFRerRAgxyReil^qg)t&DnxOAPIjI0vtGWSz2#TbCCE-a7hWD+TWcw z^ZfLpx7*V0*?&Aa@}2ve`!RE8-g~3byZL5Ea7~rV#bj}_uQ1}2vkk;A8vFrK0r9g| zHWPmpHkVBUU(GS2-ER=I8s)XBa#|;FHz?`Nrb-2Rt^qSiWeSTGF#{}5T6~$5ubH<~ zzsLuzskQ4jGEB=DVIqutE>0IbweNZG;mdFE{>{s)Bgvcoqxg1l#kyboTG}9=BtwPt z#T0X%>KEWcGRF9C#~e0r%nR(r=<|sS6Ejw$TCuDJdRm2+M`5@UeyxN22M+ja4){R_ z`wuwCZ+4JB;($NzfIsAbzwUsyAh4C<@PGsUxPzT82l-bW>xkxfWPB_ zzv|G>E(iI`9OUnD=;tip3O@ES>R|sp2m2)l`C%9)ANHaHQ0yT1MGp8F@JjQ341VXK z&0gLDFpJG$ir;8yK)-pxePTfGPe(%$x;Zp5t+QvH7Kx^#eX)!lP4}!@9Zw~rJ)te} zsL@urMT@4>$&?mPg+qEQm1JZPf5JB=GJOm_GI}Jua3Q%^#x$)jkxFVAJ(SipjcHf+ zbav~@ql4k-0N2&7Uf-RHXF6hN>eicEGz}e0-K52mH-_S|h!#rsWfRe)-u2ZmB-VH9 zt+7-_+Y-t|TRM|5y}ha9M)(L1hO{jhMN&hT!u{MrGAJ{!m)e)1jE2=?r&thw!IkSvs1D-5l*mkk3fGi(K>#4r&9@bS9NVzx1uz zjR+rl+_X&7Qm_{dCD7+gG_6-M+pz(XOAO~iy0b^?Y1BHpmuX#J?OvkAxwUu((Xscb zl5)5Qs!O3-F)FKhR47`1>d2RC>$ETiqenY7Boe$&&5d$SQdwO~^=j!*vM*>m@pfb;Np8>FW`5 zteWukTDbputv3{lGlW@BaT1Rv#jK;JgE5^&vIEU*AQg|ZL^Kf|*h+wq=#9~g-Ha8j zksGlT6QNj=tzErZTY~FgZLqU#^;K7)-r`$sRd~AAfKJ1|T2T5&^*T14*Q-!Buo}qGQ}YyPkPH=Sn}+A9i`|NAou1(e zK3x}WJ(c8U(E}L81&t^uwRho@`{n{jPiJSNoiKgD-Pl4+V;2kl<;SnbR-lG05&R7& z?uC3c`-*AL&Hi5a^F#miSZpTk!qy4-d%pc$bg!0e5`6ZY*mT+rY%%qz$A)hZX0%tC z?Q(x9_jT+Xl49%$v452K_-q5;W5dV9e!tFdv`cx(A6{kP6vGRQD*yYM1)pQV$1V7I z7QA4=6$^gMf}d}}PgwAI7QDf4Fcg!y7JRk^7enH$ioj{VM*AjNPJG3v)q;>Mvk1S0 zW7^D8XTinP@U{jEPWw7pW?OLbEsJ8ojdf|X%(vj=Tb4!(F6V~YS}iyhj9L5^Tzs|R zZK?&wf;UT-1)pJ}j9q2Hv0%-z*@D-bC}aH=TznPdtpgUEt{+(jEx7f$K4ihI&*|+J z{7cdZ=q?LR`)*n8v*2e)5OlW%KhuIgV!_X{;7?d^aS8F(Jr-PCavUGC;OAQG9J1hl zWx@Zys=xP~_pv(sPMtbh^Q*;-soTc%s?uR~_?f!>yi28}Px}~~C|$T8#50$Xd_T2J z6#uJKD(&JtT{siP7fqfnn2F*(lcx)1qWBY&rwe4F_(PMY3uB`AZIh=9VxoAv$nK2hD@Fo{zUO>CQl1~q8KoFTIdtSCX=THK2bd1=3o)#j;FL}(~5$uCKbK4o8Kk%R7c)`jaxAE`V_#-y{4IBT8jsK;Mf7ZtT z!p8rrjsLNY|3@4D0~`Mx8=trF+id);Ha=_P6E;3-x8*ThL8{c8$SK9ccHhz)h z1H-FW*4>d?td9P>cL?(uT>hqBQ#g*fRdc^la|Ly{;L7$EA^`T%x>EB?Yp|Zx{K^1q zsJUkgACc^62kJ*lT@7fM&l?UD#<-D#(70&^V+C5Dg&-Dvkq)!e(ObNm)yr=2*1_E! zT=HmPJzDu417_!;{`OnM1vUk~9@rS@+1Rb#{>~xvA)=1XxNtsoCbz@82ej$A;gZX< z^EuoY)X`*}nji5F0S@LL^6mmvbJgBp?jeq;+urqz+(Ux7qlE`PqhYptmCoF=>hKAV z=gw8sGJL}2*)|U~&(AQd{54)>`-ov^6te2*J%**+h<7`zAE>T^*T*NJj_pJULapzD~r{E+9) zJ0Q`XJHG9u3KP^rwuV11c}6a#9_QP=18N=-ZF=cR>*x5Gb*?A>I3;*y5 zXGU&7e?7U&0R=`c#p-)>0X!auB)5ab_bc4K)!ac$abZ2+UVdNNOQS^N8)yt-CA6TW z_#u{|h=*b8IQ>ukM4g`2bUKCfVYFF1A1*frbdByVW)x5r(Wb& zjsY)xgP_q7ei=m6CDr`8$X>19{>&k03?C|e^8rY|>{8%9OOko2UzIHHm2=#-I zdXn0}7QV}E%zTubjJ9~ye9gV6_Nt!bA^NkA&pRBBkifwa?|smt((8%u^DL0DGh$X) zPL|1kd+yD`<!-s&hcHlA8aJ*FsZZk@S{cO{Sa#t?b$I2+7gDEkNAwvO=0#8|eDom}MFd?u zP_q(pu4|#otop^9&}fNQU{f%^a&#V+&DT3~uLd@D=8gw?0=Z8&s`*7DfV+bWKBGNj z;i=;Y=DyF|`rM}1g?=zM5zM`ZnGcjs|BX7l-=!{pBl{MG+Op1jCu2jSSEvmec21^VgHI1bh4dF z;tV+()|F&79#@hnUE#kn2!#$ht5)dj8AcSnKdOZLWATVGkWPi8nT!udt{FWQW88mt zDtvuZKiRioB$ib8Y4oBnTf8NfT#T;tGoy)4xU;(HA(cpkk`W*4G=A`~jBAC0e!1qj zFY5xuE{$Dsv{a&}{X54>rN=-&1$_qev58V?2v7Oo?@OgmsT~i|`@mmvqEw25KNmZN zpMu{3`YEV9b8_9hfw=}7TytjB*6k8F?dtYGALlFB6xB8m@#52h&+hk1r7_5{`i3?2 zv#;=+dQ;sHTXoKgFE8=pNo&}>2DBCZ;)(>KkUt%tM&M77z9{62itFaCAn!@-{Y!EF zI!E@0#!bFejPHBZIH9hE@|yaFZ&kI`&)(^7t5@>XZT0ha)CB4q@0b>-Zyl~(TR&9g z{<8a&`quXP#z6gi$UwHOzM-wYEajCKX~!pmw#|rRlmOo6PU>?9^|^!k zjQ-s*O*Q)LPu90$47UFAv-`(jXFKfFkR4G<_b+gr_d?YRRiD?feKpJPn(oR^yPmPz zYiAv;bMLKN2pC$ovT+2sbpIKyQ`#2Y?P7TsY;gRL47@ZrMW-S#6@jS;OhsTS0#gx~ ziojF^{=5i?A6Mo33-WyhY`%E0Q@%$;i^S<&4=R$UcQL5UFo^kL1)U>P*)IIacL?PB z6?2SczK^7;5M%Ov3b_q5cCC!zhnf`0?Z(MH6}jj1*BbmZgRn!QUH(>|6ukV6p7zF6 ztiNFsFT~imc#lC0i)|Mb+G|r0?wI+Twiu|y4+%%I->o80^c{(c^e^A#ka9S9<>P}m zhj2pA`4eIwI9cR8zH0D-uPdDY7txNdPi5^w>@P;-d((DswJbuD;oF!CD&V zjjq;;xSPrMvn}FS^VRH@it;t)byhAv&Ah(K@meOY!*aZi$@N)|PiJynm*b}}dHs~* zxTxd}#nRxWyN+BRW%x{{RK)Aqc!l|OGY>mf5pQ6-tuMz2A8t0wysuf@BA$3*L9rr6 z-OavazMpSxb>kbndcGBr@@KHR3o7AfGI{^Bwz_dQlK0JWd^W3e-MZP?=6$YQ9(Q5C z6*1~=%lo?4R=1f|GKtdduA04Hnna8m-KMHASu&oxg#g`G375|!eqI4=K0Yq^Z3-BI zWS7dN_*Amr2Au44$p;MyqtJN=;X^ijlfdQkk7TJN@FBmAHov!U{Ny-42%PMj4>0gl z9>>SUPM$BP{y)#2)1@q4)V45FEu{-m=L-KIVYm=74{Q`^bAV1)M?*LBm zR7C%U8Frt8{J2B^k3*i;A+y=3#=JM+dT$L#%Lc8&d{!FonGX1T2fW(>j{+yZ_Ho_d zApf@x_`@7;U=0`=6}eykHwXEb9q(DyZw^M?PhU_@4LlvOfzJY1&f4x4iu5&fo%9Jr^E5K7^%s5=RW=(eo zQbYo6!49&DJPJ$7jo;5x7La~GnFd-k64FCFX`;MAjrB$K^DmWMQaQZ5r8x{;AGsX#Ntvs%g_%2+8!j8r3m8S(w1 zNkKLvwnUmqw=I}1WPQoC`}$~M!TZ0q{u{IGHXndfHn@jqqYmE}l5 zPh=~7p$oV?v8${Tl+9!rE8PnvZ=~(f%~)v2JC1GXm)V1IdCnh=v2rFM793C0v+18a zJCx^FF2sD9tqDD}1r%vvoc7CFEQxH!0p`OG{83+DGV8-H_{iPUw_2brS^TuWC>9YA zvb+}Qp+3gN`{~zuUu0_%E)1%tjg}jc0Z1v2Tud+;+S1W@h!jL^Ag(hX-RzkURbO99 zR5H;p^C4pmEDy6Uo#MA{U$kF5WcnkpCONo4%AAobsbP$`2Xd>%^T)6u>u?@Q#9-bq zh{ex*c=l25r1cs8=hW#u5nDNi?H@1ld_+=to+z5RtgI8g03SNTllraLFH(_I;oRgO zd2T0>WvE#7uM+x_dZnPC*lv}TPH=u`hGcC!BhW_f{2eR&QgsXWJ({-wSg|Gh%LO&XNv zRf5WMWYVXj2)q6dfl*APeSA4EilFkmT%ae-|M$^g)mMa`q+_;#+sw0vZTjP4^DU{A zm;NO$=@T}6d7dVz_1zk>A@wBvxlP|ZClcpxN6f&G_N2bSG4>QH*73{V9VC_0A?5AY z&$B{b&OcLxq@WXml|;^;a)m6~Rg(^(22D zlnImm6~ED<2z|0|EsB*v{Q}`%h?}iaf1!yO6=}{&<=V4~b_s)n;s+@D-KiNL*?)Qe jqGs85tNx+o2G?P`{-j?iOSg+k`ZN88#3eQb8_WJ1?ebF2 literal 33952 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 jV#;Gc&`$Lrw}e%`DlT=Cs_Y6Q+WEf(x6qcr# Date: Tue, 31 Oct 2023 17:29:16 +0530 Subject: [PATCH 12/23] Introduced terminate control message --- src/hpsh/hpsh.cpp | 18 ++++++++++++++++-- src/hpsh/hpsh.hpp | 2 ++ test/bin/hpsh | Bin 18752 -> 18752 bytes 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index 50ac92e3..815abedc 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -2,6 +2,8 @@ namespace hpsh { + constexpr const char *HPSH_CTR_SH = "sh"; + constexpr const char *HPSH_CTR_TERMINATE = "terminate"; constexpr uint32_t POLL_TIMEOUT = 1000; constexpr uint32_t READ_BUFFER_SIZE = 128 * 1024; @@ -22,7 +24,7 @@ namespace hpsh ctx.hpsh_pid = fork(); if (ctx.hpsh_pid == -1) { - LOG_ERROR << errno << ": Error forking."; + LOG_ERROR << errno << ": Error forking hpfs process."; close(ctx.control_fds[0]); close(ctx.control_fds[1]); return -1; @@ -42,6 +44,7 @@ namespace hpsh std::string fd_str; fd_str.resize(10); snprintf(fd_str.data(), sizeof(fd_str), "%d", ctx.control_fds[0]); + char *argv[] = {(char *)conf::ctx.hpsh_exe_path.data(), fd_str.data(), NULL}; // Just before we execv the hpsh binary, we set user execution user/group if specified in hp config. @@ -78,7 +81,7 @@ namespace hpsh ctx.is_shutting_down = true; if (ctx.hpsh_pid > 0) - kill(ctx.hpsh_pid, SIGTERM); + send_terminate_message(); // Joining consensus processing thread. if (ctx.watcher_thread.joinable()) @@ -138,11 +141,22 @@ namespace hpsh } } + int send_terminate_message() + { + return (write(ctx.control_fds[1], HPSH_CTR_TERMINATE, 10) < 0) ? -1 : 0; + } + int execute(std::string_view id, std::string_view pubkey, std::string_view message) { if (ctx.is_shutting_down) return -1; + if (write(ctx.control_fds[1], HPSH_CTR_SH, 3) < 0) + { + LOG_ERROR << errno << ": Error writing header message to control fd."; + return -1; + } + int child_fds[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, child_fds) == -1) { diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index 7f902cf2..11a5d7a8 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -35,6 +35,8 @@ namespace hpsh int check_hpsh_exited(const bool block); + int send_terminate_message(); + int execute(std::string_view id, std::string_view pubkey, std::string_view message); void response_watcher(); diff --git a/test/bin/hpsh b/test/bin/hpsh index 83eb98762dfb435a71ee8253cf86f28388699370..4a225764dc18d461bf713c00e44f0230069a6910 100755 GIT binary patch delta 2577 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 Sje@LT!+cdU_zo4cY5oI~ksaOu From 835b702e7e7cc955ba573d96864c76a5ade81524 Mon Sep 17 00:00:00 2001 From: chalith Date: Tue, 31 Oct 2023 18:31:06 +0530 Subject: [PATCH 13/23] Remove command when user disconnected --- src/hpsh/hpsh.cpp | 30 +++++++++++++++++++----------- src/hpsh/hpsh.hpp | 6 ++++-- src/usr/usr.cpp | 10 ++++++++-- test/bin/hpsh | Bin 18752 -> 18752 bytes 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index 815abedc..6700190b 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -146,7 +146,14 @@ namespace hpsh return (write(ctx.control_fds[1], HPSH_CTR_TERMINATE, 10) < 0) ? -1 : 0; } - int execute(std::string_view id, std::string_view pubkey, std::string_view message) + void remove_user_commands(std::string_view user_pubkey) + { + std::scoped_lock lock(ctx.command_mutex); + ctx.commands.remove_if([&](const command_context &command) + { return command.user_pubkey == user_pubkey; }); + } + + int execute(std::string_view id, std::string_view user_pubkey, std::string_view message) { if (ctx.is_shutting_down) return -1; @@ -203,9 +210,11 @@ namespace hpsh return -1; } + close(child_fds[0]); + { std::scoped_lock lock(ctx.command_mutex); - ctx.commands.push_back(command_context{std::string(id), std::string(pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); + ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); } return 0; @@ -219,6 +228,8 @@ namespace hpsh { if (ctx.commands.size() > 0) { + std::scoped_lock lock(ctx.command_mutex); + auto itr = ctx.commands.begin(); while (itr != ctx.commands.end()) { @@ -262,7 +273,7 @@ namespace hpsh std::scoped_lock lock(usr::ctx.users_mutex); // Find the user session by user pubkey. - const auto user_itr = usr::ctx.users.find(itr->pubkey); + const auto user_itr = usr::ctx.users.find(itr->user_pubkey); if (user_itr != usr::ctx.users.end()) // match found { const usr::connected_user &user = user_itr->second; @@ -272,10 +283,10 @@ namespace hpsh user.session.send(msg); } } - { - std::scoped_lock lock(ctx.command_mutex); - itr = ctx.commands.erase(itr); - } + + // Close the file descriptor and remove the command from context. + close(itr->child_fds[1]); + itr = ctx.commands.erase(itr); } else { @@ -283,10 +294,7 @@ namespace hpsh } } } - else - { - util::sleep(1000); - } + util::sleep(1000); } } } \ No newline at end of file diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index 11a5d7a8..24dd2c9d 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -10,7 +10,7 @@ namespace hpsh struct command_context { std::string id; - std::string pubkey; + std::string user_pubkey; int child_fds[2]; std::string response; bool read_completed = false; @@ -37,7 +37,9 @@ namespace hpsh int send_terminate_message(); - int execute(std::string_view id, std::string_view pubkey, std::string_view message); + void remove_user_commands(std::string_view user_pubkey); + + int execute(std::string_view id, std::string_view user_pubkey, std::string_view message); void response_watcher(); } diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 096646dd..14a6760b 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -420,8 +420,14 @@ namespace usr */ int remove_user(const std::string &pubkey) { - std::scoped_lock lock(ctx.users_mutex); - ctx.users.erase(pubkey); + { + std::scoped_lock lock(ctx.users_mutex); + ctx.users.erase(pubkey); + } + // Remove any hpsh commands sent by the user. + if (hpsh::ctx.is_initialized) + hpsh::remove_user_commands(pubkey); + return 0; } diff --git a/test/bin/hpsh b/test/bin/hpsh index 4a225764dc18d461bf713c00e44f0230069a6910..464264046384853e748562115621245fdc02a0e2 100755 GIT binary patch delta 1066 zcmX|ATWpI_96zV)tnD^mH)h)1yUtdZxa`7EQAWSTc)*NAVwmyZGBK10m3H`2O=d@e z%!A8=d9vht*+eKdTOy(pBVJq{BwvGUbDbf_@AP9Q>G}Qsx8MJNPQMdrqmee+I+a?_ z*@nz5$t1p7)HJ%2rdbPga~zpscr&?Yp}j+Ue!a@%E6Kif_|&ge-yIS4Si)wLZP>2o zcP`e^qyvevk>pI;shU$BC((R1IO%M9KSB+1$XHYYA}c{>7dtSyt8kN%5Km}IV9X%} z1@A)C-_5aV=%`%TFP&bluF1%y^oqJ?$_|<-;tg`CE+e({3bB(t{VbOG>qP3OBv|3Z z*8)P#PE(^S?d=!aeK}O+te3;?MqPtNaBuqtIp z+b#?P4DdQ|PpASqPo^Pn>KNy@vqfdN{BROE0fjzU>DBfl4X$L-3suWt-V<`#u6V%x zbprUEQIX`<1oy-LMamtMm50^JU~FXE?2T=B2YTSoNEb9*UWRb&IFsz2S*H#q10>OPf6HqzYoFRu2j|<)s zX*Tn>Ql1|}lZXEh`8VVF<=0rqo=t06hdtMI5IxAj8MSi2Z9xpjZvS~)!HJlyMQTz_PoM|-L+$$DU95refY ze}KKnUs6YCR>Gq75I5sz9pd~9Fgnb6C-5y$d|R!bIS=BNmww@#03*2H%Rqt~YXS@d zyI|Mj3W)eW32Q8H&@)UaVDu==5dXl%1wH46WD)sr?l<;Ihr%Nhx6`7u=vts;hE-3LRuySIjp1vUEisyR^bfQ`tNC M#-F`vTUng&7gE<~#Q*>R delta 1077 zcmX|BT}%^M7@e=QON(6x5X6E4tp%-$3Kf*Bb*%wAB*ZAf8WR(D4I&SSF`|jlgc@pO zQk!6JjF^2{pL|dglkow3fU2MvjSCO1nrs4^kWAxdE8-8h?aD7Ex~&~udYB5v=54%&jeLGon4KGW$>IfH zyDih1$Ra<#6%g)nTiX=5b4-a?#!(RQJ>^lz{TC!+i5dC@hU?tFx5*v%l!)&ph_WZ- z4yOBkKz+{_&W8w5otn^_MPfpNSV8O$*FZN^4qmq{$@$&oLK>+)DrQh0De9V3+PSWLC2Z*w@%dPnjZdXFdXPr&ug>$UqwGxKa;j(jg~gu3*h4zGwngdjCEW-W zb-K%rG0H*JzkK3cZ^f1mEj~6`xTY+O_s#!XgZhuZr9u7ZZ}zLH79~; zi9QavAGsaJ(t$h$yo0<0N01`c=5$d%Q=N=dw!*cV`q)mF5BHF3JvGMa;D66m+LIT_8LQ)f|J>@tW&YsyQ|vA Date: Wed, 1 Nov 2023 13:53:19 +0530 Subject: [PATCH 14/23] Changes to support follow commands --- examples/js_client/text-client.js | 6 ++- src/hpsh/hpsh.cpp | 66 ++++++++++++++---------------- src/hpsh/hpsh.hpp | 2 - src/usr/usr.cpp | 2 +- test/bin/hpsh | Bin 18752 -> 18752 bytes 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/examples/js_client/text-client.js b/examples/js_client/text-client.js index d402ac47..36e4e16d 100644 --- a/examples/js_client/text-client.js +++ b/examples/js_client/text-client.js @@ -124,7 +124,11 @@ async function main() { hpc.getStatus().then(stat => console.log(stat)); } else if (inp.startsWith("hpsh ")) { - hpc.submitHpshRequest(inp.substr(5)).then(reply => console.log(reply)); + hpc.submitHpshRequest(inp.substr(5)).then(id => { + hpc.on(id, (reply) => { + console.log(reply); + }) + }); } else { diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index 6700190b..7e9479be 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -43,7 +43,7 @@ namespace hpsh std::string fd_str; fd_str.resize(10); - snprintf(fd_str.data(), sizeof(fd_str), "%d", ctx.control_fds[0]); + snprintf(fd_str.data(), 10, "%d", ctx.control_fds[0]); char *argv[] = {(char *)conf::ctx.hpsh_exe_path.data(), fd_str.data(), NULL}; @@ -149,8 +149,20 @@ namespace hpsh void remove_user_commands(std::string_view user_pubkey) { std::scoped_lock lock(ctx.command_mutex); - ctx.commands.remove_if([&](const command_context &command) - { return command.user_pubkey == user_pubkey; }); + auto itr = ctx.commands.begin(); + while (itr != ctx.commands.end()) + { + if (itr->user_pubkey == user_pubkey) + { + // Close the file descriptor and remove the command from context. + close(itr->child_fds[1]); + itr = ctx.commands.erase(itr); + } + else + { + itr++; + } + } } int execute(std::string_view id, std::string_view user_pubkey, std::string_view message) @@ -202,7 +214,7 @@ namespace hpsh return -1; } - if (write(child_fds[1], message.data(), sizeof(message)) < 0) + if (write(child_fds[1], message.data(), message.size()) < 0) { LOG_ERROR << errno << ": Error writing to child fd."; close(child_fds[0]); @@ -214,7 +226,7 @@ namespace hpsh { std::scoped_lock lock(ctx.command_mutex); - ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), {child_fds[0], child_fds[1]}, std::string(), false}); + ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), {child_fds[0], child_fds[1]}}); } return 0; @@ -247,29 +259,12 @@ namespace hpsh } else if (pfd.revents & POLLIN) { - itr->response.resize(READ_BUFFER_SIZE); - const int res = read(pfd.fd, itr->response.data(), READ_BUFFER_SIZE); - + std::string response; + response.resize(READ_BUFFER_SIZE); + const int res = read(pfd.fd, response.data(), READ_BUFFER_SIZE); if (res > 0) - itr->response.resize(res); // Resize back to the actual bytes read. - else if (res == -1) - { - // Assuming that EPIPE or ECONNRESET resulted from contract termination, consider this as a neutral read. - if (errno == EPIPE || errno == ECONNRESET) - itr->read_completed = true; - else - LOG_ERROR << errno << ": Error reading from fd"; - } - } - else - { - itr->read_completed = true; - } - - // Send command back to user; - if (itr->read_completed) - { { + response.resize(res); std::scoped_lock lock(usr::ctx.users_mutex); // Find the user session by user pubkey. @@ -279,22 +274,21 @@ namespace hpsh const usr::connected_user &user = user_itr->second; msg::usrmsg::usrmsg_parser parser(user.protocol); std::vector msg; - parser.create_hpsh_response_container(msg, itr->id, itr->response); + parser.create_hpsh_response_container(msg, itr->id, response); user.session.send(msg); + response.clear(); } } + else if (res == -1) + { + LOG_ERROR << errno << ": Error reading from fd"; + } + } - // Close the file descriptor and remove the command from context. - close(itr->child_fds[1]); - itr = ctx.commands.erase(itr); - } - else - { - itr++; - } + itr++; } } - util::sleep(1000); + util::sleep(100); } } } \ No newline at end of file diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index 24dd2c9d..c368e991 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -12,8 +12,6 @@ namespace hpsh std::string id; std::string user_pubkey; int child_fds[2]; - std::string response; - bool read_completed = false; }; struct hpsh_context diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 14a6760b..bb0839be 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -278,7 +278,7 @@ namespace usr std::string id, content; if (hpsh::ctx.is_initialized && parser.extract_hpsh_request(id, content) != -1) { - if (hpsh::execute(id, user.pubkey, content.c_str()) == -1) + if (hpsh::execute(id, user.pubkey, content) == -1) return -1; return 0; diff --git a/test/bin/hpsh b/test/bin/hpsh index 464264046384853e748562115621245fdc02a0e2..4b9f3f2603a6d38f3fb3db3a55ec2841e98a773d 100755 GIT binary patch delta 2207 zcmZWrdrT8|9RFPbDG$BMAfr4h9!^A<2o3GUD4lbM99*^`dCtb6q?GJGt{=K}=8Mv_hb#A7 znpYBXN3Az5tWMVr+h5X8qkfPDX*$vIAGs+#6rXq?)*}U?1#cN?j0&~eW z;)U1BI`RKVnYoWuKu z!FIs5-ZL28$8_y?O~neG4jxtKwECsf|Iiox;0H-%IuUUkl3z0lOE zw5McvT43WHgULaTkWssk#kmHG2D=C`u=<>Gy-+9h+l5A!XrEnZB6KOLkOD5Du9F$b zmuV&-{5|}h37GJ{65vR$-!2+t?MZ^IGhi3$&a$#Gr4u-va^JmAMgCx)*z&uFRPtS; zmHtuQw-JtFOW9kz-w#`{Whd9z{2mSiY2MMmkMu}EpKuJCqCvJIlaBtX1>n%(yjc8I znb^z1W>LWsmQtak-Y3Y_>lP%QfBy&s5^|}KkgRVnIPcCx59Y+iY!5V6yLfQ3&pCg>I{8p?f?jtva&gBPD&p^XexX66wRSU?-tyl1em zLF>^t9CE)y?xWqn>4XCldsaj4lpoU1S*DT2x`5!hPQOU2Q-fF`{ERU{_u>b(HQF5g~P zE3Ox7#SP-dbN?;{t$6(G2G|iL3ux%--d<$;bogeN(ff}yjnBk7B!9y6SXK1s$qTF$ zk=j|(7KB4L<|64xlRjcGg4WVV8C$@HH^W=+JsM?X8#YOEm4sA_=N7$+IN=p+HG|~` zVlnz}A?Tc?=^B+Wj&P?6sl&)Mn<#PuHNGPC-XEUEJ z=JPRp*3n)~TiygMEz{|GMvsH;X0xVAh}n%Bfrz+cV!(7UF`5T3%si0AEvIOQ}WgVvv+4QDB;*;>^B8#QGafq0cOZ$d&rbZe+EeS7q2i=8uD zknj%mGj+~mJ6R?Ty#tRR-gCy9xAFAp? zCXi;BYGz=i@!)nL_0Y8{KjlOlWvG`ap#58JrHO9qI7QNxDr1QMKv+b$5h1LOgt z?S};JPooo^iJRG;5cMQJA7Ws=OWHAW^>7LoUs-?)y^RBaCjTHKv~6}_T+-A>d+H-? zN>@7PZ{UVQ=7NjSIPMg^%q6iB*u%cO24cb&U0GJV+=DhYTf?99qIH+R6?%9S4TSP+rHKZsQQ1^k7&jdGCt^5s Ps4|x0R)>x+KWg{~r{Q2i delta 2123 zcmZuye@qi+82+vlDHS<1Frgq6cBqIr5sM-+IW2gN-DaGq%S0PT7&BzUSq3pE)wbZJ zJHxzfZgI(`E>r(f*TpC^*hK^rw}@oUEL(Lt=Rih&QyglC?%w${txbOY>ywCf7 z@AV>kxyW9wE1gSuFC&&1oJjOvP@T*@m)IC*XpLbPmt#upU1U2#zdz)(w9d>r*3$8C z#YkQx+!nXqGVi9%2t2;nI4#CO1~Lrc)W7VoqG^&m7<3Ng;os}$@HqjL zCWOx+>dMrjgu6&~hu%>GsrGpzd?3VB`5sjsGuBSQ?vi^Y|0vIQI#?C|D8~mkn+Os4 zlM~!Zqk1*9uzmOu8nOb@E&qj1ogsU_Ucx2!(IMct zQ1rEO4ScY{5Zg_J57t6<^;gYhRO|UzqfK%C4FlMTf3r-+*Y(G3QykcM}W!LDJjxquzZ?_l|t zS>RZ{^=bYrn1_4D*WO)j7Q7a>ysV%8`hd+NAh0E@lS<6_0Kui4XQg)bUclj$uf19; zt`}>?4dTXgMhl@f!BRYki=n&JhID)T2wei4=uv&gDsCr$NHz@J(-@56SOmrx*~J-H z1-z?t7b~hbvJCTAFw>V<{yN-Qcdn7s0TATu8_#*s$f1VW$8s`Rj)0sEG#BDoHXqu_ zB)l0!#QVMtN)I#Ro}pg650&|#(jF+1GU-npF#Z>IV8bo-6947}_V`9$6Hw?=w`U0L z9+qoB#pr9}Kyr+(g=}2lchgZn9VNT7Py-FNFi^brD7{6m=9s8kVst4~gKvZGsJJr$ zxo1Whr3%VqAMD28);X7aCA#|7Kl=ITCe$!|z#fR+gR7p;aT1~%{eM^hvT6oE8X0(~ zViJf+{$7~VrZ7=)%!fC+L)~a|EN6tZw1fGC-04Ezj}Rm!evlnyquw+r6u*PX!H73e zyT<4E&>A^6b|U_$9`87){$$HC)#R)9ZPR8oqX=m(tdaZ`R=6>P-@HlSQ3{17-osl} zhnjuyFHBb}GYj(f^=bD{pP_A;g%E;ej9fKfn@Xb{(=Ph5g4priHyYbNW7jW5^O#943R&qL_Y}m@l7B?Y& zYatA0t&<0=amd|HBDjBTe;Q|9TJ!-&x;S9y_9I#0ozKolR3oOTQ^r5A;~&)HHnn^9 z2Cg-nQFPUe<5uw!ZVIE#e(XbOA}RR#s!L0%Gb+bE&bki|#+tdC)B`0`O$@1|+H}(v zHqC#+VGLa9TU@KUrSveD63$rgI>!-p=fcBWQ@EgPL6Yf8g1V_{PGW1Ofz}%SxGI6; LoZ$o2pPK##rm8pC From c4c304a10602c3c037e15bec7d35e484267eb240 Mon Sep 17 00:00:00 2001 From: chalith Date: Wed, 1 Nov 2023 16:13:51 +0530 Subject: [PATCH 15/23] Added code comments --- src/hpsh/hpsh.cpp | 17 +++++++++++++++++ test/bin/hpsh | Bin 18752 -> 18792 bytes 2 files changed, 17 insertions(+) diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index 7e9479be..6d5d7d94 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -15,12 +15,14 @@ namespace hpsh if (!conf::cfg.hpsh.enabled) return 0; + // Create a socket pair for the control channel. if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctx.control_fds) == -1) { LOG_ERROR << errno << ": Error initializing socket pair."; return -1; } + // Create a child process for hpsh process ctx.hpsh_pid = fork(); if (ctx.hpsh_pid == -1) { @@ -31,6 +33,7 @@ namespace hpsh } else if (ctx.hpsh_pid > 0) { + // Close child end of socket and start the watcher thread. close(ctx.control_fds[0]); ctx.watcher_thread = std::thread(response_watcher); @@ -149,6 +152,7 @@ namespace hpsh void remove_user_commands(std::string_view user_pubkey) { std::scoped_lock lock(ctx.command_mutex); + // Loop for all the child commands and delete the commands belongs to the user. auto itr = ctx.commands.begin(); while (itr != ctx.commands.end()) { @@ -170,12 +174,14 @@ namespace hpsh if (ctx.is_shutting_down) return -1; + // Send the hpsh request header. if (write(ctx.control_fds[1], HPSH_CTR_SH, 3) < 0) { LOG_ERROR << errno << ": Error writing header message to control fd."; return -1; } + // Create a socket pair to communicate for the hpsh request. int child_fds[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, child_fds) == -1) { @@ -183,6 +189,7 @@ namespace hpsh return -1; } + // Prepare and send the child socket file descriptor with scm rights. struct msghdr msg = {0}; struct cmsghdr *cmsg; char iobuf[1]; @@ -214,6 +221,7 @@ namespace hpsh return -1; } + // Write the request message to the child socket. if (write(child_fds[1], message.data(), message.size()) < 0) { LOG_ERROR << errno << ": Error writing to child fd."; @@ -222,8 +230,10 @@ namespace hpsh return -1; } + // Close the child end of the socket. close(child_fds[0]); + // Add the command to the context. { std::scoped_lock lock(ctx.command_mutex); ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), {child_fds[0], child_fds[1]}}); @@ -252,6 +262,7 @@ namespace hpsh pfd.fd = itr->child_fds[1]; pfd.events = POLLIN; + // If child fd has data to read handle them. if (poll(&pfd, 1, POLL_TIMEOUT) == -1) { LOG_ERROR << errno << ": Error in poll"; @@ -259,12 +270,18 @@ namespace hpsh } else if (pfd.revents & POLLIN) { + // Read the response and send to the user. std::string response; response.resize(READ_BUFFER_SIZE); const int res = read(pfd.fd, response.data(), READ_BUFFER_SIZE); if (res > 0) { response.resize(res); + + // If response contains trailing new line, Remove it. + if (response[res - 1] == '\n') + response[res - 1] = '\0'; + std::scoped_lock lock(usr::ctx.users_mutex); // Find the user session by user pubkey. diff --git a/test/bin/hpsh b/test/bin/hpsh index 4b9f3f2603a6d38f3fb3db3a55ec2841e98a773d..ce2524706564058544078a3d87568ee1162cd1fc 100755 GIT binary patch delta 3381 zcmZ`*4Nz3q6~32cVHb8;7Fl)|`4`$qMNcQOHc4@!iJjI4v+WF_wPH=w>8N9Dlksm7$W-%~+Cnrc{%*f}-+OlJq<3fE zx#v6geD|Jv&VBC=ZRP4#-s^GpWir|3YJ#T-clOSHdM2ZDqNz3#`3lt3_;E zsjmO+{Z(eh%*?Or&rQ66@$oEhm(Rrd;@C{-JQoD%D_7bXv#`f>ho5hG9Z5)Ji*DgU=X@mO1}L*wK?z%Dj%yC#Mtfz^v9yjsW6zO;gGsVk{pJ|SKFcTx-!5jXdxpAD%$K4C9LDhoDujlf5+tKK9nZfz~;dV<1gKyrTcijH)j2p2r2H=nahs{Hd*FF-vxpdrjGNg>D zRt!`Baa~$ArDE+4Wv8%f%Q}0%47XCupQpuT!Ss5#Jz|QUS#EtnPeUDD0q0Q9#zK11 zW8*Gr^Av+j>eNd>vCU(#--R&)MB6E`vs3ObqpyNkJ#N$9vR1d=O3DeX^`C(skYy4XQ-1?h z3+5B_#AyyH2b+{nM_+>bWk<6-GNV_eBKqJsG1?8)k=p@odH#c47cE%(UofwFQP6kS zzKFMSutVSS>5y2N;|#+XKDGqd=|G?AH8avl&{H*G<%tM&!)`41}R+ih6KyHHf+DoS-3 zraWZcM{_1mEi$2o>J~OBpVcjBQm)iJUZ>nz5bP&A7kVhcVKP8ME3ft6ST`G&3+(1 za&yj0Jkn9uD#ne>D|d?bnP`S=r~LYI=TY$yL^EWFmeiLg8F@pxx7Sx$jdZDWy1x2u zWf&FGNBMy;j?9igIi)tF(r{pg^KSC=Bo0x2L%Gw)fFT=bNke&(QKy!y$o7URZZ&oU zb@*Vl)!5;F@-|jmjlCS8CmO5oR_-ZWh(s%<9gR_hyCYa_9rkNj3ylP;c@24+?*9+u CQ{y23 delta 3351 zcmZ`+3s6+o89s;IgsX)1l;Keq=Gj*Hx~12qa=qLBQIk5BrZQt`l*zwc+Fzxz z{R_UjZZfERA9Zu5Bc^G^G_6>4KYx(_U*pF$$P~EJA*_puHbi^>9MvS?91^vt5F~6-KZ3=ycy65K8USk%;lXLlOA)(&JTz+2BIYYc5SE1%B z+OLX8)CSG4f?iZmS)qIAP_mPE($ZunjY1NNM#PKUYr@()4+wi4Zl!VCA2Nf1-ZaFE4Q0Pxu$9SU*7(K zi7^wKqwyQ!zkt4xExhl~z;=pwwJ`SJm$i0nI%8(GL^F7G+YS^zg)P_kjd^P=45_Z9 zV`;^~m6{v9HxOGHZTaeYQ0oRAuhp9G@YirVRa$4#pRHDEw?50u=mV>tyQwB=(9j$31|WB0{WWGN>v4$w%g0h$7eA%DOa3`&ae;g22f+wjM<8Pj9sx6 z-2#6XPiP{4?Q8sns_0F}E1Y6e^13GP$#Nj{d22`t^hkW;Gt!d)2C`89K%}7%4HAen zFNA#{bV|A|bi*y6FUf6o2r3l8Y3YdKWC#|WR>q_QV5Oie%if+3ER-J4hfE3ABdpAv0gNWJqa>K*;EpJ|j=| z!~6lF>?Xd2KFF@iTnP0*xYOM}fRC|+^Z$^UOd2j%ya4oIT{Z_#79Xu|=@gu^^y}Po!S~<5RO{1OW zRw$?4rW4MlF3+vRJ^El!1cR4jwx698)qHBA?&H?bCCLRf>FP~Ivek~E!B zOl!r0E;6qU*wzh;=~zH?54N*Zh=#Vhe+fhCce%R$8^7=Ml5|lp!YAtg1!%3<%cm;E z-h&_m1(0G(GTyEzwrKa8LNU@n3UW#MBUm;22~gr84unnwLw_6J26L4?H7@p|&>rDq zWPB%NYPTq8&v`R)okUp4Ds~obeyalUdQJk)en*gzhQC5OUKFRkyn6p(D9PE2Ah_BG z!xt3|)AM3!ig#uQ!loiYzZ~nd$fLI6E!YD)p{>vlD*6qJC@sH$U!&>yMU~m`&Nj|m z7U*ey!woVJ8tb$ok27GT{nv4Ps}Sm1+�J>p7A~w44v^V3x=+FAN7XrEDJ=c z>j6K~T6s5s{YV|rqxp-BG-9iLr^L;hMkZwWARLck9md)>Da%`Nx}GbtEba~^*wSlQ z+p(^PybTpQ3_eCHN@pfXar#MV9=^-_O3Mp#;X-^w^&#GOo%q>B2pTJ$W10u&pHN|0 z7dO(bGH2oD8?roGs0T9a%QNtlVBn3*Rv|zieN^V>hsjl5SU#A>BFXr~hErYuxx?J_ zr!@W_b1RBxaU4uD+)kZ282xU!-$Jn@vqS%Q>K{ux9jYoWeOhs@UWWuJZV6%_k}`JE z<*H)GS?$B?($Ib?tu96q-s&3ep$(wd(YERu$LK;;L36@->7(jm2g93P4D_}#hKbMm zPH9}cD=~0R9bz?#2?JG8_ye?I)*6(sd-fFMZ={J?XKBbbkIc1k#N>6(x&xXA)lQua zxV7k>zlx`_VXCXkHsInzPuBS#8g(Sfb!!`&_(t5$_DuOEeFr<6Pm^^&M_vX~N^qY;Y z^IJ`dn`ONdv0e2)cj&(ImqZ(z0;-NrF3ZlPM9-f7`54L&D*>2p~0 z^BX1J(nxWi-Fz@nWlf92q1Rns8z|ILld3oK+5G77mbu)bSEir1zmYci?G*6WTJ&n7 m0sW2l8+#PjAu&qmeZP#2zaMC{3^%D*3t57VJe|D3Y5xO!oz_tR From 0f0df5391383246a438d133c6f324065e81f9929 Mon Sep 17 00:00:00 2001 From: chalith Date: Wed, 1 Nov 2023 18:27:05 +0530 Subject: [PATCH 16/23] Added allowed user pubkey list for hpsh --- examples/js_client/text-client.js | 5 +++- src/conf.cpp | 20 +++++++++++++++ src/conf.hpp | 9 ++++--- src/hpsh/hpsh.cpp | 11 +++++--- src/hpsh/hpsh.hpp | 1 + src/msg/bson/usrmsg_bson.cpp | 16 ++++++++++-- src/msg/bson/usrmsg_bson.hpp | 2 +- src/msg/json/usrmsg_json.cpp | 22 +++++++++++++--- src/msg/json/usrmsg_json.hpp | 2 +- src/msg/usrmsg_common.hpp | 3 +++ src/msg/usrmsg_parser.cpp | 6 ++--- src/msg/usrmsg_parser.hpp | 2 +- src/usr/usr.cpp | 42 +++++++++++++++++++++++++------ src/usr/usr.hpp | 3 +++ 14 files changed, 117 insertions(+), 27 deletions(-) diff --git a/examples/js_client/text-client.js b/examples/js_client/text-client.js index 36e4e16d..3692406b 100644 --- a/examples/js_client/text-client.js +++ b/examples/js_client/text-client.js @@ -126,7 +126,10 @@ async function main() { else if (inp.startsWith("hpsh ")) { hpc.submitHpshRequest(inp.substr(5)).then(id => { hpc.on(id, (reply) => { - console.log(reply); + if (reply.data) + console.log(reply.data); + else + console.error(reply.error); }) }); } diff --git a/src/conf.cpp b/src/conf.cpp index 227b62d8..34baa7c4 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -528,6 +528,20 @@ namespace conf std::cerr << "Invalid format for hpsh run as config (\"uid>0:gid>0\" expected).\n"; return -1; } + + jpath = "hpsh.users"; + cfg.hpsh.users.clear(); + for (auto &userpk : hpsh["users"].array_range()) + { + // Convert the public key hex of each node to binary and store it. + const std::string bin_pubkey = util::to_bin(userpk.as()); + if (bin_pubkey.empty()) + { + std::cerr << "Error decoding user pubkey list.\n"; + return -1; + } + cfg.hpsh.users.emplace(bin_pubkey); + } } catch (const std::exception &e) { @@ -653,6 +667,12 @@ namespace conf jsoncons::ojson hpsh_config; hpsh_config.insert_or_assign("enabled", cfg.hpsh.enabled); hpsh_config.insert_or_assign("run_as", cfg.hpsh.run_as.to_string()); + jsoncons::ojson users(jsoncons::json_array_arg); + for (const auto &userpk : cfg.hpsh.users) + { + users.push_back(util::to_hex(userpk)); + } + hpsh_config.insert_or_assign("users", users); d.insert_or_assign("hpsh", hpsh_config); } diff --git a/src/conf.hpp b/src/conf.hpp index b91764f4..31a5357d 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -210,8 +210,9 @@ namespace conf struct hpsh_config { - bool enabled = false; // Whether or not to enable hpsh. - ugid run_as; // The user/groups id to execute the hpsh as. + bool enabled = false; // Whether or not to enable hpsh. + ugid run_as; // The user/groups id to execute the hpsh as. + std::set users; // List of users who are allowed to perform hpsh (list of binary public keys). }; struct user_config @@ -327,11 +328,11 @@ namespace conf }; // Global contract context struct exposed to the application. - // Other modeuls will access context values via this. + // Other modules will access context values via this. extern contract_ctx ctx; // Global configuration struct exposed to the application. - // Other modeuls will access config values via this. + // Other modules will access config values via this. extern hp_config cfg; int init(); diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index 6d5d7d94..d3a9ea96 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -174,6 +174,12 @@ namespace hpsh if (ctx.is_shutting_down) return -1; + if (conf::cfg.hpsh.users.find(std::string(user_pubkey)) == conf::cfg.hpsh.users.end()) + { + LOG_ERROR << "This user is not allowed to perform hpsh operations."; + return -2; + } + // Send the hpsh request header. if (write(ctx.control_fds[1], HPSH_CTR_SH, 3) < 0) { @@ -248,6 +254,7 @@ namespace hpsh while (!ctx.is_shutting_down) { + // Iterate through received commands and check for outputs. if (ctx.commands.size() > 0) { std::scoped_lock lock(ctx.command_mutex); @@ -290,9 +297,7 @@ namespace hpsh { const usr::connected_user &user = user_itr->second; msg::usrmsg::usrmsg_parser parser(user.protocol); - std::vector msg; - parser.create_hpsh_response_container(msg, itr->id, response); - user.session.send(msg); + usr::send_hpsh_response(std::move(parser), user.session, itr->id, msg::usrmsg::STATUS_ACCEPTED, response); response.clear(); } } diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index c368e991..6c859897 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -4,6 +4,7 @@ #include "../pchheader.hpp" #include "../conf.hpp" #include "../usr/usr.hpp" +#include "../msg/usrmsg_common.hpp" namespace hpsh { diff --git a/src/msg/bson/usrmsg_bson.cpp b/src/msg/bson/usrmsg_bson.cpp index 2505e734..ac415cf6 100644 --- a/src/msg/bson/usrmsg_bson.cpp +++ b/src/msg/bson/usrmsg_bson.cpp @@ -168,11 +168,13 @@ namespace msg::usrmsg::bson * { * "type": "hpsh_response", * "reply_for": "", - * "content": + * "status": "", + * "content": "" + * "reason": "", * } * @param content The contract binary output content to be put in the message. */ - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) { jsoncons::bson::bson_bytes_encoder encoder(msg); encoder.begin_object(); @@ -180,8 +182,18 @@ namespace msg::usrmsg::bson encoder.string_value(msg::usrmsg::MSGTYPE_HPSH_RESPONSE); encoder.key(msg::usrmsg::FLD_REPLY_FOR); encoder.string_value(reply_for); + encoder.key(msg::usrmsg::FLD_STATUS); + encoder.string_value(status); encoder.key(msg::usrmsg::FLD_CONTENT); encoder.byte_string_value(content); + + // Reject reason is only included for rejected inputs. + if (!reason.empty()) + { + encoder.key(msg::usrmsg::FLD_REASON); + encoder.string_value(reason); + } + encoder.end_object(); encoder.flush(); } diff --git a/src/msg/bson/usrmsg_bson.hpp b/src/msg/bson/usrmsg_bson.hpp index cc06be4f..e485195b 100644 --- a/src/msg/bson/usrmsg_bson.hpp +++ b/src/msg/bson/usrmsg_bson.hpp @@ -17,7 +17,7 @@ namespace msg::usrmsg::bson void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); diff --git a/src/msg/json/usrmsg_json.cpp b/src/msg/json/usrmsg_json.cpp index 58d271cb..04c919ce 100644 --- a/src/msg/json/usrmsg_json.cpp +++ b/src/msg/json/usrmsg_json.cpp @@ -272,7 +272,7 @@ namespace msg::usrmsg::json * { * "type": "contract_input_status", * "status": "", - * "reason": "", + * "reason": "", * "input_hash": "", * "ledger_seq_no": , * "ledger_hash": "" @@ -332,11 +332,13 @@ namespace msg::usrmsg::json * { * "type": "hpsh_response", * "reply_for": "", - * "content": "" + * "status": "", + * "content": "" + * "reason": "", * } * @param content The contract binary output content to be put in the message. */ - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) { msg.reserve(content.size() + 256); msg += "{\""; @@ -348,6 +350,10 @@ namespace msg::usrmsg::json msg += SEP_COLON; msg += reply_for; msg += SEP_COMMA; + msg += msg::usrmsg::FLD_STATUS; + msg += SEP_COLON; + msg += status; + msg += SEP_COMMA; msg += msg::usrmsg::FLD_CONTENT; msg += SEP_COLON_NOQUOTE; @@ -368,6 +374,16 @@ namespace msg::usrmsg::json msg += content; } + // Reject reason is only included for rejected inputs. + if (!reason.empty()) + { + msg += SEP_COMMA_NOQUOTE; + msg += msg::usrmsg::FLD_REASON; + msg += SEP_COLON; + msg += reason; + msg += DOUBLE_QUOTE; + } + msg += "}"; } diff --git a/src/msg/json/usrmsg_json.hpp b/src/msg/json/usrmsg_json.hpp index ff5c827d..0f4b2149 100644 --- a/src/msg/json/usrmsg_json.hpp +++ b/src/msg/json/usrmsg_json.hpp @@ -21,7 +21,7 @@ namespace msg::usrmsg::json void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); diff --git a/src/msg/usrmsg_common.hpp b/src/msg/usrmsg_common.hpp index 6844e578..0e291495 100644 --- a/src/msg/usrmsg_common.hpp +++ b/src/msg/usrmsg_common.hpp @@ -108,6 +108,9 @@ namespace msg::usrmsg constexpr const char *REASON_NONCE_EXPIRED = "nonce_expired"; constexpr const char *REASON_ALREADY_SUBMITTED = "already_submitted"; constexpr const char *REASON_ROUND_INPUTS_OVERFLOW = "round_inputs_overflow"; + constexpr const char *REASON_USER_NOT_ALLOWED = "user_not_allowed"; + constexpr const char *REASON_NOT_INITIALIZED = "not_initialized"; + constexpr const char *REASON_INTERNAL_ERROR = "internal_error"; constexpr const char *QUERY_FILTER_BY_SEQ_NO = "seq_no"; constexpr const char *STR_TRUE = "true"; constexpr const char *STR_FALSE = "false"; diff --git a/src/msg/usrmsg_parser.cpp b/src/msg/usrmsg_parser.cpp index 69a3e4bd..52bb2952 100644 --- a/src/msg/usrmsg_parser.cpp +++ b/src/msg/usrmsg_parser.cpp @@ -38,12 +38,12 @@ namespace msg::usrmsg busrmsg::create_contract_input_status(msg, status, reason, input_hash, ledger_seq_no, ledger_hash); } - void usrmsg_parser::create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const + void usrmsg_parser::create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const { if (protocol == util::PROTOCOL::JSON) - jusrmsg::create_hpsh_response_container(msg, reply_for, content); + jusrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason); else - busrmsg::create_hpsh_response_container(msg, reply_for, content); + busrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason); } void usrmsg_parser::create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const diff --git a/src/msg/usrmsg_parser.hpp b/src/msg/usrmsg_parser.hpp index 8ca9ce2d..ad06eec7 100644 --- a/src/msg/usrmsg_parser.hpp +++ b/src/msg/usrmsg_parser.hpp @@ -26,7 +26,7 @@ namespace msg::usrmsg void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash) const; - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const; + void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const; void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const; diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index bb0839be..48393c38 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -276,18 +276,33 @@ namespace usr else if (msg_type == msg::usrmsg::MSGTYPE_HPSH_REQUEST) { std::string id, content; - if (hpsh::ctx.is_initialized && parser.extract_hpsh_request(id, content) != -1) - { - if (hpsh::execute(id, user.pubkey, content) == -1) - return -1; - - return 0; - } - else + if (parser.extract_hpsh_request(id, content) == -1) { send_input_status(parser, user.session, msg::usrmsg::STATUS_REJECTED, msg::usrmsg::REASON_BAD_MSG_FORMAT, ""); return -1; } + + // If hpsh is initialized, send status reject. + if (!hpsh::ctx.is_initialized) + { + send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_NOT_INITIALIZED); + return -1; + } + + const int res = hpsh::execute(id, user.pubkey, content); + // Send user npt allowed status if not allowed. + if (res == -1) + { + send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_INTERNAL_ERROR); + return -1; + } + else if (res == -2) + { + send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_USER_NOT_ALLOWED); + return -1; + } + + return 0; } else { @@ -350,6 +365,17 @@ namespace usr } } + /** + * Send the specified hpsh request status result via the provided session. + */ + void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, + std::string_view status, std::string_view content, std::string_view reason) + { + std::vector msg; + parser.create_hpsh_response_container(msg, reply_for, status, content, reason); + session.send(msg); + } + /** * Send the specified contract input status result via the provided session. */ diff --git a/src/usr/usr.hpp b/src/usr/usr.hpp index 6e9ceef3..fa9753df 100644 --- a/src/usr/usr.hpp +++ b/src/usr/usr.hpp @@ -95,6 +95,9 @@ namespace usr void send_input_status_responses(const std::unordered_map> &responses, const uint64_t ledger_seq_no = 0, const util::h32 &ledger_hash = util::h32_empty); + void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, + std::string_view status, std::string_view content, std::string_view reason = ""); + void send_input_status(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no = 0, const util::h32 &ledger_hash = util::h32_empty); From 30bff884bf0fd0bca97ad5126cfd4a48508ddc5b Mon Sep 17 00:00:00 2001 From: chalith Date: Thu, 2 Nov 2023 13:29:53 +0530 Subject: [PATCH 17/23] Disconnect handler --- src/hpsh/hpsh.cpp | 111 ++++++++++++++++++++++------------------------ src/hpsh/hpsh.hpp | 2 +- test/bin/hpsh | Bin 18792 -> 28240 bytes 3 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/hpsh/hpsh.cpp b/src/hpsh/hpsh.cpp index d3a9ea96..bad45c07 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/hpsh/hpsh.cpp @@ -2,8 +2,8 @@ namespace hpsh { - constexpr const char *HPSH_CTR_SH = "sh"; - constexpr const char *HPSH_CTR_TERMINATE = "terminate"; + constexpr uint8_t HPSH_CTRL_TERMINATE = 0; + constexpr uint8_t HPSH_CTRL_SH = 1; constexpr uint32_t POLL_TIMEOUT = 1000; constexpr uint32_t READ_BUFFER_SIZE = 128 * 1024; @@ -94,8 +94,7 @@ namespace hpsh close(ctx.control_fds[0]); for (const auto &command : ctx.commands) { - close(command.child_fds[0]); - close(command.child_fds[1]); + close(command.out_fd); } if (ctx.hpsh_pid > 0) @@ -146,7 +145,7 @@ namespace hpsh int send_terminate_message() { - return (write(ctx.control_fds[1], HPSH_CTR_TERMINATE, 10) < 0) ? -1 : 0; + return (write(ctx.control_fds[1], &HPSH_CTRL_TERMINATE, 1) < 0) ? -1 : 0; } void remove_user_commands(std::string_view user_pubkey) @@ -159,7 +158,7 @@ namespace hpsh if (itr->user_pubkey == user_pubkey) { // Close the file descriptor and remove the command from context. - close(itr->child_fds[1]); + close(itr->out_fd); itr = ctx.commands.erase(itr); } else @@ -180,69 +179,49 @@ namespace hpsh return -2; } + std::string buffer; + buffer.resize(message.size() + 1); + buffer[0] = HPSH_CTRL_SH; + memcpy(buffer.data() + 1, message.data(), message.size()); + // Send the hpsh request header. - if (write(ctx.control_fds[1], HPSH_CTR_SH, 3) < 0) + if (write(ctx.control_fds[1], buffer.data(), message.size() + 1) < 0) { LOG_ERROR << errno << ": Error writing header message to control fd."; return -1; } - // Create a socket pair to communicate for the hpsh request. - int child_fds[2]; - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, child_fds) == -1) + // Read the control message which will contain the socket file descriptor. + struct msghdr child_msg = {0}; + memset(&child_msg, 0, sizeof(child_msg)); + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + child_msg.msg_control = cmsgbuf; + child_msg.msg_controllen = sizeof(cmsgbuf); + + recvmsg(ctx.control_fds[1], &child_msg, 0); + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&child_msg); + + // Skip if the message does not has file descriptor scm rights. + if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS) { - LOG_ERROR << errno << ": Error initializing socket pair."; + LOG_ERROR << "Message sent on control line from hpsh has non-scm_rights."; return -1; } - // Prepare and send the child socket file descriptor with scm rights. - struct msghdr msg = {0}; - struct cmsghdr *cmsg; - char iobuf[1]; - struct iovec io = { - .iov_base = iobuf, - .iov_len = sizeof(iobuf)}; - union - { /* Ancillary data buffer, wrapped in a union - in order to ensure it is suitably aligned */ - char buf[CMSG_SPACE(sizeof(int))]; - struct cmsghdr align; - } u; + int out_fd = -1; + memcpy(&out_fd, CMSG_DATA(cmsg), sizeof(out_fd)); - msg.msg_iov = &io; - msg.msg_iovlen = 1; - msg.msg_control = u.buf; - msg.msg_controllen = sizeof(u.buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), child_fds, sizeof(int)); - - if (sendmsg(ctx.control_fds[1], &msg, 0) < 0) + if (out_fd <= 0) { - LOG_ERROR << errno << ": Error writing to control fd."; - close(child_fds[0]); - close(child_fds[1]); + LOG_ERROR << "Invalid file descriptor receives on control line from hpsh"; return -1; } - // Write the request message to the child socket. - if (write(child_fds[1], message.data(), message.size()) < 0) - { - LOG_ERROR << errno << ": Error writing to child fd."; - close(child_fds[0]); - close(child_fds[1]); - return -1; - } - - // Close the child end of the socket. - close(child_fds[0]); - // Add the command to the context. { std::scoped_lock lock(ctx.command_mutex); - ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), {child_fds[0], child_fds[1]}}); + ctx.commands.push_back(command_context{std::string(id), std::string(user_pubkey), out_fd}); } return 0; @@ -266,16 +245,19 @@ namespace hpsh break; struct pollfd pfd; - pfd.fd = itr->child_fds[1]; + pfd.fd = itr->out_fd; pfd.events = POLLIN; + bool remove = false; + // If child fd has data to read handle them. - if (poll(&pfd, 1, POLL_TIMEOUT) == -1) + const int poll_res = poll(&pfd, 1, POLL_TIMEOUT); + if (poll_res == -1) { LOG_ERROR << errno << ": Error in poll"; - continue; + remove = true; } - else if (pfd.revents & POLLIN) + else if (poll_res > 0 && (pfd.revents & POLLIN)) { // Read the response and send to the user. std::string response; @@ -303,11 +285,26 @@ namespace hpsh } else if (res == -1) { - LOG_ERROR << errno << ": Error reading from fd"; + LOG_ERROR << errno << ": Error reading from fd."; + remove = true; + } + else + { + LOG_DEBUG << "Hpsh has closed the connection."; + remove = true; } } - itr++; + if (remove) + { + // Close the file descriptor and remove the command from context. + close(itr->out_fd); + itr = ctx.commands.erase(itr); + } + else + { + itr++; + } } } util::sleep(100); diff --git a/src/hpsh/hpsh.hpp b/src/hpsh/hpsh.hpp index 6c859897..ef9ad675 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/hpsh/hpsh.hpp @@ -12,7 +12,7 @@ namespace hpsh { std::string id; std::string user_pubkey; - int child_fds[2]; + int out_fd; }; struct hpsh_context diff --git a/test/bin/hpsh b/test/bin/hpsh index ce2524706564058544078a3d87568ee1162cd1fc..1c76d10b66d9a39e498d978bcbddd1b472ed53a6 100755 GIT binary patch literal 28240 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 literal 18792 zcmeHPeRNbsmak4HBz&cVibnk4q3sNe(j*~Z;w)n~B=E8}njt~hS@F?ycalEzN9=wL z!Q)3X!Ld(_qB}c!R%aK_=!|DaSDdr6tL%;jQQ+)ZU1ZihtoVVRQM*S+Fe)-C^!{$W zs+ZS~emgVn{I!STbZ*^W-FxfSt&dk-{fb-LgUc&iE+&(keTNaZeU^dvML}OcWI+6^ zg-yp_h0SJ@z*ln2DEAu#rA9hfQA%qB?gk~jddifc=NmASRC-91^qkU|$0(7M)fqhL zRZ&*(b~QQXAUuNiS|Fcp$DD)nXjS+rPxJd75q4%`V zlT;D$lvKu(%+RMr*tJsyWt0^DmodBETA^pBZ9-mBs)JJ3yL#m7)YmEW>gE`B?6li} znWVD5??R8_@`onb&8tLxPW`Z6v|Cc@Z%PZ|u?>rx7sMm;5Gb?>hW{chpsulM#!8&oIB zP$GTN#hj+p$IJ+4NU9kUa3W*>1b~(qes)- zE0@Jn$!K?ILp*Afl`qkv>2xxs#Z%#s9!n)zIG)Nx8JWeO@TNqjm!YPN9tmH1DOI$X zXQZbAFr)m^E0ragwDF1@K))8J-mvldHk3dLg) zEtKxfCZb8b^Qtf;uI|!XVyTR_A(V+WcO+waTVwks)Da#CX&ca%qz1>recV=a7|t3x zmy^UmV`F0z6k}m{la3{OJHlOhV`I24l-BfgD5hsR!tGrl{ApjDj%H#vM%xoqXC&T9 zRrC%FX#LT2CY6L=`W9^yf(VZr7i(Gy_M)K#e9lDEdO5T0t01}1s9Z>QbZgxWT6@=G zt@Em`g<70ji)RoWyHDkm!`)C_1l6)pS;nJ6(fVUs-m0zC!f1>hZC{m0aG#nQWS^w6 zx|ZtE(xGH;l-JDT9!*9pQEzOO((zO;LXAF1rAZj$qBo4t)39h{+Un%y7!+4UGw5C_ z3>)JmI)HJ+dQ$0)h&e`0c%v5X+o<(~VsVBr>nTp+(WK~gcsdZ%StQ%v#QIb5I7>tm z;r=ZI2#KB;_1KLV*BVtLhGHTVOR^QqmT3zy8&(86mM&Yn7WrmhtCeFw14}!!M&Cj! z>}zT?Sgpy|Y~~s#vQ554n06I-epcYwTLn4^|EfXhALVP$H~ zM(HFxZ(VE%bDo~@3O=3R*fNzQ&!Go2k_$Q;L8-hGpWLnUAU&DQMmb^ny!)`ln#AS{ z{#Q?K#8#n-wF>@*TD*r*$X8RZpbx!ixsec#}DB*oZcVt*;|^Ovf!ax@{r}e@I?*4KJ&);FS~7tj>Z{-7?i%aARZ|C5i>7I%Jw_!DU}k zS%U?~fH6~x1)pM~jQK4%2E3V63ogDY@v=?}jsa_?wHCbAL>XIe!NpfKUfO5DY5vI6 zZ^5n4{Q(PZeU1-W@H3?m&^s+S?aO7_X2EAl5cB~HezpbQZo$v7;E!4GdJDe8f{Ure zOP{vj=Ue2*EcgW$e4hos$b$c0v!8e_{6Zc2utpuJ`tJpdsawbNisF8C=!Kfy+;nl# zP9J0A#Y_GL#50?bd>@sJ7v3%wi`zI)6JxyaipkT27%%KHd7230g{MrOCct>%VUwqU zKVG=kM zZ2YS>{v{j#qK*HhjsJy>f5OH;YU6)oumgL8^6-V zx7+w7Hhz(fpKs$YvGEt!_?b3-y5!Z7O7Bn$%evcgiaPSI-a&M=+ImE<%D;o|R&#F! zb9r?r@5=V&X?*OYp{I^6Ix&sNk_%x*&Apg^k7P&Mkv~%GtV2N+FW8fRf*aWjjc#b< z{}yb%74sr6^m4JV74uphxyide*!n&yr11#@yqqs9FgzWyAN;1r=b1f>iW%eUMPNnI8_`^w zw?@r9&cT&if9n~}!<8WFzWD_C(B@S-axbVu$333!-$zak9d~)Qdax`7Jpa_rf}=Ni zl{<$GQzH;oM}ELfQT2Di{+`MTH0&Xc>VWSl#m^+Dhwv8xz!H^S`-uz3buOs)O z`t9qyif8x`4@jkVq;BYoi#)>z!BT4mpFtFgL04XF-RJrK^FZ5jA8b94t)|X9rQg0q zCWlTGJ;Sv3Q%B?8`XK(S4~|B>{o9_VwRR^p_gTsz-nr|%^*w0v`T2fm4jqT${U|!t z=DpCR?{7TtENyBLn_w>DU9awK^Y%fH?P>G&v%C*&Q%7{~`kf?{dn-R3Cbo`w?mPhz z&u}yBsNtiH2Pm`^kPRYQ>z|=uV2o@94d(WI@{@q){yl-gH(9&q*<yU{p!7SVZEzfK}%vXBR#uFHoBMtd$X$;U)0Tba?JZ;q6 z-j3X!{FAV=6AA=30}kds&p$|hib>%aUP%*XEmgM+IXpjw-A4_(C&_@YTMq*;3e)*D z7Q3(47iFIME*G%0{IG5`5f(h0$BGx1I#BVq6&67 zu~bGuZsqFJ*YbL*I*4Ej*7T^J^y{OY-NDhSgnJHtCkXJJ+9Bh*7hSW^4Qu=E*=(s?G_aB=Nb->zB&&}{84q+ zM^~!5j=NRY9`%)z`dKjWqA*ZXJZ#KAsZah5E_oNaEPLr{b!f?rkVN3#)u*AEKLL}^ z9mD*Iz{NdPzl5A?9dwyhzpxpFmUso$1V@*+F|q^KcI5smu(~7nS)eo1g%v~qk`s~I-LO+-r$7E^Cy&ou^^_Duc+oiU?k^K#Y+Oh`pOvIS{ z-wlt=eu5OoQ}Z%{|LCS@1vylXZn#@#+ufjaq)>OHSiBST@X=y%2k22y+EDEnFBXUK1X}+| zu}Fu4op}B{1iB5hALWDC3D7?MD5wZ8lV?t@8&@&cK%MKnY1K8`AVWAkgX^J-^B3$8 zs_Tf*Q=}Q6!HV_L6X&nzNq;&~Ms=@68w*u9p{|DV^4hw4DwfvP-|b#ntBh7I zt(|*URiL)vj!A*qmZ9nuwSyJz>)lgoTiR+H0=07?1KFjubxUh&0(A6(?~*)O>Uls?>NUz_TBuO`UY?#VNro9g~}N*iEUxtZ-iz>5#gbWLfW zk8fr7xnO|f56F%%YdD=b9f8vkI30o05jY)z(-AlwfzuJ72*~#oUa0UjFt@dtOS`-=>KdV(g%J4?#4Gze7Uhw1=i7 zs$=rEYDF|u;(1Y#^t(j_j=uj;lJ(;|0#8y7=e4|j5a$riRXJZT?BPU<^OZsmUqd+m z@1mjjx>Hgv#QtPNzAtSz*dRL4FKDNr>jmu>bWqT3f^HXdhoEDE?icj1phpFjFDcfE zmlhO38wB+W+9~LILHh+A6m*-Q+XdYr=$N4U1wAaNy}f@ZU*j(?i5Ir6Q0A`QkWK1Y zr4?^$HOz0!a<1`~rUqX_v#)8MftS~}qHfH}dO2_{1@z8VOIh5_LL$?;u^PhoN%mEu#GoNuK#Rv$S|ECp`d zs!+<}wd`n_{&h1?*_T+|Fg|8|`9;*>W;2*v-z?Q4K6qh4u_8v^&CX=<{d{Yw8>>s- z94jK_XR^5$m&4Cyavimny0I$B^|KVOXXWOvo1JT}cct=Jjr~@{$h+CZd%4z9w|T2% z0;OfIl6_p9K#UwMR~43cJ}LxgeI;Bzm-u-Eu(|lSP;XlF2|>w{iVRk&VKno zAz>ss&mbJ8O41sE%jcjhOdvz`HrVRDiQ}in`NzV}pw0f1T>jMla`OLWE`JvDmg)C$ z?R_2ctjxH23J;13cIv!1!tI|r9*%Q6XP+{DCi8%w>i_w`U1i2k6L5N6$DTTY*RfgV zd)=~pje~s50l&oo{~YU`0{ixH`!eKbSmvXAe!k&g=S$!hN#`u|oQm@8qHa0^E$bH> z1UloRbSdO#RLo-b=YZ3_gI>tbfqcE6s~ejDWNE)uE}lO^J!e#$y8b-jAU`JT*V*jT zeX?@)o$fn0-6Np)c+1)OlH+ye{kH{1^Vp>h^8F6@UBD@xitt~UVGlUSA9iThXOO3H z$ZU2h(eHJb?=1mo*`O5|Fy-2HwgW!b0q=6aqrj#*41gXQVR4)V_fFY~Bohk+|X*Gi5! z;FIwMq1?R^1$a6C7dqgKUc2{&`};*E6^}4&Mev%Xfgs-Y&u-8t&=w81OwwCePdb!{YLRRru>~p?4%a(kdWoo}EngK_*{-!; z-9}eiG~Alg+EoFnZL65p_7_(NR(32yS&1?lZ3Xz{7&8vnEMMN$j>{o|rNMTxiW?M` zD>r^WzpQ|Z2Xx0ki$+3vh+mf|EfBYHN~N!_6hn7qQd%E=9-}Kszwd5PiEpfJjV~ST@i|}G zak!*XYQ?xoGT{~OcSysh++yNQH}0ZLC{Pda`z)mp-Bl??j7vrWGvfPouLIeP*sjn_ zRNIX1!mTekcK?(&nMz#1eH!#62B~rHM%>|<@PlGRznhjKyuY399hKPUmws%@+J;O< zREJpG3QxU5Mz^I(ZHk*h;Y^lKQ!%p5i%zz2ed^7yQUQ6x%~r?%b_1{Eb`^e>pZSpW^`=B7 z6Ad#TuCIaRk@uxjd^Pt)`^0mnF9K_lLp8WRXWX3B&_*na+^X?NGHl2^Di0-MFmD*d zd|*C24(TGL^>P2T^R!LEmXBeZ$df!rkyM^PiefG+^F%MkhtB+@ehc=Mlq6L+H}OZF z^GReeGFJVyLSIs^6ciNOvXayR&Z;lZZzNSpr0KhIX`=7Fc#ke6{g>xFlG68XO7dLQ z?tchnbTldT<#~{#+eCZFM~bu5m*<}`U?d{-<++ih^4u08Jdq7+x&aKGiAsHWz9cE$ z9pFj&FXbe?1*LSxDtUPhCFy>lPySQvr2hhDqXL)u^1Mn?dG0Igm-@2(_Y3`{!k|3Y zl61Q;O!{APg4Glj4(;WW}f}jrZ3OaB$e{g zgybdNVbeD^;bJpBX6taNC+RabeR)17X}b)Va6sxwf9Mq$Yy9Lno}}{k3n_1(KQ9V> z+5b!tl7ddR`EPTFy=2pu=Yo=U3v-g#>px`Em*~fCNjvo@x9T%Lj8SSZh++`)uhf&kg-|9;*01=D5=H2f zeQQ#z4DuI?`h~bzD)lcl5hEkbS*ba8EwY`$;5PAt75z@tgpc%Ju3uCveYdEy!>tCl b)?AnjUe+sR={tQn{T9C=ahXlQ# Date: Thu, 2 Nov 2023 15:54:28 +0530 Subject: [PATCH 18/23] Updated hpsh binary --- test/bin/hpsh | Bin 28240 -> 28240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/bin/hpsh b/test/bin/hpsh index 1c76d10b66d9a39e498d978bcbddd1b472ed53a6..8caebf0b7db7b401e83cf26c50e69b84907d98a5 100755 GIT binary patch delta 1722 zcmYjS3v5$W7`~@nx0Q_E+db0Gl`)_jdr7;EA+u}P-HN?UCTwhD2!kz(JjF0mf+%L4 z+jLE-4v!>+hw==NOo25fiaZ5*Bum5uA>la`!mUmQA`WEc_?@<(f71K^-}gVyIrpBP zze>(uB|T>1Tc19p-(VCXvVj_jO}{NJinfJ3#72x>ISQX?>et*zjlU4@o^WKh!`74M`G7kwpr9@$O5 z%5F-|C4#U}3B+aRB1Z9dTFrDqP6-)B8*_Rmu8#*7sJ2Q0eaGYRVrLNe5aN7C8AKu9 zDP@0%AFihP6N^brX#T`qWbEch3d%(4mPG4{U0-5#O8co?nw2+2zlwukr`1H8^RAG- zkR#ti$R*lUP)vTJUl&|$+nLG(bf0n+@LJ7_6!Fay{Bc$ZI@>vWrqh~;4qO(AZ=6v4 zy;cEO%C?lb5z4UBY$x)q)vVmA=N_Yz+vlN?#qhWZM__% z0w@8ORYK3HlLaAQSARsILl!udV5yFe;XkAJzgI_r2D3ATGehdP=x~hpR*i6|7M?UN znzS*Q=Q_hBa9%(dvR3e{pz|W9+Cj-3{cS9~;0bp+>)=#-A4Y69w*_8oOthFInz@x{ zb|dq*KDCwCjLqBy9y4eDul*+8K00$FkHoMx6c5kDX+97$|Hfj%j$yXo8F&fFQ3n=! zKHT~Yp7i)Hgq?um*a{&M(J`2afyZN`)OC?5oLh^~t>YBvv>n_Gmd3#wUO?L>mAdC3 zm!%bh|FZ{qOCtfgSGg*C=6j(hcNKpgACl7*8ojrg)id}%R#GRZ=2Q?o5I zZ#vd1tSV?wI-HyAFctr8Z;}#lo(52tKEO#VM9b5}Kjnr2$h0qGQyiE{DhSsqXV~xhI_c~*{pv!ME)(>3` zeG9t(7sf1jOV{0E>@41({z1$Dob)?m>);=OmcU!?GByHS2we!g7J3f!mLbNPc>F!o zhsG-!5keo!Ch|5lR+==zb(&w9Lzd9mN>h5v0AoG`J{1WDZ)B$Jl_{CG(B8~l(+yIG zW`==ZBm9~;jNhX{+EmhCNeUT5)ykbL=C)F9`!S0<+QdcmkiK%s&b^g zSmY7#ad+^L4FmK*l{ww_D`UmLf?|*w(ZB_B5Jjfan^o@DTd-ao_r`>6ZXlj5THObd z5Z1oQn+E%CLJjQeiFVlA^;a|i85VSsM0Gm$L%O`RJTG^ux!LS&`Trg{tUhSt>2BxEH$ z*RYtB)1uiwpbcqUO?v2>#*d4(#paP?HOsLb<5BWnj8DN{ahZ`I2+81mp|UwQ2$5*| z+&#n>Ix%;@NT$=)Wj1{`z8Egubl);Jd5hi$_urpO-trgpYOIM$mjc=OQ9$gWearV~ F{spgxPfP#+ delta 1739 zcmYjS3s6*57(Qno!Zzq#9y>sw3wQxnkX=+1vQ;kZ40lIHkcUsqa*TYII$P;Pfw55A zx{4i}m>x4Q1EUs3xz!Y-<^$6jXL1^CrZkn*ygQ;mYLZ&F@7!IjGjs3%f8Y7P|NqZ9 z_i_3>J$;_GCDFE>$wQ{@SfY(?7EA4>J%%va6LeEMjct&^@R4Oc-Nl5sfy?nPbkDAR zx6fa^d9=I1Yt^p}Hs}+Kv?I7Px_1oSz$76txiT*-uB;2&=&&J<;6~w^h1RgenM-Le z`y#V0u8j@LwKW=P0pT5mj{<+cTwxdngnUIywk#Yg_eU@oxHWbkfqsXn7kYWyka(6ZaYVh z24_unQ~En=$(c&8vafQ^H||T|0mfb2_&s7$y(~O`lHZPi-OAY$UeSySeAEl;Ks!C0 zM*q>E1)EnK#+2;q5ecwz_fJ(l#N%DQA>|%`%XjUN4p_ONfgvSxR3nw~u#Nr$;vPO3 z3jn`|`$qV(-zAz+%Ql@5ze72CS5^B`F)0TMh*tiD>^rX9M@lfe;&}r@N)O;Sytbl4 zyfT)H(!(NO9M?L3nTE;ZVbxPmHG(_AxlQ1t=2L2@;yzF5bYW8Y@Q&sea(@H?edEK) zazP+wI~Q&Ne|^8Qg6E9%{1SNdEc~y$pO^P(JsBpQ!6(+-+~lNzv_vR{mw4|l*PAjHY-u`TjN+(Vb6W6 z6K(llF)R(WvlhFHPGsNPB}!S0VAXE(3*q~)^$$+@1U z=x1#}Yh!VBT~O67*y#hRdJ5JBdj+=tvZ|)y+4Wvg)suLx&J3at;Dj5hx()M&o2ts+ z4H5PM*Td!ldtn#Bb`7a&9gk-NQugCbP}>njTv29jL|iyCGWsjaD9K8G`Vx|HJ~Hr> z6A!LM?3t28OBzZ>MP`yFh^;E@$=tQbuM$4PNKtX zQ)!m11M4{mf#Di%(zsz=b5!e?ZN`9MyM70MHF>Es==V)_q%@Hhv!6@L=qi@(O00j! zOhWo6I?ZInFbDq4s7m-3q8;!%P3Lp~?J-6B%=*@G>*2QwNtpOVh&^D||0o#Y4+ zcG|$ws}ixO^eT(qLJHaZsv%m*r0TNd!;$YWa%!U*cO5a4Vb)olNFD6!>N0$>X-yfO z4pls>t4XB|!7Vivls2*NYM-NXS^k0_P=+pinRc)(3wPvy8tF%hqXCNhUgo${* z0E~G!mpJfk!J Date: Thu, 2 Nov 2023 21:54:58 +0530 Subject: [PATCH 19/23] Updated hpsh binary --- test/bin/hpsh | Bin 28240 -> 28456 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/bin/hpsh b/test/bin/hpsh index 8caebf0b7db7b401e83cf26c50e69b84907d98a5..f1324999665c4e6d5e69380b678982b6aa93c08d 100755 GIT binary patch delta 6837 zcmZ`-4RlmRmVU20ogYa0CqHzDAJbtP2q5WhArQnk>5#ySG??(?AOwx`A`mhP=!kE>TkpNt zGP`w7*RA{ATeoiAx>c{bhCdKr_)u(jB#*iUUh-8UWIfO^@A-uDsVaNEzsX9erc?uZaBc2j9D{ogE8G%LFf@O zg;aqsDvQ{V@nP{1wm-(sN@6_X^JuxnpRt~pa?wqw_%4^_n;hav&L86Si@e^;>wc=) zut^dX^s|ePGjHrl)*a&zU*?kbSciC+YyN`sgW%ueny+*8ZH_wQ9O7j{SxKBEZsJ%s zu+MmFG;UwaAFvQ?s5FJ`iqEv=d({cVsYE!_dnCTW$WqGF#8vEY;du?4E zb0&QkXAoip{8*-W!6p&W@WU3ZqZ7Z9*^f*Xgvr8nZJ|ZMDAa25e8^L4Ym)>aUJy)b zpQk(i3F{swOw#zqskI3L?5CO7G4m}3khjdY1Tr;gFfi932nm8mQPRGO=3h+9=LS<+QIc$s7 zp0rQ}c-_qQL;t{56`}=1047R1>#^Edr!_H2TMjPiVjls06DWDBmu_aW+1YiV`eaEm z$b3MvY>7#ebVbl%wj1b1povlFC_4i5fGsiI9EFZW`DS4++U!Z%o>z64m~3YsS77R<(wIR*PVheuFP81JJ0zu!>pPtbQ_OU-cXeGzglkj zriRjSJW{Ij(ERF--t-^MF$72qw(WL7uw)bpg2q2~6W@3fzvCu;+fDqIoA?bk@vAjH zAaDnz;32m*t}zEOa?qa)m}?VK7$;z3QT)R$6+w z!6a|`4t;`u@drnx7Fm>nH@K`bK0j7$=kV%OrDY-qCTM_AprYIi4~F! zTyk2T!L6NTKEv=mBMANje#?Tu8n{N35^Qg2$s2OBvkbT?IWl~ z5iL)y!`AbM9*UR3t?Jyv$6Z#6L9o!3B?XUjaCO^NOKTyvu0ME9uKJeZ(&}o4iQ?c% zspY!G^29<2(GnZee3n;Y{VQRG0u?sf821sp#mbT+aPbs8YkU~$ZQq8aE~|HBfDY!$wo~li*pB)3K(z@=*^Jc? z8m9Ry0}Za_6quD?Q-IFMe*ujIV3hXu2u3Il#kiz!(i2$A0s4eUp?r_D^v#C1pr8y} z2F5N7wjv8@kM++`$6SLk)ewdA?p}+EgMxMi`Mfh_~=MdSN*Zy7~fW$R9wBXZaT3v>)bxdPk7Q$QRld`BE5F zwdL}l=4Y#`om*&i4H8A}brJ0&yYwUEO;CiWk60vSHz*YeN0h{M0Cv*&I`abB4z8h^ zrDGU&hCwWI)omsx(~Kx_X(^W!Dr1elMb64ZyzTKmfJseE4bC zt29cu!L`UAz=9t}NFwJE9b}vuw;eogg)S#jjV_B?s_EHgX>BKM>=q~2=ZP0-0@k0& zE$1Y{cWt!1QCzU($*>qXNZVf99RIV3YXo>I3_z-O{Xr&N#=jkT1XGz<-G99bGueD_ zb&ox#n&DRVkrldg=<}dMC!F&hSveSOr5skY*ag%H??hK16c-iPLjIm6f5Uk;GSGxR z69+wJp2hP+o&`NxZ2oD*#@0`MK=h^Y2S4@)ugbf~?ceg0R^7gYnDBuD*a&aHxBiU3 z^LrT$dyaY*VK=KO+j2@&{o9H@uhZQWp8>fPjOINpHn3B2o;pXG(E#bmw*tU&?u1n- zY$_*$OG6;5TC(gMqUudd)lV?;(m`fWsx5Ux^r57=P!7^G<==g!D10334*49I!r*0f zjI*4%CTGGSfU2vhs&|yBDq#HHUG4lCC*QQhIEVj#Tn~{s2E3o{mOot49$aqa0gN?~ z7ad<}5t9F)!jU#gl5pNsQe}{$ZKie{Ov-OSN#21<8^0G#J#`f;1t_lsZpfR-SUBhR zHV)+x6c6b8>&;hmhH2;Q%c_>0v}W>-d6TJq^{4<$2&=%Spg#1=I}ZJO^py zmM>X-_UwBW)0ZurMA?FV66`5yBlt)5Wjojeu5U6BS$e%8O$wR*4Kf@t4GGGq_T@dH ze}Th!e=5`8>E)J+abqlecF%+zpBB=bH@?uDhzts z^qQBIxaU{VVuc=!*&I25M)cHh^$VBdwt@+Ub~)&Jkv%bWTrLLiS5}aF5l*^8tfEE5 zr}BRA{C07o@qG%y<}GkHpB-}FZupmR_O?6Uuz#E-dFl=Cjj2haI76bHZZt@j1L-5`Y*lmTAnpL>J6k}Vf|f9$m-{U(2* zIK8BD&$gWn&b?GMY}>P=c4uY7Hs{{j2X>DBYm>A1TUt z&=Sxw(6RqkloBk=;3tamE%ui6lA`PbUjo`m`j-`DI`9fm`l@z=(oJ#@w1V`<6y+eO z2a{??zb?@8peXEfU*?SNi;6-kA{541iMa5?i7A}_GyGw*3Vsx*7*#0aCkhU3p#i^* zz`ImSTt+$v@#}(T`1teUARfQzz^E-0nXN5`HD+A9`ABs5I3eTjOOXB4;4?c~jFQ>; zsM+B&TYcvE$wC&CKEZF}C3dV}b}XGVO_$iYf_uehm}j}eurh(&wR}!s%wW7?oMg@| zG<$sJtOB#M!0ae6TMNwbKK$k3!|em@L}1?rjd>rH&pc*miTi2nK~p&9N#h}!4NZ>% z-F`t)ut$)qX6sMja3RT{&2b7=#Qi!J%)3d``;v`E&8H1u4%lqJN;W=YGeQ1>%>-o7 zb{E>X0X!y1(*!|zHcgD53G0n?-6j+(3tTI`ccm7^rR$F@`lCv-M-_`5M^adwKh;L> zM^wlJm0H%}&#>h#RJnAO2p%@%&k*z3M}D^`Gu!G6v5I+DyKOaFRRw+N$Jp-G88%r< z5q;%5*^$+Ei+$|M>Wn16_B?^l+b*G_Cxexw-XY>;acv44G{p3_ugMqVx@U5$?Df(# zh;L=_CD$>kSZWvj%v+jfOc44&?dhEs&AljM#QT@bDoa<2!+2s#Gg^dEQ2W&8Sy4(_ z(rZsLWInP&6ljiD)*lv6 zu#OE&48tDw)`qRNlG&=#N;+myo?=&wc=5a^Wx}T)LT{+)k7CSZ1FfB^q1Q`EDz4%6{ZxA&LUxl) zYlW(#+k6uEO!#^8T^ZF9iCOm5j$*jkavN{zl>RF;aBKow!AJ*_L4NuWF z)ER67iirMP&(Bx%`Bt|m`dH;gySSd$9aN{ki2qa+EvM$SHiYmWTxSZ~f3IC!$?LP+ z$2Q(R#xj8qv8DIA#sA{S$GrZM*RjmE$u4@SPG62NScPeSXa8=lQ^9rGphJES@^eoR zwrNiMBiHHS^$4#cY&R^MSmkEBID_i+-LyXF>(SN+Q{`npNljgl+9;Od029&Y9bSLV zyl8*NHEj5=O3_a3ePr{W3`;k87gufD+puTXBjtOx?QTSK@7h)C8W!%TtS_#uUDvRv zZrk3y#kEE2DvQC?SJv(+UR7ILR8-Vkx-~b3rIx4SCEYz~3LC7nFl%`XJ3T3xJ$v5@ zBOcXzNA4Ri;^Z;)wpUk(2CIpUKag#cwLH-&4!at+O+UJHTE}+RxD)!c1Fer8tyz+w zA4#1oQnO^@Ak+`UG3Koeh~2EG)}1h{9&&ijjnpo&jcS}uyO{Sucd~wH>Gb6!w&%g@ zNqXMn>^k<~3Y=Y69&}Iab$!n_G4FP_O+V3eTF-U^ZKe+xicYIo&vti$zWY5avVBQ{ ze)iTdatY^oPNrRhJZ1E&EzGJa?mCfBb=YIiM CY1jJz delta 6174 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 From 09a488e14abb6a471d797c24501d327cf89c786d Mon Sep 17 00:00:00 2001 From: supunvindula Date: Thu, 2 Nov 2023 22:08:38 +0530 Subject: [PATCH 20/23] added hpsh to Dockerfile bin --- test/local-cluster/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/local-cluster/Dockerfile b/test/local-cluster/Dockerfile index 0d36bdb7..00c7199e 100644 --- a/test/local-cluster/Dockerfile +++ b/test/local-cluster/Dockerfile @@ -2,7 +2,7 @@ FROM evernodedev/hotpocket:latest-ubt.20.04-njs.20 # Copy (overwrite) the local build outputs into the docker image. -COPY hpcore hpfs hpws /usr/local/bin/hotpocket/ +COPY hpcore hpfs hpws hpsh /usr/local/bin/hotpocket/ ENTRYPOINT ["/usr/local/bin/hotpocket/hpcore"] From c3bacabff64da9480b5055dab010aed7a73907cb Mon Sep 17 00:00:00 2001 From: Chalith Desaman Date: Wed, 8 Nov 2023 10:24:15 +0530 Subject: [PATCH 21/23] Introduced fallback contract execution (#388) --- CMakeLists.txt | 2 +- examples/js_client/file-client.js | 26 +-- .../nodejs_contract/diagnostic_contract.js | 15 +- examples/nodejs_contract/echo_contract.js | 36 +++- examples/nodejs_contract/file_contract.js | 15 +- examples/nodejs_contract/package-lock.json | 14 +- examples/nodejs_contract/package.json | 2 +- src/conf.cpp | 7 + src/conf.hpp | 8 +- src/consensus.cpp | 166 ++++++++++++++---- src/consensus.hpp | 13 +- src/msg/fbuf/p2pmsg.fbs | 1 + src/msg/fbuf/p2pmsg_conversion.cpp | 2 + src/msg/fbuf/p2pmsg_generated.h | 20 ++- src/p2p/p2p.hpp | 1 + src/sc/sc.cpp | 100 +++++++---- src/sc/sc.hpp | 36 +++- src/unl.cpp | 14 +- src/usr/read_req.cpp | 2 +- src/util/version.hpp | 4 +- test/local-cluster/cluster-create.sh | 11 +- test/local-cluster/cluster-start.sh | 2 +- .../consensus-test-continuous.sh | 2 +- test/local-cluster/consensus-test-loop.sh | 2 +- test/local-cluster/rundir.sh | 2 +- 25 files changed, 377 insertions(+), 126 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91e2711a..e4a7d7e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,7 @@ add_custom_target(docker COMMAND mkdir -p ./test/local-cluster/bin COMMAND cp ./build/hpcore ./test/local-cluster/bin/ COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/local-cluster/bin/ - COMMAND docker build -t hpcore:latest -t hpcore:0.6.4 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/ + COMMAND docker build -t hpcore:latest -t hpcore:0.6.5 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/ ) set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE) add_dependencies(docker hpcore) diff --git a/examples/js_client/file-client.js b/examples/js_client/file-client.js index d6a481ac..43ac05e0 100644 --- a/examples/js_client/file-client.js +++ b/examples/js_client/file-client.js @@ -67,22 +67,6 @@ async function main() { }); }) - // This will get fired when contract sends a read response. - hpc.on(HotPocket.events.contractReadResponse, (response) => { - const result = bson.deserialize(response); - if (result.type == "downloadResult") { - if (result.status == "ok") { - fs.writeFileSync(result.fileName, result.content.buffer); - console.log("File " + result.fileName + " downloaded to current directory."); - } - else { - console.log("File " + result.fileName + " download failed. reason: " + result.status); - } - } - else { - console.log("Unknown read request result."); - } - }) console.log("Ready to accept inputs."); @@ -122,10 +106,16 @@ async function main() { else if (inp.startsWith("download ")) { const fileName = inp.substr(9); - hpc.sendContractReadRequest(bson.serialize({ + hpc.submitContractReadRequest(bson.serialize({ type: "download", fileName: fileName - })); + })).then(reply => { + const res = bson.deserialize(reply); + if (res && res.type === 'downloadResult' && res.status === 'ok') + console.log(res.content); + else + console.log(res); + }); } else { console.log("Invalid command. [upload | delete | download ] expected.") diff --git a/examples/nodejs_contract/diagnostic_contract.js b/examples/nodejs_contract/diagnostic_contract.js index 48650af9..d5c14e59 100644 --- a/examples/nodejs_contract/diagnostic_contract.js +++ b/examples/nodejs_contract/diagnostic_contract.js @@ -6,7 +6,7 @@ const filename = "file.dat"; const autofilePrefix = "autofile"; const autofileSize = 1 * 1024 * 1024; -const diagnosticContract = async (ctx) => { +const diagnosticContract = async (ctx, readOnly = false) => { // Collection of per-user promises to wait for. Each promise completes when inputs for that user is processed. const userHandlers = []; @@ -134,5 +134,16 @@ const diagnosticContract = async (ctx) => { } +const fallback = async (ctx) => { + console.log(`Fallback mode: Non consensus execution count: ${ctx.nonConsensusRounds}`); +} + + const hpc = new HotPocket.Contract(); -hpc.init(diagnosticContract); \ No newline at end of file +hpc.init({ + "consensus": async (ctx) => { await diagnosticContract(ctx); }, + "consensus_fallback": async (ctx) => { await fallback(ctx); }, + "read_req": async (ctx) => { await diagnosticContract(ctx, true); } +}); + + diff --git a/examples/nodejs_contract/echo_contract.js b/examples/nodejs_contract/echo_contract.js index 7b152b55..f065c9a5 100644 --- a/examples/nodejs_contract/echo_contract.js +++ b/examples/nodejs_contract/echo_contract.js @@ -5,10 +5,10 @@ const exectsFile = "exects.txt"; // HP smart contract is defined as a function which takes HP ExecutionContext as an argument. // HP considers execution as complete, when this function completes and all the NPL message callbacks are complete. -const echoContract = async (ctx) => { +const contract = async (ctx, readonly = false) => { // We just save execution timestamp as an example state file change. - if (!ctx.readonly) { + if (!readonly) { fs.appendFileSync(exectsFile, "ts:" + ctx.timestamp + "\n"); const stats = fs.statSync(exectsFile); @@ -56,7 +56,7 @@ const echoContract = async (ctx) => { // ctx.unl.find(""); // NPL messages example. - // if (!ctx.readonly) { + // if (!readonly) { // // Start listening to incoming NPL messages before we send ours. // const promise = new Promise((resolve, reject) => { // let timeout = setTimeout(() => { @@ -84,5 +84,33 @@ const echoContract = async (ctx) => { // await ctx.updateConfig(config); } +const fallback = async (ctx) => { + console.log(`Fallback mode: Non consensus execution count: ${ctx.nonConsensusRounds}`); + // NPL messages example. + // Start listening to incoming NPL messages before we send ours. + const promise = new Promise((resolve, reject) => { + let timeout = setTimeout(() => { + reject('NPL timeout.'); + }, 2000); + + let list = []; + ctx.unl.onMessage((node, msg) => { + console.log(`${node.publicKey} said ${msg} to me.`); + list.push(msg); + if (list.length == ctx.unl.list().length) { + clearTimeout(timeout); + resolve(); + } + }); + }); + + await ctx.unl.send("Hello"); + await promise; +} + const hpc = new HotPocket.Contract(); -hpc.init(echoContract); \ No newline at end of file +hpc.init({ + "consensus": async (ctx) => { await contract(ctx, false); }, + "consensus_fallback": async (ctx) => { await fallback(ctx); }, + "read_req": async (ctx) => { await contract(ctx, true); } +}); \ No newline at end of file diff --git a/examples/nodejs_contract/file_contract.js b/examples/nodejs_contract/file_contract.js index 55c3820b..6c239ace 100644 --- a/examples/nodejs_contract/file_contract.js +++ b/examples/nodejs_contract/file_contract.js @@ -2,7 +2,7 @@ const HotPocket = require("hotpocket-nodejs-contract"); const fs = require('fs'); const bson = require('bson'); -const fileContract = async (ctx) => { +const fileContract = async (ctx, readonly = false) => { for (const user of ctx.users.list()) { @@ -54,7 +54,7 @@ const fileContract = async (ctx) => { })); } } - else if (msg.type == "download") { + else if (readonly && msg.type == "download") { if (fs.existsSync(msg.fileName)) { const fileContent = fs.readFileSync(msg.fileName); await user.send(bson.serialize({ @@ -76,5 +76,14 @@ const fileContract = async (ctx) => { } }; + +const fallback = async (ctx) => { + console.log(`Fallback mode: Non consensus execution count: ${ctx.nonConsensusRounds}`); +} + const hpc = new HotPocket.Contract(); -hpc.init(fileContract, HotPocket.clientProtocols.bson); +hpc.init({ + "consensus": async (ctx) => { await fileContract(ctx); }, + "consensus_fallback": async (ctx) => { await fallback(ctx); }, + "read_req": async (ctx) => { await fileContract(ctx, true); } +}, HotPocket.clientProtocols.bson); diff --git a/examples/nodejs_contract/package-lock.json b/examples/nodejs_contract/package-lock.json index 4ae9c899..4b24d58a 100644 --- a/examples/nodejs_contract/package-lock.json +++ b/examples/nodejs_contract/package-lock.json @@ -6,7 +6,7 @@ "": { "dependencies": { "bson": "4.0.4", - "hotpocket-nodejs-contract": "0.5.10", + "hotpocket-nodejs-contract": "0.7.0", "seedrandom": "3.0.5" } }, @@ -37,9 +37,9 @@ } }, "node_modules/hotpocket-nodejs-contract": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/hotpocket-nodejs-contract/-/hotpocket-nodejs-contract-0.5.10.tgz", - "integrity": "sha512-1Cw9WcyoQmJabGkjRbM4FZ1HMvUI3z6IVTbhi0BDiD+K1c6bHROPgNKbIHCSL15+Z5xvbHpeuOOPLGogGtdC7Q==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/hotpocket-nodejs-contract/-/hotpocket-nodejs-contract-0.7.0.tgz", + "integrity": "sha512-MHIhGGzPBsKkmXMZrr8L3ze6cSqlSKQ+V2J59/fSS7FDeo5+Z983ZOwt1aBvaLmkN22YOvtLVdBUn1EEamryOg==" }, "node_modules/ieee754": { "version": "1.1.13", @@ -82,9 +82,9 @@ } }, "hotpocket-nodejs-contract": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/hotpocket-nodejs-contract/-/hotpocket-nodejs-contract-0.5.10.tgz", - "integrity": "sha512-1Cw9WcyoQmJabGkjRbM4FZ1HMvUI3z6IVTbhi0BDiD+K1c6bHROPgNKbIHCSL15+Z5xvbHpeuOOPLGogGtdC7Q==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/hotpocket-nodejs-contract/-/hotpocket-nodejs-contract-0.7.0.tgz", + "integrity": "sha512-MHIhGGzPBsKkmXMZrr8L3ze6cSqlSKQ+V2J59/fSS7FDeo5+Z983ZOwt1aBvaLmkN22YOvtLVdBUn1EEamryOg==" }, "ieee754": { "version": "1.1.13", diff --git a/examples/nodejs_contract/package.json b/examples/nodejs_contract/package.json index 31bca1ba..afe6db89 100644 --- a/examples/nodejs_contract/package.json +++ b/examples/nodejs_contract/package.json @@ -5,7 +5,7 @@ "build-diag": "ncc build diagnostic_contract.js -o dist/diagnostic-contract" }, "dependencies": { - "hotpocket-nodejs-contract": "0.5.10", + "hotpocket-nodejs-contract": "0.7.0", "bson": "4.0.4", "seedrandom": "3.0.5" } diff --git a/src/conf.cpp b/src/conf.cpp index 47e6e696..8f6204f8 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -952,10 +952,14 @@ namespace conf jdoc.insert_or_assign("max_input_ledger_offset", contract.max_input_ledger_offset); jsoncons::ojson consensus; + jsoncons::ojson fallback; + fallback.insert_or_assign("execute", contract.consensus.fallback.execute); + consensus.insert_or_assign("mode", contract.consensus.mode == MODE::PUBLIC ? MODE_PUBLIC : MODE_PRIVATE); consensus.insert_or_assign("roundtime", contract.consensus.roundtime.load()); consensus.insert_or_assign("stage_slice", contract.consensus.stage_slice.load()); consensus.insert_or_assign("threshold", contract.consensus.threshold); + consensus.insert_or_assign("fallback", fallback); jdoc.insert_or_assign("consensus", consensus); jsoncons::ojson npl; @@ -1095,6 +1099,9 @@ namespace conf } contract.consensus.mode = jdoc["consensus"]["mode"].as() == MODE_PUBLIC ? MODE::PUBLIC : MODE::PRIVATE; + jpath = "contract.consensus.fallback"; + contract.consensus.fallback.execute = jdoc["consensus"]["fallback"]["execute"].as(); + jpath = "contract.npl"; if (jdoc["npl"]["mode"].as() != MODE_PUBLIC && jdoc["npl"]["mode"].as() != MODE_PRIVATE) { diff --git a/src/conf.hpp b/src/conf.hpp index 242d8d43..d22594bd 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -173,12 +173,18 @@ namespace conf size_t max_file_count = 0; // Max no. of log files to keep. }; + struct fallback_config + { + bool execute = false; // Whether or not to execute the contract on fallback mode. + }; + struct consensus_config { MODE mode; // If PUBLIC, consensus are broadcasted to non-unl nodes as well. std::atomic roundtime = 0; // Consensus round time in ms (max: 3,600,000). std::atomic stage_slice = 0; // Percentage slice of round time that stages 0,1,2 get (max: 33). - uint16_t threshold = 0; + uint16_t threshold = 0; // The minimum percentage of votes for accepting a stage 3 proposal to create a ledger. + fallback_config fallback; // Consensus fallback related configuration. }; struct npl_config diff --git a/src/consensus.cpp b/src/consensus.cpp index 4efb7ee2..5e899b63 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -29,6 +29,7 @@ namespace consensus // Max no. of time to get unreliable votes before we try heuristics to increase vote receiving reliability. constexpr uint16_t MAX_UNRELIABLE_VOTES_ATTEMPTS = 5; + constexpr uint16_t FALLBACK_CONTRACT_TERMINATE_MARGIN = 100; consensus_context ctx; bool init_success = false; @@ -140,6 +141,9 @@ namespace consensus broadcast_nonunl_proposal(); } + // Keep copy of current stage since we might change the stage in following conditions. + uint8_t cur_stage = ctx.stage; + if (ctx.stage == 0) { // Prepare the consensus candidate user inputs that we have accumulated so far. (We receive them periodically via NUPs) @@ -147,7 +151,7 @@ namespace consensus if (verify_and_populate_candidate_user_inputs(lcl_id.seq_no) == -1) return -1; - const p2p::proposal p = create_stage0_proposal(state_hash, patch_hash, last_primary_shard_id, last_raw_shard_id); + const p2p::proposal p = create_stage0_proposal(state_hash, patch_hash, last_primary_shard_id, last_raw_shard_id, lcl_id); broadcast_proposal(p); ctx.stage = 1; // Transition to next stage. @@ -200,6 +204,7 @@ namespace consensus { ctx.stage = 0; ctx.unreliable_votes_attempts++; + ctx.non_consensus_rounds++; // If we get too many consecutive unreliable vote rounds, then we perform time config sniffing just in case the unreliable votes // are caused because our roundtime config information is different from other nodes. @@ -208,15 +213,19 @@ namespace consensus refresh_time_config(true); ctx.unreliable_votes_attempts = 0; } + + if (execute_contract_in_fallback(cur_stage, lcl_id)) + apply_consensed_patch_file_changes(); } else { ctx.unreliable_votes_attempts = 0; + ctx.non_consensus_rounds = 0; if (new_vote_status == status::VOTE_STATUS::SYNCED) { // If we are in sync, vote and broadcast the winning votes to next stage. - const p2p::proposal p = create_stage123_proposal(votes, unl_count, state_hash, patch_hash, last_primary_shard_id, last_raw_shard_id); + const p2p::proposal p = create_stage123_proposal(votes, unl_count, state_hash, patch_hash, last_primary_shard_id, last_raw_shard_id, lcl_id); broadcast_proposal(p); // This marks the moment we finish a sync cycle. We are in stage 1 and we just detected that our votes are in sync. @@ -238,34 +247,33 @@ namespace consensus } /** - * Scan the stage 3 proposals from last round and create the ledger if all majority critertia are met. + * Evaluates stage 3 proposals and populates winning info. + * @param proposal_count Number of stage proposals. + * @param winning_votes Number of votes fo winning proposal. + * @param winning_proposal The winning proposal. + * @param stage Stage to evaluate. */ - void attempt_ledger_close() + int evaluate_proposals(uint32_t &proposal_count, uint32_t &winning_votes, p2p::proposal &winning_proposal, const uint8_t stage) { std::map> proposal_groups; // Stores sets of proposals against grouped by their root hashes. - uint32_t stage3_prop_count = 0; // Keep track of the number of stage 3 proposals received. + proposal_count = 0; // Keep track of the number of stage 3 proposals received. // Count votes of all stage 3 proposal hashes. for (const auto &[pubkey, cp] : ctx.candidate_proposals) { - if (cp.stage == 3) + if (cp.stage == stage) { - stage3_prop_count++; + proposal_count++; proposal_groups[cp.root_hash].push_back(cp); } } - // Threshold is devided by 100 to convert average to decimal. - const uint32_t min_votes_required = ceil((conf::cfg.contract.consensus.threshold * unl::count()) / 100.0); - if (stage3_prop_count < min_votes_required) - { - // We don't have enough stage 3 proposals to create a ledger. - LOG_DEBUG << "Not enough stage 3 proposals to create a ledger. received:" << stage3_prop_count << " needed:" << min_votes_required; - return; - } + // Return -1 if there are no proposals to evaluate. + if (proposal_count == 0) + return -1; // Find the winning hash and no. of votes for it. - uint32_t winning_votes = 0; + winning_votes = 0; util::h32 winning_hash = util::h32_empty; for (const auto [hash, proposals] : proposal_groups) { @@ -276,16 +284,44 @@ namespace consensus } } - if (winning_votes < min_votes_required) + // Return -1 if there are no winning proposal. + if (winning_votes == 0) + return -1; + + // Consensus reached. This is the winning set of proposals. + std::vector &winning_group = proposal_groups[winning_hash]; + + winning_proposal = std::move(winning_group.front()); + + return winning_votes; + } + + /** + * Scan the stage 3 proposals from last round and create the ledger if all majority criteria are met. + * @return true on successful ledger closure and false on failure. + */ + void attempt_ledger_close() + { + uint32_t stage3_prop_count = 0; + uint32_t winning_votes = 0; + p2p::proposal winning_prop; + const uint32_t min_votes_required = ceil((conf::cfg.contract.consensus.threshold * unl::count()) / 100.0); + + evaluate_proposals(stage3_prop_count, winning_votes, winning_prop, 3); + + // Threshold is divided by 100 to convert average to decimal. + if (stage3_prop_count < min_votes_required) + { + // We don't have enough stage 3 proposals to create a ledger. + LOG_DEBUG << "Not enough stage 3 proposals to create a ledger. received:" << stage3_prop_count << " needed:" << min_votes_required; + return; + } + else if (winning_votes < min_votes_required) { LOG_INFO << "Cannot close ledger. Possible fork condition. won:" << winning_votes << " needed:" << min_votes_required; return; } - // Consensus reached. This is the winning set of proposals. - std::vector &winning_group = proposal_groups[winning_hash]; - - p2p::proposal &winning_prop = winning_group.front(); LOG_DEBUG << "Closing ledger with proposal:" << winning_prop.root_hash; // Upon successful ledger close condition, update the ledger and execute the contract using the consensus proposal. @@ -293,16 +329,18 @@ namespace consensus if (prepare_consensed_users(consensed_users, winning_prop) == -1 || commit_consensus_results(winning_prop, consensed_users) == -1) { - LOG_ERROR << "Error occured when closing ledger"; + LOG_ERROR << "Error occurred when closing ledger"; // Cleanup obsolete information before next round starts. cleanup_output_collections(); cleanup_consensed_user_inputs(consensed_users); } + + return; } /** - * Performs the consensus finalalization activities with the provided consensused information. + * Performs the consensus finalization activities with the provided consensed information. * @param cons_prop The proposal which reached consensus. * @param consensed_users Set of consensed users and their consensed inputs and outputs. */ @@ -338,7 +376,8 @@ namespace consensus // Apply consensed config patch file changes to the hpcore runtime and hp.cfg. const util::h32 patch_hash = sc::contract_fs.get_parent_hash(sc::PATCH_FILE_PATH); - if (apply_consensed_patch_file_changes(cons_prop.patch_hash, patch_hash) == -1) + // Check whether is there any patch changes to be applied which reached consensus. + if (patch_hash == cons_prop.patch_hash && apply_consensed_patch_file_changes() == -1) return -1; // Execute the smart contract with the consensed user inputs. @@ -795,7 +834,7 @@ namespace consensus if (ctx.contract_ctx->args.lcl_id == npl_msg.lcl_id) return ctx.contract_ctx->args.npl_messages.try_enqueue(std::move(npl_msg)); else - LOG_DEBUG << "Trying to add irrelevant NPL from " << util::to_hex(npl_msg.pubkey) << " | lcl-seq: " << npl_msg.lcl_id.seq_no; + LOG_DEBUG << "Trying to add irrelevant NPL from " << util::to_hex(npl_msg.pubkey) << " | lcl-seq: " << npl_msg.lcl_id.seq_no; } return false; } @@ -904,8 +943,8 @@ namespace consensus return 0; } - p2p::proposal create_stage0_proposal(const util::h32 &state_hash, const util::h32 &patch_hash, - const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id) + p2p::proposal create_stage0_proposal(const util::h32 &state_hash, const util::h32 &patch_hash, const util::sequence_hash &last_primary_shard_id, + const util::sequence_hash &last_raw_shard_id, const util::sequence_hash &lcl_id) { // This is the proposal that stage 0 votes on. // We report our own values in stage 0. @@ -917,6 +956,7 @@ namespace consensus p.last_primary_shard_id = last_primary_shard_id; p.last_raw_shard_id = last_raw_shard_id; p.time_config = CURRENT_TIME_CONFIG; + p.lcl_id = lcl_id; // In stage 0 proposals, we calculate a random nonce from this node to contribute to the group nonce std::string rand_bytes; @@ -939,7 +979,7 @@ namespace consensus } p2p::proposal create_stage123_proposal(vote_counter &votes, const size_t unl_count, const util::h32 &state_hash, const util::h32 &patch_hash, - const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id) + const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id, const util::sequence_hash &lcl_id) { // The proposal to be emited at the end of this stage. p2p::proposal p; @@ -955,6 +995,7 @@ namespace consensus p.time_config = CURRENT_TIME_CONFIG; p.output_hash.resize(BLAKE3_OUT_LEN); // Default empty hash. p.node_nonce = ctx.round_nonce; + p.lcl_id = lcl_id; const uint64_t time_now = util::get_epoch_milliseconds(); @@ -1208,7 +1249,7 @@ namespace consensus } sc::contract_execution_args &args = ctx.contract_ctx->args; - args.readonly = false; + args.mode = sc::EXECUTION_MODE::CONSENSUS; args.time = time; // lcl to be passed to the contract. @@ -1252,6 +1293,65 @@ namespace consensus return 0; } + /** + * Executes the contract on consensus failure. + * @param stage Stage the consensus are currently in. + * @param lcl_id Current lcl id of the node. + */ + bool execute_contract_in_fallback(const uint8_t stage, const util::sequence_hash &lcl_id) + { + // Do not execute if fallback is not enabled, HotPocket is shutting down. + if (!conf::cfg.contract.consensus.fallback.execute || ctx.is_shutting_down) + return false; + + // Pass new user store for inputs, We are not handling inputs in fallback mode right now. + util::buffer_store fallback_store; + { + std::scoped_lock lock(ctx.contract_ctx_mutex); + ctx.contract_ctx.emplace(fallback_store); + } + + sc::contract_execution_args &args = ctx.contract_ctx->args; + args.mode = sc::EXECUTION_MODE::CONSENSUS_FALLBACK; + + // lcl to be passed to the contract. + args.lcl_id = lcl_id; + args.non_consensus_rounds = ctx.non_consensus_rounds; + + uint32_t stage3_prop_count = 0; + uint32_t winning_votes = 0; + p2p::proposal winning_prop; + // Evaluate proposals and take tike from winning proposal. + if (evaluate_proposals(stage3_prop_count, winning_votes, winning_prop, (stage + 3) % 4) > 0) + args.time = winning_prop.time; + + // We should end the contact before this round end, Otherwise we'll trap inside a round reset loop. + // We keep a margin of 100 milliseconds to avoid contract monitor thread hangs. + args.end_before = (ctx.round_start_time + conf::cfg.contract.consensus.roundtime - FALLBACK_CONTRACT_TERMINATE_MARGIN); + + bool executed = false; + // Execute contract in fallback mode without user inputs or outputs. + if (sc::execute_contract(ctx.contract_ctx.value()) == -1) + { + LOG_ERROR << "Contract execution for fallback mode failed."; + } + else + { + // Get the new state hash after contract execution. + const util::h32 &new_state_hash = args.post_execution_state_hash; + // Update state hash in contract fs global hash tracker. + sc::contract_fs.set_parent_hash(sc::STATE_DIR_PATH, new_state_hash); + executed = true; + } + + { + std::scoped_lock lock(ctx.contract_ctx_mutex); + ctx.contract_ctx.reset(); + } + + return executed; + } + /** * Dispatch acceptence status responses to consensed user inputs, if the recipients are connected to us locally. * @param consensed_users The map of consensed users containing their inputs. @@ -1417,14 +1517,12 @@ namespace consensus /** * Apply patch file changes after verification from consensus. - * @param prop_patch_hash Hash of patch file which reached consensus. - * @param current_patch_hash Hash of the current patch file. * @return 0 on success. -1 on failure. */ - int apply_consensed_patch_file_changes(const util::h32 &prop_patch_hash, const util::h32 ¤t_patch_hash) + int apply_consensed_patch_file_changes() { - // Check whether is there any patch changes to be applied which reached consensus. - if (is_patch_update_pending && current_patch_hash == prop_patch_hash) + // Check whether is there any patch changes to be applied. + if (is_patch_update_pending) { if (sc::contract_fs.start_ro_session(HPFS_SESSION_NAME, false) != -1) { diff --git a/src/consensus.hpp b/src/consensus.hpp index 11434779..4d0e2b51 100644 --- a/src/consensus.hpp +++ b/src/consensus.hpp @@ -113,6 +113,7 @@ namespace consensus uint64_t round_boundry_offset = 0; // Time window boundry offset based on contract id. uint16_t unreliable_votes_attempts = 0; // No. of times we failed to get reliable votes continously. util::h32 round_nonce; // The random nonce generated by this node for this consensus round. + uint16_t non_consensus_rounds = 0; // No. of times we failed reach the consensus. // Indicates whether we are inside a sync cycle or not. Sync cycle is considered to being when we first detect that we are out of sync // and considered to end when we detect to be in sync inside stage 1 of a round for the first time after we began a sync. @@ -167,6 +168,8 @@ namespace consensus int consensus(); + int evaluate_proposals(uint32_t &proposal_count, uint32_t &winning_votes, p2p::proposal &winning_proposal, const uint8_t stage); + void attempt_ledger_close(); int commit_consensus_results(const p2p::proposal &cons_prop, const consensus::consensed_user_map &consensed_users); @@ -191,11 +194,11 @@ namespace consensus int verify_and_populate_candidate_user_inputs(const uint64_t lcl_seq_no); - p2p::proposal create_stage0_proposal(const util::h32 &state_hash, const util::h32 &patch_hash, - const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id); + p2p::proposal create_stage0_proposal(const util::h32 &state_hash, const util::h32 &patch_hash, const util::sequence_hash &last_primary_shard_id, + const util::sequence_hash &last_raw_shard_id, const util::sequence_hash &lcl_id); p2p::proposal create_stage123_proposal(vote_counter &votes, const size_t unl_count, const util::h32 &state_hash, const util::h32 &patch_hash, - const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id); + const util::sequence_hash &last_primary_shard_id, const util::sequence_hash &last_raw_shard_id, const util::sequence_hash &lcl_id); void broadcast_proposal(const p2p::proposal &p); @@ -215,6 +218,8 @@ namespace consensus int execute_contract(const uint64_t time, const consensed_user_map &consensed_users, const util::sequence_hash &lcl_id); + bool execute_contract_in_fallback(const uint8_t stage, const util::sequence_hash &lcl_id); + void dispatch_consensed_user_input_responses(const consensed_user_map &consensed_users, const util::sequence_hash &lcl_id); void dispatch_consensed_user_outputs(const consensed_user_map &consensed_users, const util::sequence_hash &lcl_id); @@ -232,7 +237,7 @@ namespace consensus bool push_control_message(const std::string &control_msg); - int apply_consensed_patch_file_changes(const util::h32 &prop_patch_hash, const util::h32 ¤t_patch_hash); + int apply_consensed_patch_file_changes(); void refresh_time_config(const bool perform_detection); diff --git a/src/msg/fbuf/p2pmsg.fbs b/src/msg/fbuf/p2pmsg.fbs index acb0ab61..1c1d32fa 100644 --- a/src/msg/fbuf/p2pmsg.fbs +++ b/src/msg/fbuf/p2pmsg.fbs @@ -68,6 +68,7 @@ table ProposalMsg { output_sig:[ubyte]; state_hash: [ubyte]; patch_hash: [ubyte]; + lcl_id:SequenceHash; last_primary_shard_id:SequenceHash; last_raw_shard_id: SequenceHash; diff --git a/src/msg/fbuf/p2pmsg_conversion.cpp b/src/msg/fbuf/p2pmsg_conversion.cpp index 4c70923a..9d850e61 100644 --- a/src/msg/fbuf/p2pmsg_conversion.cpp +++ b/src/msg/fbuf/p2pmsg_conversion.cpp @@ -157,6 +157,7 @@ namespace msg::fbuf::p2pmsg p.stage = msg.stage(); p.state_hash = flatbuf_bytes_to_sv(msg.state_hash()); p.patch_hash = flatbuf_bytes_to_sv(msg.patch_hash()); + p.lcl_id = flatbuf_seqhash_to_seqhash(msg.lcl_id()); p.last_primary_shard_id = flatbuf_seqhash_to_seqhash(msg.last_primary_shard_id()); p.last_raw_shard_id = flatbuf_seqhash_to_seqhash(msg.last_raw_shard_id()); @@ -432,6 +433,7 @@ namespace msg::fbuf::p2pmsg sv_to_flatbuf_bytes(builder, p.output_sig), hash_to_flatbuf_bytes(builder, p.state_hash), hash_to_flatbuf_bytes(builder, p.patch_hash), + seqhash_to_flatbuf_seqhash(builder, p.lcl_id), seqhash_to_flatbuf_seqhash(builder, p.last_primary_shard_id), seqhash_to_flatbuf_seqhash(builder, p.last_raw_shard_id)); diff --git a/src/msg/fbuf/p2pmsg_generated.h b/src/msg/fbuf/p2pmsg_generated.h index 799b4e80..c297e5c5 100644 --- a/src/msg/fbuf/p2pmsg_generated.h +++ b/src/msg/fbuf/p2pmsg_generated.h @@ -1006,8 +1006,9 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_OUTPUT_SIG = 24, VT_STATE_HASH = 26, VT_PATCH_HASH = 28, - VT_LAST_PRIMARY_SHARD_ID = 30, - VT_LAST_RAW_SHARD_ID = 32 + VT_LCL_ID = 30, + VT_LAST_PRIMARY_SHARD_ID = 32, + VT_LAST_RAW_SHARD_ID = 34 }; const flatbuffers::Vector *pubkey() const { return GetPointer *>(VT_PUBKEY); @@ -1087,6 +1088,12 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { flatbuffers::Vector *mutable_patch_hash() { return GetPointer *>(VT_PATCH_HASH); } + const msg::fbuf::p2pmsg::SequenceHash *lcl_id() const { + return GetPointer(VT_LCL_ID); + } + msg::fbuf::p2pmsg::SequenceHash *mutable_lcl_id() { + return GetPointer(VT_LCL_ID); + } const msg::fbuf::p2pmsg::SequenceHash *last_primary_shard_id() const { return GetPointer(VT_LAST_PRIMARY_SHARD_ID); } @@ -1126,6 +1133,8 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyVector(state_hash()) && VerifyOffset(verifier, VT_PATCH_HASH) && verifier.VerifyVector(patch_hash()) && + VerifyOffset(verifier, VT_LCL_ID) && + verifier.VerifyTable(lcl_id()) && VerifyOffset(verifier, VT_LAST_PRIMARY_SHARD_ID) && verifier.VerifyTable(last_primary_shard_id()) && VerifyOffset(verifier, VT_LAST_RAW_SHARD_ID) && @@ -1177,6 +1186,9 @@ struct ProposalMsgBuilder { void add_patch_hash(flatbuffers::Offset> patch_hash) { fbb_.AddOffset(ProposalMsg::VT_PATCH_HASH, patch_hash); } + void add_lcl_id(flatbuffers::Offset lcl_id) { + fbb_.AddOffset(ProposalMsg::VT_LCL_ID, lcl_id); + } void add_last_primary_shard_id(flatbuffers::Offset last_primary_shard_id) { fbb_.AddOffset(ProposalMsg::VT_LAST_PRIMARY_SHARD_ID, last_primary_shard_id); } @@ -1210,12 +1222,14 @@ inline flatbuffers::Offset CreateProposalMsg( flatbuffers::Offset> output_sig = 0, flatbuffers::Offset> state_hash = 0, flatbuffers::Offset> patch_hash = 0, + flatbuffers::Offset lcl_id = 0, flatbuffers::Offset last_primary_shard_id = 0, flatbuffers::Offset last_raw_shard_id = 0) { ProposalMsgBuilder builder_(_fbb); builder_.add_time(time); builder_.add_last_raw_shard_id(last_raw_shard_id); builder_.add_last_primary_shard_id(last_primary_shard_id); + builder_.add_lcl_id(lcl_id); builder_.add_patch_hash(patch_hash); builder_.add_state_hash(state_hash); builder_.add_output_sig(output_sig); @@ -1246,6 +1260,7 @@ inline flatbuffers::Offset CreateProposalMsgDirect( const std::vector *output_sig = nullptr, const std::vector *state_hash = nullptr, const std::vector *patch_hash = nullptr, + flatbuffers::Offset lcl_id = 0, flatbuffers::Offset last_primary_shard_id = 0, flatbuffers::Offset last_raw_shard_id = 0) { auto pubkey__ = pubkey ? _fbb.CreateVector(*pubkey) : 0; @@ -1273,6 +1288,7 @@ inline flatbuffers::Offset CreateProposalMsgDirect( output_sig__, state_hash__, patch_hash__, + lcl_id, last_primary_shard_id, last_raw_shard_id); } diff --git a/src/p2p/p2p.hpp b/src/p2p/p2p.hpp index 2890bf5a..3feb43eb 100644 --- a/src/p2p/p2p.hpp +++ b/src/p2p/p2p.hpp @@ -62,6 +62,7 @@ namespace p2p std::set input_ordered_hashes; std::string output_hash; std::string output_sig; + util::sequence_hash lcl_id; }; struct nonunl_proposal diff --git a/src/sc/sc.cpp b/src/sc/sc.cpp index 284da8a5..4535fd77 100644 --- a/src/sc/sc.cpp +++ b/src/sc/sc.cpp @@ -91,7 +91,7 @@ namespace sc ctx.working_dir = contract_fs.physical_path(ctx.args.hpfs_session_name, STATE_DIR_PATH); // Setup contract output log file paths (for consensus execution only). - if (conf::cfg.contract.log.enable && !ctx.args.readonly) + if (conf::cfg.contract.log.enable && ctx.args.mode == EXECUTION_MODE::CONSENSUS) { // We keep appending logs to the same out/err files (Rollout log files are maintained according to the hp config settings). const std::string prefix = ctx.args.hpfs_session_name; @@ -122,14 +122,17 @@ namespace sc // (Note: User socket will only be used for contract output only. For feeding user inputs we are using a memfd.) if (create_iosockets_for_fdmap(ctx.user_fds, ctx.args.userbufs) == -1 || create_iosockets(ctx.control_fds, SOCK_SEQPACKET) == -1 || - (!ctx.args.readonly && create_iosockets(ctx.npl_fds, SOCK_SEQPACKET) == -1)) + (ctx.args.mode != EXECUTION_MODE::READ_REQUEST && create_iosockets(ctx.npl_fds, SOCK_SEQPACKET) == -1)) { cleanup_fds(ctx); stop_hpfs_session(ctx); return -1; } - LOG_DEBUG << "Starting contract process..." << (ctx.args.readonly ? " (rdonly)" : ""); + std::string_view mode = ctx.args.get_exec_mode_str(); + + LOG_DEBUG << "Starting contract process..." + << "(" << mode << ")"; int ret = 0; const pid_t pid = fork(); @@ -157,14 +160,18 @@ namespace sc if (insert_demarkation_line(ctx) == -1) { - std::cerr << errno << ": Contract process inserting demarkation line failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Contract process inserting demarkation line failed." + << "(" << mode << ")" + << "\n"; exit(1); } // Set process resource limits. if (set_process_rlimits() == -1) { - std::cerr << errno << ": Failed to set contract process resource limits." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Failed to set contract process resource limits." + << "(" << mode << ")" + << "\n"; exit(1); } @@ -195,7 +202,9 @@ namespace sc if (chdir(ctx.working_dir.c_str()) == -1) { - std::cerr << errno << ": Contract process chdir failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Contract process chdir failed." + << "(" << mode << ")" + << "\n"; exit(1); } @@ -203,27 +212,32 @@ namespace sc // (Must set gid before setting uid) if (!conf::cfg.contract.run_as.empty() && (setgid(conf::cfg.contract.run_as.gid) == -1 || setuid(conf::cfg.contract.run_as.uid) == -1)) { - std::cerr << errno << ": Contract process setgid/uid failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Contract process setgid/uid failed." + << "(" << mode << ")" + << "\n"; exit(1); } // We do not create logs files in readonly execution due to the difficulty in managing the log file limits. - (conf::cfg.contract.log.enable && !ctx.args.readonly) + (conf::cfg.contract.log.enable && ctx.args.mode == EXECUTION_MODE::CONSENSUS) ? execv_and_redirect_logs(execv_len - 1, (const char **)execv_args, ctx.stdout_file, ctx.stderr_file, (const char **)env_args) : execve(execv_args[0], execv_args, env_args); - std::cerr << errno << ": Contract process execve() failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Contract process execve() failed." + << "(" << mode << ")" + << "\n"; exit(1); } else { - LOG_ERROR << errno << ": fork() failed when starting contract process." << (ctx.args.readonly ? " (rdonly)" : ""); + LOG_ERROR << errno << ": fork() failed when starting contract process." + << "(" << mode << ")"; ret = -1; } cleanup_fds(ctx); // If the consensus contact finished executing successfully, run the post-exec.sh script if it exists. - if (ctx.exit_success && !ctx.args.readonly && run_post_exec_script(ctx) == -1) + if (ctx.exit_success && ctx.args.mode == EXECUTION_MODE::CONSENSUS && run_post_exec_script(ctx) == -1) ret = -1; if (stop_hpfs_session(ctx) == -1) @@ -283,16 +297,20 @@ namespace sc else // Child has exited { ctx.contract_pid = 0; + std::string_view mode = ctx.args.get_exec_mode_str(); if (WIFEXITED(scstatus)) { ctx.exit_success = true; - LOG_DEBUG << "Contract process" << (ctx.args.readonly ? " (rdonly)" : "") << " ended normally."; + LOG_DEBUG << "Contract process ended normally. " + << "(" << mode << ")"; return 1; } else { - LOG_WARNING << "Contract process" << (ctx.args.readonly ? " (rdonly)" : "") << " ended prematurely. Exit code " << WEXITSTATUS(scstatus); + LOG_WARNING << "Contract process ended prematurely. " + << "(" << mode << ") " + << "Exit code " << WEXITSTATUS(scstatus); return -1; } } @@ -303,11 +321,11 @@ namespace sc */ int start_hpfs_session(execution_context &ctx) { - if (!ctx.args.readonly) + if (ctx.args.mode != EXECUTION_MODE::READ_REQUEST) ctx.args.hpfs_session_name = hpfs::RW_SESSION_NAME; - return ctx.args.readonly ? contract_fs.start_ro_session(ctx.args.hpfs_session_name, false) - : contract_fs.acquire_rw_session(); + return ctx.args.mode == EXECUTION_MODE::READ_REQUEST ? contract_fs.start_ro_session(ctx.args.hpfs_session_name, false) + : contract_fs.acquire_rw_session(); } /** @@ -315,7 +333,7 @@ namespace sc */ int stop_hpfs_session(execution_context &ctx) { - if (ctx.args.readonly) + if (ctx.args.mode == EXECUTION_MODE::READ_REQUEST) { return contract_fs.stop_ro_session(ctx.args.hpfs_session_name); } @@ -357,7 +375,7 @@ namespace sc * "public_key": "", * "private_key": "", * "timestamp": , - * "readonly": , + * "mode": , * "lcl_seq_no": "", * "lcl_hex": "", * "control_fd": fd, @@ -367,7 +385,7 @@ namespace sc * "unl":[ "", ... ] * } */ - int write_contract_args(const execution_context &ctx, const int user_inputs_fd) + int write_contract_args(execution_context &ctx, const int user_inputs_fd) { // Populate the json string with contract args. // We don't use a JSON parser here because it's lightweight to contrstuct the @@ -379,15 +397,20 @@ namespace sc << "\",\"public_key\":\"" << conf::cfg.node.public_key_hex << "\",\"private_key\":\"" << conf::cfg.node.private_key_hex << "\",\"timestamp\":" << ctx.args.time - << ",\"readonly\":" << (ctx.args.readonly ? "true" : "false"); + << ",\"mode\":\"" << ctx.args.get_exec_mode_str() << "\""; - if (!ctx.args.readonly) + if (ctx.args.mode != EXECUTION_MODE::READ_REQUEST) { os << ",\"lcl_seq_no\":" << ctx.args.lcl_id.seq_no << ",\"lcl_hash\":\"" << util::to_hex(ctx.args.lcl_id.hash.to_string_view()) << "\",\"npl_fd\":" << ctx.npl_fds.scfd; } + if (ctx.args.mode == EXECUTION_MODE::CONSENSUS_FALLBACK) + { + os << ",\"non_consensus_rounds\":" << ctx.args.non_consensus_rounds; + } + os << ",\"control_fd\":" << ctx.control_fds.scfd; os << ",\"user_in_fd\":" << user_inputs_fd @@ -435,11 +458,19 @@ namespace sc // We record the start time of the monitoring thread to track the contract execution timeout. const uint64_t start_time = util::get_epoch_milliseconds(); - const uint64_t exec_timeout = conf::cfg.contract.round_limits.exec_timeout; + // If this is in fallback mode, we should terminate the contract before the given timeout. + const uint64_t exec_timeout = ctx.args.mode == EXECUTION_MODE::CONSENSUS_FALLBACK ? (ctx.args.end_before - start_time) : conf::cfg.contract.round_limits.exec_timeout; + + // If this is in fallback mode, check wether we haven't passed the round end. If not, do not execute. + if (ctx.args.mode == EXECUTION_MODE::CONSENSUS_FALLBACK && start_time >= ctx.args.end_before) + { + LOG_INFO << "Contract process end time has passed."; + return; + } // Prepare output poll fd list. - // User out fds + control fd + NPL fd (NPL fd not available in readonly mode) - const size_t out_fd_count = ctx.user_fds.size() + (ctx.args.readonly ? 1 : 2); + // User out fds + control fd + NPL fd (NPL fd not available in read request mode) + const size_t out_fd_count = ctx.user_fds.size() + (ctx.args.mode == EXECUTION_MODE::READ_REQUEST ? 1 : 2); const size_t control_fd_idx = ctx.user_fds.size(); const size_t npl_fd_idx = control_fd_idx + 1; struct pollfd out_fds[out_fd_count]; @@ -480,7 +511,7 @@ namespace sc // Attempt to read messages from contract (regardless of contract terminated or not). const int control_read_res = read_control_outputs(ctx, out_fds[control_fd_idx]); - const int npl_read_res = ctx.args.readonly ? 0 : read_npl_outputs(ctx, &out_fds[npl_fd_idx]); + const int npl_read_res = ctx.args.mode == EXECUTION_MODE::READ_REQUEST ? 0 : read_npl_outputs(ctx, &out_fds[npl_fd_idx]); const int user_read_res = read_contract_fdmap_outputs(ctx.user_fds, out_fds, ctx.args.userbufs); messages_read = (control_read_res + npl_read_res + user_read_res) > 0; @@ -495,7 +526,7 @@ namespace sc { // Reaching here means the contract is still running. Attempt to write any queued messages to the contract. - const int npl_write_res = ctx.args.readonly ? 0 : write_npl_messages(ctx); + const int npl_write_res = ctx.args.mode == EXECUTION_MODE::READ_REQUEST ? 0 : write_npl_messages(ctx); if (npl_write_res == -1) break; @@ -550,24 +581,31 @@ namespace sc util::fork_detach(); const std::string script_args = std::to_string(ctx.args.lcl_id.seq_no) + " " + util::to_hex(ctx.args.lcl_id.hash.to_string_view()); + std::string_view mode = ctx.args.get_exec_mode_str(); // We set current working dir and pass command line arg to the script. char *argv[] = {(char *)POST_EXEC_SCRIPT, (char *)script_args.data(), (char *)NULL}; if (chdir(ctx.working_dir.c_str()) == -1) { - std::cerr << errno << ": Post-exec script chdir failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Post-exec script chdir failed." + << "(" << mode << ")" + << "\n"; exit(1); } // Set user execution user/group if specified (Must set gid before setting uid). if (!conf::cfg.contract.run_as.empty() && (setgid(conf::cfg.contract.run_as.gid) == -1 || setuid(conf::cfg.contract.run_as.uid) == -1)) { - std::cerr << errno << ": Post-exec script setgid/uid failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Post-exec script setgid/uid failed." + << "(" << mode << ")" + << "\n"; exit(1); } conf::cfg.contract.log.enable ? execv_and_redirect_logs(2, (const char **)argv, ctx.stdout_file, ctx.stderr_file) : execv(argv[0], argv); - std::cerr << errno << ": Post-exec script execv() failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + std::cerr << errno << ": Post-exec script execv() failed." + << "(" << mode << ")" + << "\n"; exit(1); } else if (pid > 0) @@ -904,7 +942,7 @@ namespace sc */ int insert_demarkation_line(execution_context &ctx) { - if (!conf::cfg.contract.log.enable || ctx.args.readonly) + if (!conf::cfg.contract.log.enable || ctx.args.mode != EXECUTION_MODE::CONSENSUS) return 0; // The permissions of a created file are restricted by the process's current umask, so group and world write are always disabled by default. @@ -1066,7 +1104,7 @@ namespace sc void close_unused_fds(execution_context &ctx, const bool is_hp) { - if (!ctx.args.readonly) + if (ctx.args.mode != EXECUTION_MODE::READ_REQUEST) { close_unused_socket_fds(is_hp, ctx.npl_fds); } diff --git a/src/sc/sc.hpp b/src/sc/sc.hpp index 7ef679b6..442e2fd0 100644 --- a/src/sc/sc.hpp +++ b/src/sc/sc.hpp @@ -19,6 +19,14 @@ namespace sc constexpr uint16_t MAX_NPL_MSG_QUEUE_SIZE = 255; // Maximum npl message queue size, The size passed is rounded to next number in binary sequence 1(1),11(3),111(7),1111(15),11111(31).... constexpr uint16_t MAX_CONTROL_MSG_QUEUE_SIZE = 255; // Maximum out message queue size, The size passed is rounded to next number in binary sequence 1(1),11(3),111(7),1111(15),11111(31).... + // Contract execution mode. + enum EXECUTION_MODE + { + CONSENSUS = 0, + CONSENSUS_FALLBACK = 1, + READ_REQUEST = 2 + }; + struct fd_pair { int hpfd = -1; @@ -27,7 +35,7 @@ namespace sc /** * Stores contract output message length along with the message. Length is used to construct the message from the stream buffer. - */ + */ struct contract_output { uint32_t message_len = 0; @@ -67,8 +75,8 @@ namespace sc */ struct contract_execution_args { - // Whether the contract should execute in read only mode (to serve read requests). - bool readonly = false; + // Contract execution mode. + EXECUTION_MODE mode; // hpfs session name used for this execution. std::string hpfs_session_name; @@ -94,12 +102,32 @@ namespace sc // State hash after execution will be copied to this (not applicable to read only mode). util::h32 post_execution_state_hash = util::h32_empty; + uint64_t end_before; + + // This is for fallback mode, No of times we failed reach the consensus. + uint16_t non_consensus_rounds = 0; + contract_execution_args(util::buffer_store &user_input_store) : user_input_store(user_input_store), npl_messages(MAX_NPL_MSG_QUEUE_SIZE), control_messages(MAX_CONTROL_MSG_QUEUE_SIZE) { } + + // Convert execution mode to string. + std::string_view get_exec_mode_str() + { + if (mode == EXECUTION_MODE::CONSENSUS_FALLBACK) + { + return "consensus_fallback"; + } + else if (mode == EXECUTION_MODE::READ_REQUEST) + { + return "read_req"; + } + + return "consensus"; + } }; /** @@ -164,7 +192,7 @@ namespace sc int stop_hpfs_session(execution_context &ctx); - int write_contract_args(const execution_context &ctx, const int user_inputs_fd); + int write_contract_args(execution_context &ctx, const int user_inputs_fd); void contract_monitor_loop(execution_context &ctx); diff --git a/src/unl.cpp b/src/unl.cpp index 47ff4cd3..2282c26b 100644 --- a/src/unl.cpp +++ b/src/unl.cpp @@ -12,8 +12,9 @@ namespace unl { struct node_stat { - uint32_t time_config = 0; // Roundtime config of this node. - uint64_t active_on = 0; // Latest timestamp we received a proposal from this node. + uint32_t time_config = 0; // Roundtime config of this node. + uint64_t active_on = 0; // Latest timestamp we received a proposal from this node. + util::sequence_hash lcl_id; // Current HotPocket lcl (seq no. and ledger hash hex) }; std::map list; // List of binary pubkeys of UNL nodes and their statistics. @@ -61,7 +62,7 @@ namespace unl * Check whether the given pubkey is in the unl list. * @param bin_pubkey Pubkey to check for existence. * @return Return true if the given pubkey is in the unl list. - */ + */ bool exists(const std::string &bin_pubkey) { std::shared_lock lock(unl_mutex); @@ -70,7 +71,7 @@ namespace unl /** * Replace the unl list from the latest unl list from patch file. - */ + */ void update_unl_changes_from_patch() { bool is_unl_list_changed = false; @@ -100,6 +101,7 @@ namespace unl if (itr != list.end()) { changes_made = true; + itr->second.lcl_id = p.lcl_id; itr->second.active_on = p.recv_timestamp; itr->second.time_config = p.time_config; } @@ -210,7 +212,9 @@ namespace unl // Convert binary pubkey into hex. os << "\"" << util::to_hex(node->first) << "\":{" - << "\"active_on\":" << node->second.active_on + << "\"active_on\":" << node->second.active_on << "," + << "\"lcl_seq_no\":" << node->second.lcl_id.seq_no << "," + << "\"lcl_hash\":\"" << util::to_hex(node->second.lcl_id.hash.to_string_view()) << "\"" << "}"; } os << "}"; diff --git a/src/usr/read_req.cpp b/src/usr/read_req.cpp index 9bd93867..1619f9ab 100644 --- a/src/usr/read_req.cpp +++ b/src/usr/read_req.cpp @@ -219,7 +219,7 @@ namespace read_req void initialize_execution_context(const user_read_req &read_request, const pthread_t thread_id, sc::execution_context &contract_ctx) { contract_ctx.args.hpfs_session_name = "ro_" + std::to_string(thread_id); - contract_ctx.args.readonly = true; + contract_ctx.args.mode = sc::EXECUTION_MODE::READ_REQUEST; sc::contract_iobufs user_bufs; user_bufs.inputs.push_back(read_request.content); contract_ctx.args.userbufs.try_emplace(read_request.pubkey, std::move(user_bufs)); diff --git a/src/util/version.hpp b/src/util/version.hpp index 2a0e4bc4..21fdcee6 100644 --- a/src/util/version.hpp +++ b/src/util/version.hpp @@ -6,10 +6,10 @@ namespace version { // HotPocket version. Written to new configs and p2p/user messages. - constexpr const char *HP_VERSION = "0.6.4"; + constexpr const char *HP_VERSION = "0.6.5"; // Minimum compatible config version (this will be used to validate configs). - constexpr const char *MIN_CONFIG_VERSION = "0.6.3"; + constexpr const char *MIN_CONFIG_VERSION = "0.6.5"; // Ledger file storage version. All nodes in a cluster MUST use the same ledger version. constexpr const char *LEDGER_VERSION = "0.6.3"; diff --git a/test/local-cluster/cluster-create.sh b/test/local-cluster/cluster-create.sh index c7603d76..071ad440 100755 --- a/test/local-cluster/cluster-create.sh +++ b/test/local-cluster/cluster-create.sh @@ -16,6 +16,7 @@ fi ncount=$1 loglevel=$2 roundtime=$3 +fallback_enabled=$4 hpcore=$(realpath ../..) iprange="172.1.1" @@ -51,7 +52,7 @@ elif [ "$CONTRACT" = "diag" ]; then # Diagnostic contract else # nodejs echo contract (default) echo "Using nodejs echo contract." pushd $hpcore/examples/nodejs_contract/ > /dev/null 2>&1 - npm install + npm install npm run build-echo popd > /dev/null 2>&1 copyfiles="$hpcore/examples/nodejs_contract/dist/echo-contract/index.js" @@ -65,6 +66,9 @@ fi if [ "$roundtime" = "" ]; then roundtime=1000 fi +if [ "$fallback_enabled" != "true" ]; then + fallback_enabled=false +fi # Delete and recreate 'hpcluster' directory. sudo rm -rf hpcluster > /dev/null 2>&1 @@ -115,7 +119,10 @@ do consensus: { \ ...require('./tmp.json').contract.consensus, \ mode: 'public', \ - roundtime: $roundtime \ + roundtime: $roundtime,\ + fallback: { \ + execute: $fallback_enabled \ + } \ }, \ npl: { \ mode: 'public' \ diff --git a/test/local-cluster/cluster-start.sh b/test/local-cluster/cluster-start.sh index 5c09c737..f52e75eb 100755 --- a/test/local-cluster/cluster-start.sh +++ b/test/local-cluster/cluster-start.sh @@ -14,7 +14,7 @@ fi clusterloc=$(pwd)/hpcluster n=$1 -hpversion=0.6.4 +hpversion=0.6.5 let pubport=8080+$n let peerport=22860+$n diff --git a/test/local-cluster/consensus-test-continuous.sh b/test/local-cluster/consensus-test-continuous.sh index 07e701d5..b6716c41 100644 --- a/test/local-cluster/consensus-test-continuous.sh +++ b/test/local-cluster/consensus-test-continuous.sh @@ -5,7 +5,7 @@ WINDOWSIZE=60 # size of window in seconds to examine for successful consensus ro PIPE=concon.pipe clusterloc=$(pwd)/hpcluster n=1 -hpversion=0.6.4 +hpversion=0.6.5 let pubport=8080+$n while true; do diff --git a/test/local-cluster/consensus-test-loop.sh b/test/local-cluster/consensus-test-loop.sh index 9d5782f6..793fe5a2 100644 --- a/test/local-cluster/consensus-test-loop.sh +++ b/test/local-cluster/consensus-test-loop.sh @@ -3,7 +3,7 @@ clusterloc=$(pwd)/hpcluster n=1 -hpversion=0.6.4 +hpversion=0.6.5 let pubport=8080+$n while true; do CONSENSUS="0" diff --git a/test/local-cluster/rundir.sh b/test/local-cluster/rundir.sh index e95c9058..7a9e0512 100755 --- a/test/local-cluster/rundir.sh +++ b/test/local-cluster/rundir.sh @@ -15,7 +15,7 @@ fi dir=$(realpath $1) dirname=$(basename $dir) n=$1 -hpversion=0.6.4 +hpversion=0.6.5 let pubport=8080 From a9a56420e6542a01abccdc0d1c7a8c09076a4ec5 Mon Sep 17 00:00:00 2001 From: supunvindula Date: Wed, 8 Nov 2023 14:38:13 +0530 Subject: [PATCH 22/23] changed hpsh to debug_shell --- CMakeLists.txt | 6 +- examples/js_client/text-client.js | 4 +- src/conf.cpp | 42 ++++----- src/conf.hpp | 12 +-- .../hpsh.cpp => debug_shell/debug_shell.cpp} | 84 +++++++++--------- .../hpsh.hpp => debug_shell/debug_shell.hpp} | 14 +-- src/main.cpp | 6 +- src/msg/bson/usrmsg_bson.cpp | 22 ++--- src/msg/bson/usrmsg_bson.hpp | 4 +- src/msg/json/usrmsg_json.cpp | 20 ++--- src/msg/json/usrmsg_json.hpp | 4 +- src/msg/usrmsg_common.hpp | 4 +- src/msg/usrmsg_parser.cpp | 12 +-- src/msg/usrmsg_parser.hpp | 4 +- src/usr/usr.cpp | 30 +++---- src/usr/usr.hpp | 2 +- test/bin/{hpsh => debug_shell} | Bin test/local-cluster/Dockerfile | 2 +- 18 files changed, 136 insertions(+), 136 deletions(-) rename src/{hpsh/hpsh.cpp => debug_shell/debug_shell.cpp} (73%) rename src/{hpsh/hpsh.hpp => debug_shell/debug_shell.hpp} (76%) rename test/bin/{hpsh => debug_shell} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2e8590c..6a19a800 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ add_executable(hpcore src/ledger/ledger_sync.cpp src/ledger/ledger_serve.cpp src/ledger/ledger.cpp - src/hpsh/hpsh.cpp + src/debug_shell/debug_shell.cpp src/status.cpp src/consensus.cpp src/main.cpp @@ -78,7 +78,7 @@ target_link_libraries(hpcore add_custom_command(TARGET hpcore POST_BUILD # COMMAND strip ./build/hpcore - COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ + COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/debug_shell ./build/ ) target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) @@ -88,7 +88,7 @@ target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) add_custom_target(docker COMMAND mkdir -p ./test/local-cluster/bin COMMAND cp ./build/hpcore ./test/local-cluster/bin/ - COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./test/local-cluster/bin/ + COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/bin/debug_shell ./test/local-cluster/bin/ COMMAND docker build -t hpcore:latest -t hpcore:0.6.4 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/ ) set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/examples/js_client/text-client.js b/examples/js_client/text-client.js index 3692406b..1e34fa1f 100644 --- a/examples/js_client/text-client.js +++ b/examples/js_client/text-client.js @@ -123,8 +123,8 @@ async function main() { else if (inp === "stat") { hpc.getStatus().then(stat => console.log(stat)); } - else if (inp.startsWith("hpsh ")) { - hpc.submitHpshRequest(inp.substr(5)).then(id => { + else if (inp.startsWith("debug_shell ")) { + hpc.submitDebugShellRequest(inp.substr(12)).then(id => { hpc.on(id, (reply) => { if (reply.data) console.log(reply.data); diff --git a/src/conf.cpp b/src/conf.cpp index 34baa7c4..89e33a45 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -194,7 +194,7 @@ namespace conf cfg.log.loggers.emplace("console"); cfg.log.loggers.emplace("file"); - cfg.hpsh.enabled = false; + cfg.debug_shell.enabled = false; // Save the default settings into the config file. if (write_config(cfg) != 0) @@ -244,7 +244,7 @@ namespace conf ctx.hpws_exe_path = ctx.exe_dir + "/" + "hpws"; ctx.hpfs_exe_path = ctx.exe_dir + "/" + "hpfs"; - ctx.hpsh_exe_path = ctx.exe_dir + "/" + "hpsh"; + ctx.debug_shell_exe_path = ctx.exe_dir + "/" + "debug_shell"; ctx.contract_dir = basedir; ctx.config_dir = basedir + "/cfg"; @@ -514,24 +514,24 @@ namespace conf } } - // hpsh + // debug_shell { - jpath = "hpsh"; + jpath = "debug_shell"; try { - const jsoncons::ojson &hpsh = d["hpsh"]; - cfg.hpsh.enabled = hpsh["enabled"].as(); + const jsoncons::ojson &debug_shell = d["debug_shell"]; + cfg.debug_shell.enabled = debug_shell["enabled"].as(); - if (cfg.hpsh.run_as.from_string(hpsh["run_as"].as()) == -1) + if (cfg.debug_shell.run_as.from_string(debug_shell["run_as"].as()) == -1) { - std::cerr << "Invalid format for hpsh run as config (\"uid>0:gid>0\" expected).\n"; + std::cerr << "Invalid format for debug_shell run as config (\"uid>0:gid>0\" expected).\n"; return -1; } - jpath = "hpsh.users"; - cfg.hpsh.users.clear(); - for (auto &userpk : hpsh["users"].array_range()) + jpath = "debug_shell.users"; + cfg.debug_shell.users.clear(); + for (auto &userpk : debug_shell["users"].array_range()) { // Convert the public key hex of each node to binary and store it. const std::string bin_pubkey = util::to_bin(userpk.as()); @@ -540,7 +540,7 @@ namespace conf std::cerr << "Error decoding user pubkey list.\n"; return -1; } - cfg.hpsh.users.emplace(bin_pubkey); + cfg.debug_shell.users.emplace(bin_pubkey); } } catch (const std::exception &e) @@ -662,18 +662,18 @@ namespace conf d.insert_or_assign("log", log_config); } - // hpsh configs + // debug_shell configs { - jsoncons::ojson hpsh_config; - hpsh_config.insert_or_assign("enabled", cfg.hpsh.enabled); - hpsh_config.insert_or_assign("run_as", cfg.hpsh.run_as.to_string()); + jsoncons::ojson debug_shell_config; + debug_shell_config.insert_or_assign("enabled", cfg.debug_shell.enabled); + debug_shell_config.insert_or_assign("run_as", cfg.debug_shell.run_as.to_string()); jsoncons::ojson users(jsoncons::json_array_arg); - for (const auto &userpk : cfg.hpsh.users) + for (const auto &userpk : cfg.debug_shell.users) { users.push_back(util::to_hex(userpk)); } - hpsh_config.insert_or_assign("users", users); - d.insert_or_assign("hpsh", hpsh_config); + debug_shell_config.insert_or_assign("users", users); + d.insert_or_assign("debug_shell", debug_shell_config); } return write_json_file(ctx.config_file, d); @@ -771,7 +771,7 @@ namespace conf ctx.tls_cert_file, ctx.hpfs_exe_path, ctx.hpws_exe_path, - ctx.hpsh_exe_path}; + ctx.debug_shell_exe_path}; for (const std::string &path : paths) { @@ -783,7 +783,7 @@ namespace conf << "openssl req -newkey rsa:2048 -new -nodes -x509 -days 365 -keyout tlskey.pem -out tlscert.pem\n" << "and add it to " + ctx.config_dir << std::endl; } - else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path || path == ctx.hpsh_exe_path) + else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path || path == ctx.debug_shell_exe_path) { std::cerr << path << " binary does not exist.\n"; } diff --git a/src/conf.hpp b/src/conf.hpp index 31a5357d..a025a9db 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -208,11 +208,11 @@ namespace conf std::vector runtime_env_args; // Contract environment variables. }; - struct hpsh_config + struct debug_shell_config { - bool enabled = false; // Whether or not to enable hpsh. - ugid run_as; // The user/groups id to execute the hpsh as. - std::set users; // List of users who are allowed to perform hpsh (list of binary public keys). + bool enabled = false; // Whether or not to enable debug_shell. + ugid run_as; // The user/groups id to execute the debug_shell as. + std::set users; // List of users who are allowed to perform debug_shell (list of binary public keys). }; struct user_config @@ -270,7 +270,7 @@ namespace conf std::string exe_dir; // HotPocket executable dir. std::string hpws_exe_path; // hpws executable file path. std::string hpfs_exe_path; // hpfs executable file path. - std::string hpsh_exe_path; // hpsh executable path file + std::string debug_shell_exe_path; // debug_shell executable path file std::string contract_dir; // Contract base directory full path. std::string contract_hpfs_dir; // Contract hpfs metadata dir (The location of hpfs log file). @@ -324,7 +324,7 @@ namespace conf hpfs_config hpfs; log_config log; health_config health; // For debugging only. Not included in the config file. - hpsh_config hpsh; + debug_shell_config debug_shell; }; // Global contract context struct exposed to the application. diff --git a/src/hpsh/hpsh.cpp b/src/debug_shell/debug_shell.cpp similarity index 73% rename from src/hpsh/hpsh.cpp rename to src/debug_shell/debug_shell.cpp index bad45c07..bf25dfa4 100644 --- a/src/hpsh/hpsh.cpp +++ b/src/debug_shell/debug_shell.cpp @@ -1,18 +1,18 @@ -#include "hpsh.hpp" +#include "debug_shell.hpp" -namespace hpsh +namespace debug_shell { - constexpr uint8_t HPSH_CTRL_TERMINATE = 0; - constexpr uint8_t HPSH_CTRL_SH = 1; + constexpr uint8_t DEBUG_SHELL_CTRL_TERMINATE = 0; + constexpr uint8_t DEBUG_SHELL_CTRL_SH = 1; constexpr uint32_t POLL_TIMEOUT = 1000; constexpr uint32_t READ_BUFFER_SIZE = 128 * 1024; - hpsh_context ctx; + debug_shell_context ctx; int init() { // Do not initialize if disabled in config. - if (!conf::cfg.hpsh.enabled) + if (!conf::cfg.debug_shell.enabled) return 0; // Create a socket pair for the control channel. @@ -22,23 +22,23 @@ namespace hpsh return -1; } - // Create a child process for hpsh process - ctx.hpsh_pid = fork(); - if (ctx.hpsh_pid == -1) + // Create a child process for debug_shell process + ctx.debug_shell_pid = fork(); + if (ctx.debug_shell_pid == -1) { LOG_ERROR << errno << ": Error forking hpfs process."; close(ctx.control_fds[0]); close(ctx.control_fds[1]); return -1; } - else if (ctx.hpsh_pid > 0) + else if (ctx.debug_shell_pid > 0) { // Close child end of socket and start the watcher thread. close(ctx.control_fds[0]); ctx.watcher_thread = std::thread(response_watcher); } - else if (ctx.hpsh_pid == 0) + else if (ctx.debug_shell_pid == 0) { util::fork_detach(); @@ -48,20 +48,20 @@ namespace hpsh fd_str.resize(10); snprintf(fd_str.data(), 10, "%d", ctx.control_fds[0]); - char *argv[] = {(char *)conf::ctx.hpsh_exe_path.data(), fd_str.data(), NULL}; + char *argv[] = {(char *)conf::ctx.debug_shell_exe_path.data(), fd_str.data(), NULL}; - // Just before we execv the hpsh binary, we set user execution user/group if specified in hp config. + // Just before we execv the debug_shell binary, we set user execution user/group if specified in hp config. // (Must set gid before setting uid) - if (!conf::cfg.hpsh.run_as.empty() && (setgid(conf::cfg.hpsh.run_as.gid) == -1 || setuid(conf::cfg.hpsh.run_as.uid) == -1)) + if (!conf::cfg.debug_shell.run_as.empty() && (setgid(conf::cfg.debug_shell.run_as.gid) == -1 || setuid(conf::cfg.debug_shell.run_as.uid) == -1)) { - std::cerr << errno << ": Hpsh process setgid/uid failed." + std::cerr << errno << ": DebugShell process setgid/uid failed." << "\n"; exit(1); } execv(argv[0], argv); - std::cerr << errno << ": Error executing hpsh." + std::cerr << errno << ": Error executing debug_shell." << "\n"; close(ctx.control_fds[0]); @@ -70,7 +70,7 @@ namespace hpsh ctx.is_initialized = true; - LOG_INFO << "Hpsh handler started."; + LOG_INFO << "DebugShell handler started."; return 0; } @@ -78,12 +78,12 @@ namespace hpsh void deinit() { // This is not initialized if disabled in config. - if (!conf::cfg.hpsh.enabled) + if (!conf::cfg.debug_shell.enabled) return; ctx.is_shutting_down = true; - if (ctx.hpsh_pid > 0) + if (ctx.debug_shell_pid > 0) send_terminate_message(); // Joining consensus processing thread. @@ -97,24 +97,24 @@ namespace hpsh close(command.out_fd); } - if (ctx.hpsh_pid > 0) + if (ctx.debug_shell_pid > 0) { - // Check if the hpsh has exited voluntarily. - if (check_hpsh_exited(false) == 0) + // Check if the debug_shell has exited voluntarily. + if (check_debug_shell_exited(false) == 0) { - // Issue kill signal to kill the hpsh process. - kill(ctx.hpsh_pid, SIGKILL); - check_hpsh_exited(true); // Blocking wait until exit. + // Issue kill signal to kill the debug_shell process. + kill(ctx.debug_shell_pid, SIGKILL); + check_debug_shell_exited(true); // Blocking wait until exit. } } - LOG_INFO << "Hpsh handler stopped."; + LOG_INFO << "DebugShell handler stopped."; } - int check_hpsh_exited(const bool block) + int check_debug_shell_exited(const bool block) { int scstatus = 0; - const int wait_res = waitpid(ctx.hpsh_pid, &scstatus, block ? 0 : WNOHANG); + const int wait_res = waitpid(ctx.debug_shell_pid, &scstatus, block ? 0 : WNOHANG); if (wait_res == 0) // Child still running. { @@ -122,22 +122,22 @@ namespace hpsh } if (wait_res == -1) { - LOG_ERROR << errno << ": Hpsh process waitpid error. pid:" << ctx.hpsh_pid; - ctx.hpsh_pid = 0; + LOG_ERROR << errno << ": DebugShell process waitpid error. pid:" << ctx.debug_shell_pid; + ctx.debug_shell_pid = 0; return -1; } else // Child has exited { - ctx.hpsh_pid = 0; + ctx.debug_shell_pid = 0; if (WIFEXITED(scstatus)) { - LOG_DEBUG << "Hpsh process ended normally."; + LOG_DEBUG << "DebugShell process ended normally."; return 1; } else { - LOG_WARNING << "Hpsh process ended prematurely. Exit code " << WEXITSTATUS(scstatus); + LOG_WARNING << "DebugShell process ended prematurely. Exit code " << WEXITSTATUS(scstatus); return -1; } } @@ -145,7 +145,7 @@ namespace hpsh int send_terminate_message() { - return (write(ctx.control_fds[1], &HPSH_CTRL_TERMINATE, 1) < 0) ? -1 : 0; + return (write(ctx.control_fds[1], &DEBUG_SHELL_CTRL_TERMINATE, 1) < 0) ? -1 : 0; } void remove_user_commands(std::string_view user_pubkey) @@ -173,18 +173,18 @@ namespace hpsh if (ctx.is_shutting_down) return -1; - if (conf::cfg.hpsh.users.find(std::string(user_pubkey)) == conf::cfg.hpsh.users.end()) + if (conf::cfg.debug_shell.users.find(std::string(user_pubkey)) == conf::cfg.debug_shell.users.end()) { - LOG_ERROR << "This user is not allowed to perform hpsh operations."; + LOG_ERROR << "This user is not allowed to perform debug_shell operations."; return -2; } std::string buffer; buffer.resize(message.size() + 1); - buffer[0] = HPSH_CTRL_SH; + buffer[0] = DEBUG_SHELL_CTRL_SH; memcpy(buffer.data() + 1, message.data(), message.size()); - // Send the hpsh request header. + // Send the debug_shell request header. if (write(ctx.control_fds[1], buffer.data(), message.size() + 1) < 0) { LOG_ERROR << errno << ": Error writing header message to control fd."; @@ -205,7 +205,7 @@ namespace hpsh // Skip if the message does not has file descriptor scm rights. if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS) { - LOG_ERROR << "Message sent on control line from hpsh has non-scm_rights."; + LOG_ERROR << "Message sent on control line from debug_shell has non-scm_rights."; return -1; } @@ -214,7 +214,7 @@ namespace hpsh if (out_fd <= 0) { - LOG_ERROR << "Invalid file descriptor receives on control line from hpsh"; + LOG_ERROR << "Invalid file descriptor receives on control line from debug_shell"; return -1; } @@ -279,7 +279,7 @@ namespace hpsh { const usr::connected_user &user = user_itr->second; msg::usrmsg::usrmsg_parser parser(user.protocol); - usr::send_hpsh_response(std::move(parser), user.session, itr->id, msg::usrmsg::STATUS_ACCEPTED, response); + usr::send_debug_shell_response(std::move(parser), user.session, itr->id, msg::usrmsg::STATUS_ACCEPTED, response); response.clear(); } } @@ -290,7 +290,7 @@ namespace hpsh } else { - LOG_DEBUG << "Hpsh has closed the connection."; + LOG_DEBUG << "DebugShell has closed the connection."; remove = true; } } diff --git a/src/hpsh/hpsh.hpp b/src/debug_shell/debug_shell.hpp similarity index 76% rename from src/hpsh/hpsh.hpp rename to src/debug_shell/debug_shell.hpp index ef9ad675..1d0ea17a 100644 --- a/src/hpsh/hpsh.hpp +++ b/src/debug_shell/debug_shell.hpp @@ -1,12 +1,12 @@ -#ifndef _HP_HPSH_ -#define _HP_HPSH_ +#ifndef _HP_DEBUG_SHELL_ +#define _HP_DEBUG_SHELL_ #include "../pchheader.hpp" #include "../conf.hpp" #include "../usr/usr.hpp" #include "../msg/usrmsg_common.hpp" -namespace hpsh +namespace debug_shell { struct command_context { @@ -15,24 +15,24 @@ namespace hpsh int out_fd; }; - struct hpsh_context + struct debug_shell_context { std::mutex command_mutex; std::list commands; int control_fds[2]; - int hpsh_pid; + int debug_shell_pid; std::thread watcher_thread; bool is_shutting_down; bool is_initialized = false; }; - extern hpsh_context ctx; + extern debug_shell_context ctx; int init(); void deinit(); - int check_hpsh_exited(const bool block); + int check_debug_shell_exited(const bool block); int send_terminate_message(); diff --git a/src/main.cpp b/src/main.cpp index 4f50fae1..2e463c48 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ #include "ledger/ledger.hpp" #include "unl.hpp" #include "killswitch/killswitch.h" -#include "hpsh/hpsh.hpp" +#include "debug_shell/debug_shell.hpp" /** * Parses CLI args and extracts HotPocket command and parameters given. @@ -76,7 +76,7 @@ void deinit() sc::deinit(); ledger::deinit(); conf::deinit(); - hpsh::deinit(); + debug_shell::deinit(); } void sig_exit_handler(int signum) @@ -216,7 +216,7 @@ int main(int argc, char **argv) read_req::init() == -1 || p2p::init() == -1 || usr::init() == -1 || - hpsh::init() == -1) + debug_shell::init() == -1) { deinit(); return -1; diff --git a/src/msg/bson/usrmsg_bson.cpp b/src/msg/bson/usrmsg_bson.cpp index ac415cf6..d41c0169 100644 --- a/src/msg/bson/usrmsg_bson.cpp +++ b/src/msg/bson/usrmsg_bson.cpp @@ -162,11 +162,11 @@ namespace msg::usrmsg::bson } /** - * Constructs a hpsh response message. + * Constructs a debug_shell response message. * @param msg Buffer to construct the generated bson message into. * Message format: * { - * "type": "hpsh_response", + * "type": "debug_shell_response", * "reply_for": "", * "status": "", * "content": "" @@ -174,12 +174,12 @@ namespace msg::usrmsg::bson * } * @param content The contract binary output content to be put in the message. */ - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) + void create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) { jsoncons::bson::bson_bytes_encoder encoder(msg); encoder.begin_object(); encoder.key(msg::usrmsg::FLD_TYPE); - encoder.string_value(msg::usrmsg::MSGTYPE_HPSH_RESPONSE); + encoder.string_value(msg::usrmsg::MSGTYPE_DEBUG_SHELL_RESPONSE); encoder.key(msg::usrmsg::FLD_REPLY_FOR); encoder.string_value(reply_for); encoder.key(msg::usrmsg::FLD_STATUS); @@ -535,29 +535,29 @@ namespace msg::usrmsg::bson } /** - * Extracts a hpsh input message sent by user. + * Extracts a debug_shell input message sent by user. * - * @param extracted_content The content to be passed to the hpsh, extracted from the message. - * @param d The bson document holding the hpsh input message. + * @param extracted_content The content to be passed to the debug_shell, extracted from the message. + * @param d The bson document holding the debug_shell input message. * Accepted signed input container format: * { - * "type": "hpsh_request", + * "type": "debug_shell_request", * "id": "", * "content": * } * @return 0 on successful extraction. -1 for failure. */ - int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d) + int extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d) { if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) { - LOG_DEBUG << "Hpsh input 'id' field missing or invalid."; + LOG_DEBUG << "DebugShell input 'id' field missing or invalid."; return -1; } if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is_byte_string_view()) { - LOG_DEBUG << "Hpsh input 'content' field missing or invalid."; + LOG_DEBUG << "DebugShell input 'content' field missing or invalid."; return -1; } diff --git a/src/msg/bson/usrmsg_bson.hpp b/src/msg/bson/usrmsg_bson.hpp index e485195b..405c72d4 100644 --- a/src/msg/bson/usrmsg_bson.hpp +++ b/src/msg/bson/usrmsg_bson.hpp @@ -17,7 +17,7 @@ namespace msg::usrmsg::bson void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); + void create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); @@ -45,7 +45,7 @@ namespace msg::usrmsg::bson int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); - int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); + int extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::ojson &d); int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::ojson &d); diff --git a/src/msg/json/usrmsg_json.cpp b/src/msg/json/usrmsg_json.cpp index 04c919ce..b875198c 100644 --- a/src/msg/json/usrmsg_json.cpp +++ b/src/msg/json/usrmsg_json.cpp @@ -326,11 +326,11 @@ namespace msg::usrmsg::json } /** - * Constructs a hpsh response message. + * Constructs a debug_shell response message. * @param msg Buffer to construct the generated json message string into. * Message format: * { - * "type": "hpsh_response", + * "type": "debug_shell_response", * "reply_for": "", * "status": "", * "content": "" @@ -338,13 +338,13 @@ namespace msg::usrmsg::json * } * @param content The contract binary output content to be put in the message. */ - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) + void create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) { msg.reserve(content.size() + 256); msg += "{\""; msg += msg::usrmsg::FLD_TYPE; msg += SEP_COLON; - msg += msg::usrmsg::MSGTYPE_HPSH_RESPONSE; + msg += msg::usrmsg::MSGTYPE_DEBUG_SHELL_RESPONSE; msg += SEP_COMMA; msg += msg::usrmsg::FLD_REPLY_FOR; msg += SEP_COLON; @@ -935,29 +935,29 @@ namespace msg::usrmsg::json } /** - * Extracts a hpsh input message sent by user. + * Extracts a debug_shell input message sent by user. * * @param extracted_content The content to be passed to the, extracted from the message. - * @param d The json document holding the hpsh input message. + * @param d The json document holding the debug_shell input message. * Accepted signed input container format: * { - * "type": "hpsh_request", + * "type": "debug_shell_request", * "id": "", * "content": "" * } * @return 0 on successful extraction. -1 for failure. */ - int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d) + int extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d) { if (!d.contains(msg::usrmsg::FLD_ID) || !d[msg::usrmsg::FLD_ID].is()) { - LOG_DEBUG << "Hpsh input 'id' field missing or invalid."; + LOG_DEBUG << "DebugShell input 'id' field missing or invalid."; return -1; } if (!d.contains(msg::usrmsg::FLD_CONTENT) || !d[msg::usrmsg::FLD_CONTENT].is()) { - LOG_DEBUG << "Hpsh input 'content' field missing or invalid."; + LOG_DEBUG << "DebugShell input 'content' field missing or invalid."; return -1; } diff --git a/src/msg/json/usrmsg_json.hpp b/src/msg/json/usrmsg_json.hpp index 0f4b2149..6fe2b610 100644 --- a/src/msg/json/usrmsg_json.hpp +++ b/src/msg/json/usrmsg_json.hpp @@ -21,7 +21,7 @@ namespace msg::usrmsg::json void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash); - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); + void create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason); void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content); @@ -49,7 +49,7 @@ namespace msg::usrmsg::json int extract_read_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); - int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); + int extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content, const jsoncons::json &d); int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::json &d); diff --git a/src/msg/usrmsg_common.hpp b/src/msg/usrmsg_common.hpp index 0e291495..689661a6 100644 --- a/src/msg/usrmsg_common.hpp +++ b/src/msg/usrmsg_common.hpp @@ -80,8 +80,8 @@ namespace msg::usrmsg constexpr const char *MSGTYPE_SERVER_CHALLENGE_RESPONSE = "server_challenge_response"; constexpr const char *MSGTYPE_CONTRACT_READ_REQUEST = "contract_read_request"; constexpr const char *MSGTYPE_CONTRACT_READ_RESPONSE = "contract_read_response"; - constexpr const char *MSGTYPE_HPSH_REQUEST = "hpsh_request"; - constexpr const char *MSGTYPE_HPSH_RESPONSE = "hpsh_response"; + constexpr const char *MSGTYPE_DEBUG_SHELL_REQUEST = "debug_shell_request"; + constexpr const char *MSGTYPE_DEBUG_SHELL_RESPONSE = "debug_shell_response"; constexpr const char *MSGTYPE_CONTRACT_INPUT = "contract_input"; constexpr const char *MSGTYPE_CONTRACT_INPUT_STATUS = "contract_input_status"; constexpr const char *MSGTYPE_CONTRACT_OUTPUT = "contract_output"; diff --git a/src/msg/usrmsg_parser.cpp b/src/msg/usrmsg_parser.cpp index 52bb2952..6cc8dbf4 100644 --- a/src/msg/usrmsg_parser.cpp +++ b/src/msg/usrmsg_parser.cpp @@ -38,12 +38,12 @@ namespace msg::usrmsg busrmsg::create_contract_input_status(msg, status, reason, input_hash, ledger_seq_no, ledger_hash); } - void usrmsg_parser::create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const + void usrmsg_parser::create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const { if (protocol == util::PROTOCOL::JSON) - jusrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason); + jusrmsg::create_debug_shell_response_container(msg, reply_for, status, content, reason); else - busrmsg::create_hpsh_response_container(msg, reply_for, status, content, reason); + busrmsg::create_debug_shell_response_container(msg, reply_for, status, content, reason); } void usrmsg_parser::create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const @@ -129,12 +129,12 @@ namespace msg::usrmsg return busrmsg::extract_read_request(extracted_id, extracted_content, bdoc); } - int usrmsg_parser::extract_hpsh_request(std::string &extracted_id, std::string &extracted_content) const + int usrmsg_parser::extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content) const { if (protocol == util::PROTOCOL::JSON) - return jusrmsg::extract_hpsh_request(extracted_id, extracted_content, jdoc); + return jusrmsg::extract_debug_shell_request(extracted_id, extracted_content, jdoc); else - return busrmsg::extract_hpsh_request(extracted_id, extracted_content, bdoc); + return busrmsg::extract_debug_shell_request(extracted_id, extracted_content, bdoc); } int usrmsg_parser::extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const diff --git a/src/msg/usrmsg_parser.hpp b/src/msg/usrmsg_parser.hpp index ad06eec7..698acaba 100644 --- a/src/msg/usrmsg_parser.hpp +++ b/src/msg/usrmsg_parser.hpp @@ -26,7 +26,7 @@ namespace msg::usrmsg void create_contract_input_status(std::vector &msg, std::string_view status, std::string_view reason, std::string_view input_hash, const uint64_t ledger_seq_no, const util::h32 &ledger_hash) const; - void create_hpsh_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const; + void create_debug_shell_response_container(std::vector &msg, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) const; void create_contract_read_response_container(std::vector &msg, std::string_view reply_for, std::string_view content) const; @@ -51,7 +51,7 @@ namespace msg::usrmsg int extract_read_request(std::string &extracted_id, std::string &extracted_content) const; - int extract_hpsh_request(std::string &extracted_id, std::string &extracted_content) const; + int extract_debug_shell_request(std::string &extracted_id, std::string &extracted_content) const; int extract_signed_input_container(std::string &extracted_input_container, std::string &extracted_sig) const; diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 48393c38..9512eb63 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -17,7 +17,7 @@ #include "user_input.hpp" #include "read_req.hpp" #include "input_nonce_map.hpp" -#include "../hpsh/hpsh.hpp" +#include "../debug_shell/debug_shell.hpp" namespace usr { @@ -273,32 +273,32 @@ namespace usr user.session.send(resp); return 0; } - else if (msg_type == msg::usrmsg::MSGTYPE_HPSH_REQUEST) + else if (msg_type == msg::usrmsg::MSGTYPE_DEBUG_SHELL_REQUEST) { std::string id, content; - if (parser.extract_hpsh_request(id, content) == -1) + if (parser.extract_debug_shell_request(id, content) == -1) { send_input_status(parser, user.session, msg::usrmsg::STATUS_REJECTED, msg::usrmsg::REASON_BAD_MSG_FORMAT, ""); return -1; } - // If hpsh is initialized, send status reject. - if (!hpsh::ctx.is_initialized) + // If debug_shell is initialized, send status reject. + if (!debug_shell::ctx.is_initialized) { - send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_NOT_INITIALIZED); + send_debug_shell_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_NOT_INITIALIZED); return -1; } - const int res = hpsh::execute(id, user.pubkey, content); + const int res = debug_shell::execute(id, user.pubkey, content); // Send user npt allowed status if not allowed. if (res == -1) { - send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_INTERNAL_ERROR); + send_debug_shell_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_INTERNAL_ERROR); return -1; } else if (res == -2) { - send_hpsh_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_USER_NOT_ALLOWED); + send_debug_shell_response(parser, user.session, id, msg::usrmsg::STATUS_REJECTED, "", msg::usrmsg::REASON_USER_NOT_ALLOWED); return -1; } @@ -366,13 +366,13 @@ namespace usr } /** - * Send the specified hpsh request status result via the provided session. + * Send the specified debug_shell request status result via the provided session. */ - void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, + void send_debug_shell_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason) { std::vector msg; - parser.create_hpsh_response_container(msg, reply_for, status, content, reason); + parser.create_debug_shell_response_container(msg, reply_for, status, content, reason); session.send(msg); } @@ -450,9 +450,9 @@ namespace usr std::scoped_lock lock(ctx.users_mutex); ctx.users.erase(pubkey); } - // Remove any hpsh commands sent by the user. - if (hpsh::ctx.is_initialized) - hpsh::remove_user_commands(pubkey); + // Remove any debug_shell commands sent by the user. + if (debug_shell::ctx.is_initialized) + debug_shell::remove_user_commands(pubkey); return 0; } diff --git a/src/usr/usr.hpp b/src/usr/usr.hpp index fa9753df..93e053ee 100644 --- a/src/usr/usr.hpp +++ b/src/usr/usr.hpp @@ -95,7 +95,7 @@ namespace usr void send_input_status_responses(const std::unordered_map> &responses, const uint64_t ledger_seq_no = 0, const util::h32 &ledger_hash = util::h32_empty); - void send_hpsh_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, + void send_debug_shell_response(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, std::string_view reply_for, std::string_view status, std::string_view content, std::string_view reason = ""); void send_input_status(const msg::usrmsg::usrmsg_parser &parser, usr::user_comm_session &session, diff --git a/test/bin/hpsh b/test/bin/debug_shell similarity index 100% rename from test/bin/hpsh rename to test/bin/debug_shell diff --git a/test/local-cluster/Dockerfile b/test/local-cluster/Dockerfile index 00c7199e..c04e0551 100644 --- a/test/local-cluster/Dockerfile +++ b/test/local-cluster/Dockerfile @@ -2,7 +2,7 @@ FROM evernodedev/hotpocket:latest-ubt.20.04-njs.20 # Copy (overwrite) the local build outputs into the docker image. -COPY hpcore hpfs hpws hpsh /usr/local/bin/hotpocket/ +COPY hpcore hpfs hpws debug_shell /usr/local/bin/hotpocket/ ENTRYPOINT ["/usr/local/bin/hotpocket/hpcore"] From 78d534fa2af50c7614bc78c01ef1158eacddca50 Mon Sep 17 00:00:00 2001 From: Dulana Peiris Date: Tue, 19 Dec 2023 10:56:17 +0530 Subject: [PATCH 23/23] Naming changes and added HPSH to docker image --- CMakeLists.txt | 4 ++-- src/conf.cpp | 6 +++--- src/conf.hpp | 2 +- src/debug_shell/debug_shell.cpp | 2 +- test/bin/{debug_shell => hpsh} | Bin test/docker/Dockerfile.ubt.20.04 | 2 +- test/docker/build.sh | 2 +- test/local-cluster/Dockerfile | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) rename test/bin/{debug_shell => hpsh} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a19a800..5284dbbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ target_link_libraries(hpcore add_custom_command(TARGET hpcore POST_BUILD # COMMAND strip ./build/hpcore - COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/debug_shell ./build/ + COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./build/ ) target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) @@ -88,7 +88,7 @@ target_precompile_headers(hpcore PUBLIC src/pchheader.hpp) add_custom_target(docker COMMAND mkdir -p ./test/local-cluster/bin COMMAND cp ./build/hpcore ./test/local-cluster/bin/ - COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/bin/debug_shell ./test/local-cluster/bin/ + COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/bin/hpsh ./test/local-cluster/bin/ COMMAND docker build -t hpcore:latest -t hpcore:0.6.4 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/ ) set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE) diff --git a/src/conf.cpp b/src/conf.cpp index 89e33a45..184a9fc9 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -244,7 +244,7 @@ namespace conf ctx.hpws_exe_path = ctx.exe_dir + "/" + "hpws"; ctx.hpfs_exe_path = ctx.exe_dir + "/" + "hpfs"; - ctx.debug_shell_exe_path = ctx.exe_dir + "/" + "debug_shell"; + ctx.hpsh_exe_path = ctx.exe_dir + "/" + "hpsh"; ctx.contract_dir = basedir; ctx.config_dir = basedir + "/cfg"; @@ -771,7 +771,7 @@ namespace conf ctx.tls_cert_file, ctx.hpfs_exe_path, ctx.hpws_exe_path, - ctx.debug_shell_exe_path}; + ctx.hpsh_exe_path}; for (const std::string &path : paths) { @@ -783,7 +783,7 @@ namespace conf << "openssl req -newkey rsa:2048 -new -nodes -x509 -days 365 -keyout tlskey.pem -out tlscert.pem\n" << "and add it to " + ctx.config_dir << std::endl; } - else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path || path == ctx.debug_shell_exe_path) + else if (path == ctx.hpfs_exe_path || path == ctx.hpws_exe_path || path == ctx.hpsh_exe_path) { std::cerr << path << " binary does not exist.\n"; } diff --git a/src/conf.hpp b/src/conf.hpp index a025a9db..b5d1e881 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -270,7 +270,7 @@ namespace conf std::string exe_dir; // HotPocket executable dir. std::string hpws_exe_path; // hpws executable file path. std::string hpfs_exe_path; // hpfs executable file path. - std::string debug_shell_exe_path; // debug_shell executable path file + std::string hpsh_exe_path; // debug_shell executable path file std::string contract_dir; // Contract base directory full path. std::string contract_hpfs_dir; // Contract hpfs metadata dir (The location of hpfs log file). diff --git a/src/debug_shell/debug_shell.cpp b/src/debug_shell/debug_shell.cpp index bf25dfa4..582d6a4b 100644 --- a/src/debug_shell/debug_shell.cpp +++ b/src/debug_shell/debug_shell.cpp @@ -48,7 +48,7 @@ namespace debug_shell fd_str.resize(10); snprintf(fd_str.data(), 10, "%d", ctx.control_fds[0]); - char *argv[] = {(char *)conf::ctx.debug_shell_exe_path.data(), fd_str.data(), NULL}; + char *argv[] = {(char *)conf::ctx.hpsh_exe_path.data(), fd_str.data(), NULL}; // Just before we execv the debug_shell binary, we set user execution user/group if specified in hp config. // (Must set gid before setting uid) diff --git a/test/bin/debug_shell b/test/bin/hpsh similarity index 100% rename from test/bin/debug_shell rename to test/bin/hpsh diff --git a/test/docker/Dockerfile.ubt.20.04 b/test/docker/Dockerfile.ubt.20.04 index bf5f8d2e..14bba941 100644 --- a/test/docker/Dockerfile.ubt.20.04 +++ b/test/docker/Dockerfile.ubt.20.04 @@ -13,6 +13,6 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* \ && mkdir /usr/local/bin/hotpocket -COPY hpcore hpfs hpws /usr/local/bin/hotpocket/ +COPY hpcore hpfs hpws hpsh /usr/local/bin/hotpocket/ ENTRYPOINT ["/usr/local/bin/hotpocket/hpcore"] diff --git a/test/docker/build.sh b/test/docker/build.sh index b158d159..3bb7a937 100755 --- a/test/docker/build.sh +++ b/test/docker/build.sh @@ -8,7 +8,7 @@ njsfile="Dockerfile.ubt.20.04-njs" # Prepare build context tmp=$(mktemp -d) -cp $hpcoredir/build/hpcore $hpcoredir/test/bin/{hpfs,hpws,libblake3.so} $tmp/ +cp $hpcoredir/build/hpcore $hpcoredir/test/bin/{hpfs,hpws,hpsh,libblake3.so} $tmp/ strip $tmp/hpcore # Remove the revision component from hp version to make up the image version. diff --git a/test/local-cluster/Dockerfile b/test/local-cluster/Dockerfile index c04e0551..00c7199e 100644 --- a/test/local-cluster/Dockerfile +++ b/test/local-cluster/Dockerfile @@ -2,7 +2,7 @@ FROM evernodedev/hotpocket:latest-ubt.20.04-njs.20 # Copy (overwrite) the local build outputs into the docker image. -COPY hpcore hpfs hpws debug_shell /usr/local/bin/hotpocket/ +COPY hpcore hpfs hpws hpsh /usr/local/bin/hotpocket/ ENTRYPOINT ["/usr/local/bin/hotpocket/hpcore"]