Code consistency improvements (#21)

Fully-qualified namespace accessors
Updated function out param order
reinterpret_cast
This commit is contained in:
Ravin Perera
2019-10-11 20:08:53 +05:30
committed by GitHub
parent f64cdc6ad0
commit ebf13209e1
14 changed files with 235 additions and 241 deletions

View File

@@ -6,17 +6,17 @@ add_definitions("-std=c++17")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build)
add_executable(hpcore
src/main.cpp
src/conf.cpp
src/crypto.cpp
src/proc.cpp
src/usr/usr.cpp
src/usr/user_session_handler.cpp
src/util.cpp
src/p2p/message.pb.cc
src/sock/socket_client.cpp
src/sock/socket_server.cpp
src/sock/socket_session.cpp
src/util.cpp
src/crypto.cpp
src/conf.cpp
src/proc.cpp
src/usr/user_session_handler.cpp
src/usr/usr.cpp
src/main.cpp
)
target_link_libraries(hpcore

View File

@@ -12,9 +12,6 @@
#include "crypto.hpp"
#include "util.hpp"
using namespace std;
using namespace rapidjson;
namespace conf
{
@@ -58,7 +55,7 @@ int rekey()
if (save_config() != 0)
return -1;
cout << "New signing keys generated at " << ctx.configFile << endl;
std::cout << "New signing keys generated at " << ctx.configFile << std::endl;
return 0;
}
@@ -72,7 +69,7 @@ int create_contract()
{
if (boost::filesystem::exists(ctx.contractDir))
{
cerr << "Contract dir already exists. Cannot create contract at the same location.\n";
std::cerr << "Contract dir already exists. Cannot create contract at the same location.\n";
return -1;
}
@@ -99,7 +96,7 @@ int create_contract()
if (save_config() != 0)
return -1;
cout << "Contract directory created at " << ctx.contractDir << endl;
std::cout << "Contract directory created at " << ctx.contractDir << std::endl;
return 0;
}
@@ -108,7 +105,7 @@ int create_contract()
* Updates the contract context with directory paths based on provided base directory.
* This is called after parsing HP command line arg in order to populate the ctx.
*/
void set_contract_dir_paths(string basedir)
void set_contract_dir_paths(std::string basedir)
{
if (basedir[basedir.size() - 1] == '/')
basedir = basedir.substr(0, basedir.size() - 1);
@@ -129,42 +126,42 @@ int load_config()
{
// Read the file into json document object.
ifstream ifs(ctx.configFile);
IStreamWrapper isw(ifs);
std::ifstream ifs(ctx.configFile);
rapidjson::IStreamWrapper isw(ifs);
Document d;
rapidjson::Document d;
if (d.ParseStream(isw).HasParseError())
{
cerr << "Invalid config file format. Parser error at position " << d.GetErrorOffset() << endl;
std::cerr << "Invalid config file format. Parser error at position " << d.GetErrorOffset() << std::endl;
return -1;
}
else if (is_schema_valid(d) != 0)
{
cerr << "Invalid config file format.\n";
std::cerr << "Invalid config file format.\n";
return -1;
}
ifs.close();
// Check whether the contract version is specified.
string cfgversion = d["version"].GetString();
std::string cfgversion = d["version"].GetString();
if (cfgversion.empty())
{
cerr << "Contract config version missing.\n";
std::cerr << "Contract config version missing.\n";
return -1;
}
// Check whether this contract complies with the min version requirement.
int verresult = util::version_compare(cfgversion, string(util::MIN_CONTRACT_VERSION));
int verresult = util::version_compare(cfgversion, std::string(util::MIN_CONTRACT_VERSION));
if (verresult == -1)
{
cerr << "Contract version too old. Minimum "
<< util::MIN_CONTRACT_VERSION << " required. "
<< cfgversion << " found.\n";
std::cerr << "Contract version too old. Minimum "
<< util::MIN_CONTRACT_VERSION << " required. "
<< cfgversion << " found.\n";
return -1;
}
else if (verresult == -2)
{
cerr << "Malformed version string.\n";
std::cerr << "Malformed version string.\n";
return -1;
}
@@ -207,31 +204,31 @@ int save_config()
{
// Popualte json document with 'cfg' values.
Document d;
rapidjson::Document d;
d.SetObject();
Document::AllocatorType &allocator = d.GetAllocator();
d.AddMember("version", StringRef(util::HP_VERSION), allocator);
d.AddMember("pubkeyb64", StringRef(cfg.pubkeyb64.data()), allocator);
d.AddMember("seckeyb64", StringRef(cfg.seckeyb64.data()), allocator);
d.AddMember("keytype", StringRef(cfg.keytype.data()), allocator);
d.AddMember("binary", StringRef(cfg.binary.data()), allocator);
d.AddMember("binargs", StringRef(cfg.binargs.data()), allocator);
d.AddMember("listenip", StringRef(cfg.listenip.data()), allocator);
rapidjson::Document::AllocatorType &allocator = d.GetAllocator();
d.AddMember("version", rapidjson::StringRef(util::HP_VERSION), allocator);
d.AddMember("pubkeyb64", rapidjson::StringRef(cfg.pubkeyb64.data()), allocator);
d.AddMember("seckeyb64", rapidjson::StringRef(cfg.seckeyb64.data()), allocator);
d.AddMember("keytype", rapidjson::StringRef(cfg.keytype.data()), allocator);
d.AddMember("binary", rapidjson::StringRef(cfg.binary.data()), allocator);
d.AddMember("binargs", rapidjson::StringRef(cfg.binargs.data()), allocator);
d.AddMember("listenip", rapidjson::StringRef(cfg.listenip.data()), allocator);
Value peers(kArrayType);
for (string &peer : cfg.peers)
rapidjson::Value peers(rapidjson::kArrayType);
for (std::string &peer : cfg.peers)
{
Value v;
v.SetString(StringRef(peer.data()), allocator);
rapidjson::Value v;
v.SetString(rapidjson::StringRef(peer.data()), allocator);
peers.PushBack(v, allocator);
}
d.AddMember("peers", peers, allocator);
Value unl(kArrayType);
for (string &node : cfg.unl)
rapidjson::Value unl(rapidjson::kArrayType);
for (std::string &node : cfg.unl)
{
Value v;
v.SetString(StringRef(node.data()), allocator);
rapidjson::Value v;
v.SetString(rapidjson::StringRef(node.data()), allocator);
unl.PushBack(v, allocator);
}
d.AddMember("unl", unl, allocator);
@@ -242,16 +239,15 @@ int save_config()
d.AddMember("pubmaxsize", cfg.pubmaxsize, allocator);
d.AddMember("pubmaxcpm", cfg.pubmaxcpm, allocator);
// Write the json doc to file.
ofstream ofs(ctx.configFile);
OStreamWrapper osw(ofs);
std::ofstream ofs(ctx.configFile);
rapidjson::OStreamWrapper osw(ofs);
PrettyWriter<OStreamWrapper> writer(osw);
rapidjson::PrettyWriter<rapidjson::OStreamWrapper> writer(osw);
if (!d.Accept(writer))
{
cerr << "Writing to config file failed. " << ctx.configFile << endl;
std::cerr << "Writing to config file failed. " << ctx.configFile << std::endl;
return -1;
}
ofs.close();
@@ -266,15 +262,21 @@ int save_config()
*/
int binpair_to_b64()
{
if (util::base64_encode((unsigned char *)cfg.pubkey.data(), crypto_sign_PUBLICKEYBYTES, cfg.pubkeyb64) != 0)
if (util::base64_encode(
cfg.pubkeyb64,
reinterpret_cast<const unsigned char *>(cfg.pubkey.data()),
crypto_sign_PUBLICKEYBYTES) != 0)
{
cerr << "Error encoding public key bytes.\n";
std::cerr << "Error encoding public key bytes.\n";
return -1;
}
if (util::base64_encode((unsigned char *)cfg.seckey.data(), crypto_sign_SECRETKEYBYTES, cfg.seckeyb64) != 0)
if (util::base64_encode(
cfg.seckeyb64,
reinterpret_cast<const unsigned char *>(cfg.seckey.data()),
crypto_sign_SECRETKEYBYTES) != 0)
{
cerr << "Error encoding secret key bytes.\n";
std::cerr << "Error encoding secret key bytes.\n";
return -1;
}
@@ -289,23 +291,25 @@ int binpair_to_b64()
int b64pair_to_bin()
{
unsigned char decoded_pubkey[crypto_sign_PUBLICKEYBYTES];
unsigned char decoded_seckey[crypto_sign_SECRETKEYBYTES];
if (util::base64_decode(cfg.pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES) != 0)
if (util::base64_decode(decoded_pubkey, crypto_sign_PUBLICKEYBYTES, cfg.pubkeyb64) != 0)
{
cerr << "Error decoding base64 public key.\n";
std::cerr << "Error decoding base64 public key.\n";
return -1;
}
if (util::base64_decode(cfg.seckeyb64, decoded_seckey, crypto_sign_SECRETKEYBYTES) != 0)
unsigned char decoded_seckey[crypto_sign_SECRETKEYBYTES];
if (util::base64_decode(decoded_seckey, crypto_sign_SECRETKEYBYTES, cfg.seckeyb64) != 0)
{
cerr << "Error decoding base64 secret key.\n";
std::cerr << "Error decoding base64 secret key.\n";
return -1;
}
// Assign the cfg pubkey/seckey fields with the decoded strings.
cfg.pubkey = string((char *)decoded_pubkey, crypto_sign_PUBLICKEYBYTES);
cfg.seckey = string((char *)decoded_seckey, crypto_sign_SECRETKEYBYTES);
cfg.pubkey = std::string(reinterpret_cast<char *>(decoded_pubkey), crypto_sign_PUBLICKEYBYTES);
cfg.seckey = std::string(reinterpret_cast<char *>(decoded_seckey), crypto_sign_SECRETKEYBYTES);
return 0;
}
@@ -320,7 +324,7 @@ int validate_config()
// We also check for key pair validity as well in the below code.
if (cfg.pubkeyb64.empty() || cfg.seckeyb64.empty())
{
cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n";
std::cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n";
return -1;
}
@@ -328,23 +332,23 @@ int validate_config()
if (cfg.binary.empty() || cfg.listenip.empty() ||
cfg.peerport == 0 || cfg.roundtime == 0 || cfg.pubport == 0 || cfg.pubmaxsize == 0 || cfg.pubmaxcpm == 0)
{
cerr << "Required configuration fields missing at " << ctx.configFile << endl;
std::cerr << "Required configuration fields missing at " << ctx.configFile << std::endl;
return -1;
}
// Check whether the contract binary actually exists.
if (!boost::filesystem::exists(cfg.binary))
{
cerr << "Contract binary does not exist: " << cfg.binary << endl;
std::cerr << "Contract binary does not exist: " << cfg.binary << std::endl;
return -1;
}
//Sign and verify a sample message to ensure we have a matching signing key pair.
string msg = "hotpocket";
string sigb64 = crypto::sign_b64(msg, cfg.seckeyb64);
std::string msg = "hotpocket";
std::string sigb64 = crypto::sign_b64(msg, cfg.seckeyb64);
if (crypto::verify_b64(msg, sigb64, cfg.pubkeyb64) != 0)
{
cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n";
std::cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n";
return -1;
}
@@ -358,13 +362,13 @@ int validate_config()
*/
int validate_contract_dir_paths()
{
string dirs[4] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir};
std::string dirs[4] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir};
for (string &dir : dirs)
for (std::string &dir : dirs)
{
if (!boost::filesystem::exists(dir))
{
cerr << dir << " does not exist.\n";
std::cerr << dir << " does not exist.\n";
return -1;
}
}
@@ -377,7 +381,7 @@ int validate_contract_dir_paths()
*
* @return 0 for successful validation. -1 for failure.
*/
int is_schema_valid(Document &d)
int is_schema_valid(rapidjson::Document &d)
{
const char *cfg_schema =
"{"
@@ -408,14 +412,14 @@ int is_schema_valid(Document &d)
"}"
"}";
Document sd;
rapidjson::Document sd;
sd.Parse(cfg_schema);
SchemaDocument schema(sd);
rapidjson::SchemaDocument schema(sd);
SchemaValidator validator(schema);
rapidjson::SchemaValidator validator(schema);
if (!d.Accept(validator))
return -1;
return 0;
}

View File

@@ -4,9 +4,6 @@
#include <rapidjson/document.h>
#include <vector>
using namespace std;
using namespace rapidjson;
/**
* Manages the central contract config and context structs.
* Contains functions to contract config operations such as create/rekey/load.
@@ -17,13 +14,13 @@ namespace conf
// Holds contextual information about the currently loaded contract.
struct contract_ctx
{
string command; // The CLI command issued to launch HotPocket
std::string command; // The CLI command issued to launch HotPocket
string contractDir; // Contract base directory
string histDir; // Contract history dir
string stateDir; // Contract state dir
string configDir; // Contract config dir
string configFile; // Full path to the contract config file
std::string contractDir; // Contract base directory
std::string histDir; // Contract history dir
std::string stateDir; // Contract state dir
std::string configDir; // Contract config dir
std::string configFile; // Full path to the contract config file
};
// Holds all the contract config values.
@@ -31,19 +28,19 @@ struct contract_config
{
// Config elements which are initialized in memory (these are not directly loaded from the config file)
string pubkey; // Contract public key bytes
string seckey; // Contract secret key bytes
std::string pubkey; // Contract public key bytes
std::string seckey; // Contract secret key bytes
// Config elements which are loaded from the config file.
string pubkeyb64; // Contract base64 public key
string seckeyb64; // Contract base64 secret key
string keytype; // Key generation algorithm used by libsodium
string binary; // Full path to the contract binary
string binargs; // CLI arguments to pass to the contract binary
string listenip; // The IPs to listen on for incoming connections
vector<string> peers; // List of peers in the format "<ip address>:<port>"
vector<string> unl; // Unique node list (list of base64 public keys)
std::string pubkeyb64; // Contract base64 public key
std::string seckeyb64; // Contract base64 secret key
std::string keytype; // Key generation algorithm used by libsodium
std::string binary; // Full path to the contract binary
std::string binargs; // CLI arguments to pass to the contract binary
std::string listenip; // The IPs to listen on for incoming connections
std::vector<std::string> peers; // List of peers in the format "<ip address>:<port>"
std::vector<std::string> unl; // Unique node list (list of base64 public keys)
unsigned short peerport; // Listening port for peer connections
int roundtime; // Consensus round time in ms
unsigned short pubport; // Listening port for public user connections
@@ -65,7 +62,7 @@ int rekey();
int create_contract();
void set_contract_dir_paths(string basedir);
void set_contract_dir_paths(std::string basedir);
//------Internal-use functions for this namespace.
@@ -77,7 +74,7 @@ int validate_config();
int validate_contract_dir_paths();
int is_schema_valid(Document &d);
int is_schema_valid(rapidjson::Document &d);
int binpair_to_b64();

View File

@@ -4,8 +4,6 @@
#include "crypto.hpp"
#include "util.hpp"
using namespace std;
namespace crypto
{
@@ -17,7 +15,7 @@ int init()
{
if (sodium_init() < 0)
{
cerr << "sodium_init failed.\n";
std::cerr << "sodium_init failed.\n";
return -1;
}
@@ -27,7 +25,7 @@ int init()
/**
* Generates a signing key pair using libsodium and assigns them to the provided strings.
*/
void generate_signing_keys(string &pubkey, string &seckey, string &keytype)
void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string &keytype)
{
//Generate key pair using libsodium default algorithm. (Currently using ed25519)
@@ -35,8 +33,8 @@ void generate_signing_keys(string &pubkey, string &seckey, string &keytype)
unsigned char seckeychars[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(pubkeychars, seckeychars);
pubkey = string((char *)pubkeychars, crypto_sign_PUBLICKEYBYTES);
seckey = string((char *)seckeychars, crypto_sign_SECRETKEYBYTES);
pubkey = std::string(reinterpret_cast<char *>(pubkeychars), crypto_sign_PUBLICKEYBYTES);
seckey = std::string(reinterpret_cast<char *>(seckeychars), crypto_sign_SECRETKEYBYTES);
keytype = crypto_sign_primitive();
}
@@ -47,13 +45,19 @@ void generate_signing_keys(string &pubkey, string &seckey, string &keytype)
* @param seckey Secret key bytes.
* @return Signature bytes.
*/
string sign(const string &msg, const string &seckey)
std::string sign(const std::string &msg, const std::string &seckey)
{
//Generate the signature using libsodium.
unsigned char sigchars[crypto_sign_BYTES];
crypto_sign_detached(sigchars, NULL, (unsigned char *)msg.data(), msg.length(), (unsigned char *)seckey.data());
string sig((char *)sigchars, crypto_sign_BYTES);
crypto_sign_detached(
sigchars,
NULL,
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
reinterpret_cast<const unsigned char *>(seckey.data()));
std::string sig(reinterpret_cast<char *>(sigchars), crypto_sign_BYTES);
return sig;
}
@@ -64,18 +68,23 @@ string sign(const string &msg, const string &seckey)
* @param seckeyb64 Base64 secret key string.
* @return Base64 signature string.
*/
string sign_b64(const string &msg, const string &seckeyb64)
std::string sign_b64(const std::string &msg, const std::string &seckeyb64)
{
//Decode b64 string and generate the signature using libsodium.
unsigned char seckey[crypto_sign_SECRETKEYBYTES];
util::base64_decode(seckeyb64, seckey, crypto_sign_SECRETKEYBYTES);
util::base64_decode(seckey, crypto_sign_SECRETKEYBYTES, seckeyb64);
unsigned char sig[crypto_sign_BYTES];
crypto_sign_detached(sig, NULL, (unsigned char *)msg.data(), msg.length(), seckey);
crypto_sign_detached(
sig,
NULL,
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
seckey);
string sigb64;
util::base64_encode(sig, crypto_sign_BYTES, sigb64);
std::string sigb64;
util::base64_encode(sigb64, sig, crypto_sign_BYTES);
return sigb64;
}
@@ -87,10 +96,13 @@ string sign_b64(const string &msg, const string &seckeyb64)
* @param pubkey Public key bytes.
* @return 0 for successful verification. -1 for failure.
*/
int verify(const string &msg, const string &sig, const string &pubkey)
int verify(const std::string &msg, const std::string &sig, const std::string &pubkey)
{
return crypto_sign_verify_detached(
(unsigned char *)sig.data(), (unsigned char *)msg.data(), msg.length(), (unsigned char *)pubkey.data());
reinterpret_cast<const unsigned char *>(sig.data()),
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
reinterpret_cast<const unsigned char *>(pubkey.data()));
}
/**
@@ -101,17 +113,21 @@ int verify(const string &msg, const string &sig, const string &pubkey)
* @param pubkeyb64 Base64 secret key.
* @return 0 for successful verification. -1 for failure.
*/
int verify_b64(const string &msg, const string &sigb64, const string &pubkeyb64)
int verify_b64(const std::string &msg, const std::string &sigb64, const std::string &pubkeyb64)
{
//Decode b64 string and verify the signature using libsodium.
unsigned char decoded_pubkey[crypto_sign_PUBLICKEYBYTES];
util::base64_decode(pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES);
util::base64_decode(decoded_pubkey, crypto_sign_PUBLICKEYBYTES, pubkeyb64);
unsigned char decoded_sig[crypto_sign_BYTES];
util::base64_decode(sigb64, decoded_sig, crypto_sign_BYTES);
util::base64_decode(decoded_sig, crypto_sign_BYTES, sigb64);
return crypto_sign_verify_detached(decoded_sig, (unsigned char *)msg.data(), msg.length(), decoded_pubkey);
return crypto_sign_verify_detached(
decoded_sig,
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
decoded_pubkey);
}
} // namespace crypto

View File

@@ -1,8 +1,6 @@
#ifndef _HP_CRYPTO_H_
#define _HP_CRYPTO_H_
using namespace std;
/**
* Offers convenience functions for cryptographic operations wrapping libsodium.
* These functions are used for contract config and user/peer message authentication.
@@ -12,15 +10,15 @@ namespace crypto
int init();
void generate_signing_keys(string &pubkey, string &seckey, string &keytype);
void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string &keytype);
string sign(const string &msg, const string &seckey);
std::string sign(const std::string &msg, const std::string &seckey);
string sign_b64(const string &msg, const string &seckeyb64);
std::string sign_b64(const std::string &msg, const std::string &seckeyb64);
int verify(const string &msg, const string &sig, const string &pubkey);
int verify(const std::string &msg, const std::string &sig, const std::string &pubkey);
int verify_b64(const string &msg, const string &sigb64, const string &pubkeyb64);
int verify_b64(const std::string &msg, const std::string &sigb64, const std::string &pubkeyb64);
} // namespace crypto

View File

@@ -10,8 +10,6 @@
#include "crypto.hpp"
#include "usr/usr.hpp"
using namespace std;
/**
* Parses CLI args and extracts hot pocket command and parameters given.
* HP command line accepts command and the contract directory(optional)
@@ -29,7 +27,7 @@ int parse_cmd(int argc, char **argv)
{
if (argc != 3)
{
cerr << "Contract directory not specified.\n";
std::cerr << "Contract directory not specified.\n";
}
else
{
@@ -49,11 +47,11 @@ int parse_cmd(int argc, char **argv)
// If all extractions fail display help message.
cerr << "Arguments mismatch.\n";
cout << "Usage:\n";
cout << "hpcore version\n";
cout << "hpcore <command> <contract dir> (command = run | new | rekey)\n";
cout << "Example: hpcore run ~/mycontract\n";
std::cerr << "Arguments mismatch.\n";
std::cout << "Usage:\n";
std::cout << "hpcore version\n";
std::cout << "hpcore <command> <contract dir> (command = run | new | rekey)\n";
std::cout << "Example: hpcore run ~/mycontract\n";
return -1;
}
@@ -68,7 +66,7 @@ int main(int argc, char **argv)
if (conf::ctx.command == "version")
{
// Print the version
cout << util::HP_VERSION << endl;
std::cout << util::HP_VERSION << std::endl;
}
else
{
@@ -104,11 +102,11 @@ int main(int argc, char **argv)
// TODO
// Temp code to avoid exiting.
string s;
cin >> s;
std::string s;
std::cin >> s;
}
}
}
cout << "exited normally\n";
std::cout << "exited normally\n";
return 0;
}

View File

@@ -1,6 +1,6 @@
#include <string>
#include "message.pb.h"
#include "p2p.h"
#include "p2p.hpp"
using namespace std;

View File

@@ -10,9 +10,6 @@
#include "proc.hpp"
#include "conf.hpp"
using namespace std;
using namespace util;
namespace proc
{
@@ -30,7 +27,7 @@ int exec_contract(const ContractExecArgs &args)
{
if (is_contract_running())
{
cerr << "Contract process still running.\n";
std::cerr << "Contract process still running.\n";
return -1;
}
@@ -57,7 +54,7 @@ int exec_contract(const ContractExecArgs &args)
}
else
{
cerr << "fork() failed.\n";
std::cerr << "fork() failed.\n";
return -1;
}
@@ -80,41 +77,41 @@ int write_to_stdin(const ContractExecArgs &args)
{
//Populate the json document with contract args.
Document d;
rapidjson::Document d;
d.SetObject();
Document::AllocatorType &allocator = d.GetAllocator();
rapidjson::Document::AllocatorType &allocator = d.GetAllocator();
d.AddMember("version", StringRef(util::HP_VERSION), allocator);
d.AddMember("pubkey", StringRef(conf::cfg.pubkeyb64.data()), allocator);
d.AddMember("version", rapidjson::StringRef(util::HP_VERSION), allocator);
d.AddMember("pubkey", rapidjson::StringRef(conf::cfg.pubkeyb64.data()), allocator);
d.AddMember("ts", args.timestamp, allocator);
Value users(kObjectType);
rapidjson::Value users(rapidjson::kObjectType);
for (auto &[sid, user] : args.users)
{
Value fdlist(kArrayType);
rapidjson::Value fdlist(rapidjson::kArrayType);
fdlist.PushBack(user.inpipe[0], allocator);
fdlist.PushBack(user.outpipe[1], allocator);
users.AddMember(StringRef(user.pubkeyb64.data()), fdlist, allocator);
users.AddMember(rapidjson::StringRef(user.pubkeyb64.data()), fdlist, allocator);
}
d.AddMember("usrfd", users, allocator);
Value peers(kObjectType);
rapidjson::Value peers(rapidjson::kObjectType);
for (auto &[sid, peer] : args.peers)
{
Value fdlist(kArrayType);
rapidjson::Value fdlist(rapidjson::kArrayType);
fdlist.PushBack(peer.inpipe[0], allocator);
fdlist.PushBack(peer.outpipe[1], allocator);
peers.AddMember(StringRef(peer.pubkeyb64.data()), fdlist, allocator);
peers.AddMember(rapidjson::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);
rapidjson::Value unl(rapidjson::kArrayType);
for (std::string &node : conf::cfg.unl)
unl.PushBack(rapidjson::StringRef(node.data()), allocator);
d.AddMember("unl", unl, allocator);
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
d.Accept(writer);
// Get the json string that should be written to contract input pipe.
@@ -124,7 +121,7 @@ int write_to_stdin(const ContractExecArgs &args)
int stdinpipe[2];
if (pipe(stdinpipe) != 0)
{
cerr << "Failed to create pipe to the contract process.\n";
std::cerr << "Failed to create pipe to the contract process.\n";
return -1;
}

View File

@@ -5,9 +5,6 @@
#include <map>
#include "util.hpp"
using namespace std;
using namespace util;
/**
* Contains helper functions regarding POSIX process execution and IPC between HP and SC.
*/
@@ -19,11 +16,11 @@ namespace proc
*/
struct ContractExecArgs
{
map<string, contract_user> &users; // Map of authenticated contract users indexed by user pubkey.
map<string, peer_node> &peers; // Map of connected peers indexed by node pubkey.
std::map<std::string, util::contract_user> &users; // Map of authenticated contract users indexed by user pubkey.
std::map<std::string, util::peer_node> &peers; // Map of connected peers indexed by node pubkey.
uint64_t timestamp; // Current HotPocket timestamp.
ContractExecArgs(map<string, contract_user> &_users, map<string, peer_node> &_peers, uint64_t _timestamp)
ContractExecArgs(std::map<std::string, util::contract_user> &_users, std::map<std::string, util::peer_node> &_peers, uint64_t _timestamp)
: users(_users), peers(_peers)
{
timestamp = _timestamp;

View File

@@ -14,8 +14,6 @@ namespace beast = boost::beast;
using tcp = net::ip::tcp;
using error = boost::system::error_code;
using namespace std;
namespace usr
{
@@ -24,13 +22,13 @@ namespace usr
*/
void user_session_handler::on_connect(sock::socket_session *session)
{
cout << "User client connected " << session->address_ << ":" << session->port_ << endl;
std::cout << "User client connected " << session->address_ << ":" << session->port_ << std::endl;
// As a soon as a user conntects, we issue them a challenge message. We remember the
// challenge we issued and later verifies the user's response with it.
string msg;
string challengeb64;
std::string msg;
std::string challengeb64;
usr::create_user_challenge(msg, challengeb64);
// We init the session unique id to associate with the challenge.
@@ -40,7 +38,7 @@ void user_session_handler::on_connect(sock::socket_session *session)
usr::pending_challenges[session->uniqueid_] = challengeb64;
// TODO: This needs to be reviewed to optimise passing the message.
session->send(make_shared<string>(msg));
session->send(std::make_shared<std::string>(msg));
// Set the challenge-issued flag to help later checks in on_message.
session->flags_.set(util::SESSION_FLAG::USER_CHALLENGE_ISSUED);
@@ -59,9 +57,9 @@ void user_session_handler::on_message(sock::socket_session *session, const std::
auto itr = usr::pending_challenges.find(session->uniqueid_);
if (itr != usr::pending_challenges.end())
{
string userpubkey;
const string &original_challenge = itr->second;
if (usr::verify_user_challenge_response(message, original_challenge, userpubkey) == 0)
std::string userpubkey;
const std::string &original_challenge = itr->second;
if (usr::verify_user_challenge_response(userpubkey, message, original_challenge) == 0)
{
// Challenge verification successful.
// Promote the connection from pending-challenges to authenticated users.
@@ -71,12 +69,12 @@ void user_session_handler::on_message(sock::socket_session *session, const std::
usr::pending_challenges.erase(session->uniqueid_); // Remove the stored challenge
usr::add_user(session->uniqueid_, userpubkey); // Add the user to the global authed user list
cout << "User connection " << session->uniqueid_ << " authenticated.\n";
std::cout << "User connection " << session->uniqueid_ << " authenticated.\n";
return;
}
else
{
cout << "Challenge verification failed " << session->uniqueid_ << endl;
std::cout << "Challenge verification failed " << session->uniqueid_ << std::endl;
}
}
}
@@ -91,16 +89,16 @@ void user_session_handler::on_message(sock::socket_session *session, const std::
{
// This is an authed user.
// Write the message to the user input pipe. SC will read from this pipe when it executes.
const contract_user &user = itr->second;
const util::contract_user &user = itr->second;
write(user.inpipe[1], message.data(), message.length());
cout << "User " << user.pubkeyb64 << " wrote " << message.length() << " bytes to contract input.\n";
std::cout << "User " << user.pubkeyb64 << " wrote " << message.length() << " bytes to contract input.\n";
return;
}
}
// If for any reason we reach this point, we should drop the connection.
session->close();
cout << "Dropped the user connection " << session->address_ << ":" << session->port_ << endl;
std::cout << "Dropped the user connection " << session->address_ << ":" << session->port_ << std::endl;
}
/**
@@ -121,7 +119,7 @@ void user_session_handler::on_close(sock::socket_session *session)
usr::remove_user(session->uniqueid_);
}
cout << "User disconnected " << session->uniqueid_ << endl;
std::cout << "User disconnected " << session->uniqueid_ << std::endl;
}
} // namespace usr

View File

@@ -16,10 +16,6 @@
#include "usr.hpp"
#include "user_session_handler.hpp"
using namespace std;
using namespace util;
using namespace rapidjson;
namespace usr
{
@@ -27,18 +23,18 @@ namespace usr
* Global user list. (Exposed to other sub systems)
* Map key: User socket session id (<ip:port>)
*/
map<string, contract_user> users;
std::map<std::string, util::contract_user> users;
/**
* Keep track of verification-pending challenges issued to newly connected users.
* Map key: User socket session id (<ip:port>)
*/
map<string, string> pending_challenges;
std::map<std::string, std::string> pending_challenges;
/**
* User session handler instance. This instance's methods will be fired for any user socket activity.
*/
user_session_handler global_usr_session_handler;
usr::user_session_handler global_usr_session_handler;
/**
* The IO context used by the websocket listener. (not exposed out of this namespace)
@@ -48,7 +44,7 @@ net::io_context ioc;
/**
* The thread the websocket lsitener is running on. (not exposed out of this namespace)
*/
thread listener_thread;
std::thread listener_thread;
// Challenge response fields.
// These fields are used on challenge response validation.
@@ -90,7 +86,7 @@ int init()
* }
* @param challenge String reference to copy the generated base64 challenge string into.
*/
void create_user_challenge(string &msg, string &challengeb64)
void create_user_challenge(std::string &msg, std::string &challengeb64)
{
//Use libsodium to generate the random challenge bytes.
unsigned char challenge_bytes[CHALLENGE_LEN];
@@ -99,7 +95,7 @@ void create_user_challenge(string &msg, string &challengeb64)
//We pass the b64 challenge string separately to the caller even though
//we also include it in the challenge msg as well.
base64_encode(challenge_bytes, CHALLENGE_LEN, challengeb64);
util::base64_encode(challengeb64, challenge_bytes, CHALLENGE_LEN);
//Construct the challenge msg json.
// We do not use RapidJson here in favour of performance because this is a simple json message.
@@ -119,6 +115,7 @@ void create_user_challenge(string &msg, string &challengeb64)
* Verifies the user challenge response with the original challenge issued to the user
* and the user public key contained in the response.
*
* @param extracted_pubkeyb64 The base64 public key extracted from the response.
* @param response The response bytes to verify. This will be parsed as json.
* Accepted response format:
* {
@@ -128,55 +125,54 @@ void create_user_challenge(string &msg, string &challengeb64)
* "pubkey": "<Base64 public key of the user>"
* }
* @param original_challenge The original base64 challenge string issued to the user.
* @param extracted_pubkeyb64 The public key extracted from the response.
* @return 0 if challenge response is verified. -1 if challenge not met or an error occurs.
*/
int verify_user_challenge_response(const string &response, const string &original_challenge, string &extracted_pubkeyb64)
int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::string &response, const std::string &original_challenge)
{
// We load response raw bytes into json document.
Document d;
rapidjson::Document d;
d.Parse(response.data());
if (d.HasParseError())
{
cerr << "Challenge response json parser error.\n";
std::cerr << "Challenge response json parser error.\n";
return -1;
}
// Validate msg type.
if (!d.HasMember(CHALLENGE_RESP_TYPE) || d[CHALLENGE_RESP_TYPE] != CHALLENGE_RESP_MSGTYPE)
{
cerr << "User challenge response type invalid. 'challenge_response' expected.\n";
std::cerr << "User challenge response type invalid. 'challenge_response' expected.\n";
return -1;
}
// Compare the response challenge string with the original issued challenge.
if (!d.HasMember(CHALLENGE_RESP_CHALLENGE) || d[CHALLENGE_RESP_CHALLENGE] != original_challenge.data())
{
cerr << "User challenge response challenge invalid.\n";
std::cerr << "User challenge response challenge invalid.\n";
return -1;
}
// Check for the 'sig' field existence.
if (!d.HasMember(CHALLENGE_RESP_SIG) || !d[CHALLENGE_RESP_SIG].IsString())
{
cerr << "User challenge response signature invalid.\n";
std::cerr << "User challenge response signature invalid.\n";
return -1;
}
// Check for the 'pubkey' field existence.
if (!d.HasMember(CHALLENGE_RESP_PUBKEY) || !d[CHALLENGE_RESP_PUBKEY].IsString())
{
cerr << "User challenge response public key invalid.\n";
std::cerr << "User challenge response public key invalid.\n";
return -1;
}
// Verify the challenge signature. We do this last due to signature verification cost.
string sigb64 = d[CHALLENGE_RESP_SIG].GetString();
std::string sigb64 = d[CHALLENGE_RESP_SIG].GetString();
extracted_pubkeyb64 = d[CHALLENGE_RESP_PUBKEY].GetString();
if (crypto::verify_b64(original_challenge, sigb64, extracted_pubkeyb64) != 0)
{
cerr << "User challenge response signature verification failed.\n";
std::cerr << "User challenge response signature verification failed.\n";
return -1;
}
@@ -191,11 +187,11 @@ int verify_user_challenge_response(const string &response, const string &origina
* @param pubkeyb64 User's base64 public key.
* @return 0 on successful additions. -1 on failure.
*/
int add_user(const string &sessionid, const string &pubkeyb64)
int add_user(const std::string &sessionid, const std::string &pubkeyb64)
{
if (users.count(sessionid) == 1)
{
cerr << sessionid << " already exist. Cannot add user.\n";
std::cerr << sessionid << " already exist. Cannot add user.\n";
return -1;
}
@@ -205,7 +201,7 @@ int add_user(const string &sessionid, const string &pubkeyb64)
int inpipe[2];
if (pipe(inpipe) != 0)
{
cerr << "User in pipe creation failed. sessionid:" << sessionid << endl;
std::cerr << "User in pipe creation failed. sessionid:" << sessionid << std::endl;
return -1;
}
@@ -213,7 +209,7 @@ int add_user(const string &sessionid, const string &pubkeyb64)
int outpipe[2];
if (pipe(outpipe) != 0)
{
cerr << "User out pipe creation failed. sessionid:" << sessionid << endl;
std::cerr << "User out pipe creation failed. sessionid:" << sessionid << std::endl;
//We need to close 'inpipe' in case outpipe failed.
close(inpipe[0]);
@@ -222,7 +218,7 @@ int add_user(const string &sessionid, const string &pubkeyb64)
return -1;
}
users.emplace(sessionid, contract_user(pubkeyb64, inpipe, outpipe));
users.emplace(sessionid, util::contract_user(pubkeyb64, inpipe, outpipe));
return 0;
}
@@ -232,17 +228,17 @@ int add_user(const string &sessionid, const string &pubkeyb64)
*
* @return 0 on successful removals. -1 on failure.
*/
int remove_user(const string &sessionid)
int remove_user(const std::string &sessionid)
{
auto itr = users.find(sessionid);
if (itr == users.end())
{
cerr << sessionid << " does not exist. Cannot remove user.\n";
std::cerr << sessionid << " does not exist. Cannot remove user.\n";
return -1;
}
const contract_user &user = itr->second;
const util::contract_user &user = itr->second;
//Close the User <--> SC I/O pipes.
close(user.inpipe[0]);
@@ -282,9 +278,9 @@ int read_contract_user_outputs()
read(fdout, data, bytes_available);
//Populate the user output buffer with new data
user.outbuffer = string(data, bytes_available);
user.outbuffer = std::string(data, bytes_available);
cout << "Read " + to_string(bytes_available) << " bytes into user output buffer. user:" + user.pubkeyb64 << endl;
std::cout << "Read " + std::to_string(bytes_available) << " bytes into user output buffer. user:" + user.pubkeyb64 << std::endl;
}
}
@@ -297,15 +293,15 @@ int read_contract_user_outputs()
void start_listening()
{
auto address = net::ip::make_address(conf::cfg.listenip);
make_shared<sock::socket_server>(
std::make_shared<sock::socket_server>(
ioc,
tcp::endpoint{address, conf::cfg.pubport},
global_usr_session_handler)
->run();
listener_thread = thread([&] { ioc.run(); });
listener_thread = std::thread([&] { ioc.run(); });
cout << "Started listening for incoming user connections...\n";
std::cout << "Started listening for incoming user connections...\n";
}
} // namespace usr

View File

@@ -6,9 +6,6 @@
#include <map>
#include "../util.hpp"
using namespace std;
using namespace util;
/**
* Maintains the global user list with pending input outputs and manages user connections.
*/
@@ -18,27 +15,27 @@ namespace usr
/**
* Global authenticated (challenge-verified) user list.
*/
extern map<string, contract_user> users;
extern std::map<std::string, util::contract_user> users;
/**
* Keep track of verification-pending challenges issued to newly connected users.
*/
extern map<string, string> pending_challenges;
extern std::map<std::string, std::string> pending_challenges;
/**
* Keep track of verification-pending challenges issued to newly connected users.
*/
extern map<string, string> pending_challenges;
extern std::map<std::string, std::string> pending_challenges;
int init();
void create_user_challenge(string &msg, string &challengeb64);
void create_user_challenge(std::string &msg, std::string &challengeb64);
int verify_user_challenge_response(const string &response, const string &original_challenge, string &extracted_pubkey);
int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::string &response, const std::string &original_challenge);
int add_user(const string &sessionid, const string &pubkeyb64);
int add_user(const std::string &sessionid, const std::string &pubkeyb64);
int remove_user(const string &sessionid);
int remove_user(const std::string &sessionid);
int read_contract_user_outputs();

View File

@@ -2,19 +2,17 @@
#include <sodium.h>
#include <sstream>
using namespace std;
namespace util
{
/**
* Encodes provided bytes to base64 string.
*
* @param encoded_string String reference to assign the base64 encoded output.
* @param bin Bytes to encode.
* @param bin_len Bytes length.
* @param encoded_string String reference to assign the base64 encoded output.
*/
int base64_encode(const unsigned char *bin, size_t bin_len, string &encoded_string)
int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t bin_len)
{
// Get length of encoded result from sodium.
const size_t base64_len = sodium_base64_encoded_len(bin_len, sodium_base64_VARIANT_ORIGINAL);
@@ -32,23 +30,23 @@ int base64_encode(const unsigned char *bin, size_t bin_len, string &encoded_stri
// Assign the encoded char* onto the provided string reference.
// "base64_len - 1" because sodium include '\0' in the calculated base64 length.
// Therefore we need to omit it when initializing the std::string.
encoded_string = string(base64chars, base64_len - 1);
encoded_string = std::string(base64chars, base64_len - 1);
return 0;
}
/**
* Decodes provided base64 string into bytes.
*
* @param decodedbuf Buffer to assign decoded bytes.
* @param decodedbuf_len Decoded buffer size.
* @param base64_str Base64 string to decode.
* @param decoded Decoded bytes.
* @param decoded_len Decoded bytes length.
*/
int base64_decode(const string &base64_str, unsigned char *decoded, size_t decoded_len)
int base64_decode(unsigned char *decodedbuf, size_t decodedbuf_len, const std::string &base64_str)
{
const char *b64_end;
size_t bin_len;
if (sodium_base642bin(
decoded, decoded_len,
decodedbuf, decodedbuf_len,
base64_str.data(), base64_str.size() + 1,
"", &bin_len, &b64_end,
sodium_base64_VARIANT_ORIGINAL))
@@ -66,9 +64,9 @@ int base64_decode(const string &base64_str, unsigned char *decoded, size_t decod
* v1 > v2 -> returns +1
* Error -> returns -2
*/
int version_compare(const string &x, const string &y)
int version_compare(const std::string &x, const std::string &y)
{
istringstream ix(x), iy(y);
std::istringstream ix(x), iy(y);
while (ix.good() || iy.good())
{
int cx = 0, cy = 0;

View File

@@ -4,8 +4,6 @@
#include <string>
#include <vector>
using namespace std;
/**
* Contains helper functions and data structures used by multiple other subsystems.
*/
@@ -39,12 +37,12 @@ enum SESSION_FLAG
*/
struct contract_user
{
string pubkeyb64; // Base64 user public key
std::string pubkeyb64; // Base64 user public key
int inpipe[2]; // Pipe to receive user input
int outpipe[2]; // Pipe to receive output produced by the contract
string outbuffer; // Holds the contract output to be processed by consensus rounds
std::string outbuffer; // Holds the contract output to be processed by consensus rounds
contract_user(const string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
contract_user(const std::string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
{
pubkeyb64 = _pubkeyb64;
inpipe[0] = _inpipe[0];
@@ -59,11 +57,11 @@ struct contract_user
*/
struct peer_node
{
string pubkeyb64; // Base64 peer public key
std::string pubkeyb64; // Base64 peer public key
int inpipe[2]; // NPL pipe from HP to SC
int outpipe[2]; // NPL pipe from SC to HP
peer_node(const string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
peer_node(const std::string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
{
pubkeyb64 = _pubkeyb64;
inpipe[0] = _inpipe[0];
@@ -73,11 +71,11 @@ struct peer_node
}
};
int base64_encode(const unsigned char *bin, size_t bin_len, string &encoded_string);
int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t bin_len);
int base64_decode(const string &base64_str, unsigned char *decoded, size_t decoded_len);
int base64_decode(unsigned char *decoded, size_t decoded_len, const std::string &base64_str);
int version_compare(const string &v1, const string &v2);
int version_compare(const std::string &v1, const std::string &v2);
} // namespace util