From 22a140c54335fc966f12b94b426b2bd9f942f785 Mon Sep 17 00:00:00 2001 From: Ravin Perera <33562092+ravinsp@users.noreply.github.com> Date: Mon, 7 Oct 2019 10:59:34 +0530 Subject: [PATCH] Added npl fields to the contract input. (#7) * Added npl fields to the contract input. * Made parameter passing optimisations. --- src/conf.cpp | 12 +++++----- src/main.cpp | 1 - src/proc.cpp | 59 ++++++++++++++++++++++++++++++++++++++----------- src/proc.h | 10 +++++++-- src/shared.h | 18 ++++++++++++++- src/usr/usr.cpp | 7 +++--- 6 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/conf.cpp b/src/conf.cpp index 392e76f9..96b6b0cc 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -31,8 +31,9 @@ bool is_schema_valid(Document &d); int init() { - if (!validate_contract_dir_paths() || load_config() != 0 || validate_config() != 0) + if (!validate_contract_dir_paths() || load_config() != 0 || !validate_config()) return -1; + return 0; } @@ -105,7 +106,8 @@ int load_config() cfg.pubmaxsize = d["pubmaxsize"].GetInt(); cfg.pubmaxcpm = d["pubmaxcpm"].GetInt(); - b64pair_to_bin(); + if (b64pair_to_bin() != 0) + return -1; return 0; } @@ -123,7 +125,7 @@ void save_config() d.AddMember("listenip", StringRef(cfg.listenip.data()), allocator); Value peers(kArrayType); - for (string peer : cfg.peers) + for (string &peer : cfg.peers) { Value v; v.SetString(StringRef(peer.data()), allocator); @@ -132,7 +134,7 @@ void save_config() d.AddMember("peers", peers, allocator); Value unl(kArrayType); - for (string node : cfg.unl) + for (string &node : cfg.unl) { Value v; v.SetString(StringRef(node.data()), allocator); @@ -263,7 +265,7 @@ bool validate_contract_dir_paths() { string dirs[4] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir}; - for (string dir : dirs) + for (string &dir : dirs) { if (!boost::filesystem::exists(dir)) { diff --git a/src/main.cpp b/src/main.cpp index 5a9a4f06..46586f59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,6 @@ #include #include -#include #include "conf.h" #include "crypto.h" #include "usr/usr.h" diff --git a/src/proc.cpp b/src/proc.cpp index 3d6b0d7a..72daca67 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -21,9 +21,8 @@ namespace proc */ int contract_pid; -void write_to_stdin(ContractExecArgs &args); +int write_to_stdin(ContractExecArgs &args); bool is_contract_running(); -int exec_contract(ContractExecArgs &args); int exec_contract(ContractExecArgs &args) { @@ -36,19 +35,23 @@ int exec_contract(ContractExecArgs &args) int pid = fork(); if (pid > 0) { + //HotPocket process. + contract_pid = pid; } else if (pid == 0) { + //Contract process. + //Set up the process environment and overlay the contract binary program with execv(). + //Set the contract process working directory. chdir(conf::ctx.contractDir.data()); - //Write the contract args to the stdin (0) of the contract process. + //Write the contract input message from HotPocket to the stdin (0) of the contract process. write_to_stdin(args); - char *args[] = {conf::cfg.binary.data(), conf::cfg.binargs.data(), NULL}; - - execv(args[0], args); + char *execv_args[] = {conf::cfg.binary.data(), conf::cfg.binargs.data(), NULL}; + execv(execv_args[0], execv_args); } else { @@ -60,21 +63,29 @@ int exec_contract(ContractExecArgs &args) } /** - * Passes the input in the format: + * Writes the contract input message into the stdin of the contract process. + * Input format: * { - * "version":"0.1", - * "usrfd":{ "pk1":[fd0, fd1], "pk2":[fd0, fd1] } + * "version":"", + * "pubkey": "", + * "ts": , + * "usrfd":{ "pkb64":[fd0, fd1], ... }, + * "nplfd":{ "pkb64":[fd0, fd1], ... }, + * "unl":[ "pkb64", ... ] * } */ -void write_to_stdin(ContractExecArgs &args) +int write_to_stdin(ContractExecArgs &args) { Document d; d.SetObject(); Document::AllocatorType &allocator = d.GetAllocator(); + d.AddMember("version", StringRef(_HP_VERSION_), allocator); + d.AddMember("pubkey", StringRef(conf::cfg.pubkeyb64.data()), allocator); + d.AddMember("ts", args.timestamp, allocator); Value users(kObjectType); - for (auto &[pk, user] : (*args.users)) + for (auto &[pk, user] : args.users) { Value fdlist(kArrayType); fdlist.PushBack(user.inpipe[0], allocator); @@ -83,18 +94,40 @@ void write_to_stdin(ContractExecArgs &args) } d.AddMember("usrfd", users, allocator); + Value peers(kObjectType); + for (auto &[pk, peer] : args.peers) + { + Value fdlist(kArrayType); + fdlist.PushBack(peer.inpipe[0], allocator); + fdlist.PushBack(peer.outpipe[1], allocator); + peers.AddMember(StringRef(peer.pubkeyb64.data()), fdlist, allocator); + } + d.AddMember("nplfd", peers, allocator); + + Value unl(kArrayType); + for (string &node : conf::cfg.unl) + unl.PushBack(StringRef(node.data()), allocator); + d.AddMember("unl", unl, allocator); + StringBuffer buffer; Writer writer(buffer); d.Accept(writer); const char *json = buffer.GetString(); int stdinpipe[2]; - pipe(stdinpipe); + if (pipe(stdinpipe) != 0) + { + cerr << "Failed to create pipe to the contract process.\n"; + return -1; + } + dup2(stdinpipe[0], STDIN_FILENO); close(stdinpipe[0]); - write(stdinpipe[1], json, strlen(json)); + write(stdinpipe[1], json, buffer.GetSize()); close(stdinpipe[1]); + + return 0; } bool is_contract_running() diff --git a/src/proc.h b/src/proc.h index 2c3e45b2..5d98aa57 100644 --- a/src/proc.h +++ b/src/proc.h @@ -13,9 +13,15 @@ namespace proc struct ContractExecArgs { - map *users; + map &users; + map &peers; + uint64_t timestamp; - //ContractExecArgs(map &_users) + ContractExecArgs(map &_users, map &_peers, uint64_t _timestamp) + : users(_users), peers(_peers) + { + timestamp = _timestamp; + } }; int exec_contract(ContractExecArgs &args); diff --git a/src/shared.h b/src/shared.h index 35156053..39725a3c 100644 --- a/src/shared.h +++ b/src/shared.h @@ -14,7 +14,7 @@ struct ContractUser string pubkeyb64; int inpipe[2]; int outpipe[2]; - vector outbuffer; + string outbuffer; ContractUser(string _pubkeyb64, int _inpipe[2], int _outpipe[2]) { @@ -26,6 +26,22 @@ struct ContractUser } }; +struct PeerNode +{ + string pubkeyb64; + int inpipe[2]; + int outpipe[2]; + + PeerNode(string _pubkeyb64, int _inpipe[2], int _outpipe[2]) + { + pubkeyb64 = _pubkeyb64; + inpipe[0] = _inpipe[0]; + inpipe[1] = _inpipe[1]; + outpipe[0] = _outpipe[0]; + outpipe[1] = _outpipe[1]; + } +}; + int base64_encode(unsigned char *bin, size_t bin_len, string &encoded_string); int base64_decode(string &base64_str, unsigned char *decoded, size_t decoded_len); void replace_string_contents(string &str, const char* bytes, size_t bytes_len); diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index 1e9f02ef..78dcaadc 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -131,12 +131,11 @@ int read_contract_user_outputs() if (bytes_available > 0) { - unsigned char data[bytes_available]; + char data[bytes_available]; read(fdout, data, bytes_available); - //Replace the existing user buffer with new buffer - vector buffer(data, data + bytes_available); - user.outbuffer.swap(buffer); + //Populate the user output buffer with new data + shared::replace_string_contents(user.outbuffer, data, bytes_available); cout << "Read " + to_string(bytes_available) << " bytes into user output buffer. user:" + user.pubkeyb64 << endl; }