Optimized string passing with string_view.

This commit is contained in:
Ravin Perera
2019-10-14 11:17:55 +05:30
parent ebf13209e1
commit 56c3e3ee93
10 changed files with 54 additions and 44 deletions

View File

@@ -143,7 +143,7 @@ int load_config()
ifs.close();
// Check whether the contract version is specified.
std::string cfgversion = d["version"].GetString();
std::string_view cfgversion = util::getsv(d["version"]);
if (cfgversion.empty())
{
std::cerr << "Contract config version missing.\n";
@@ -151,7 +151,7 @@ int load_config()
}
// Check whether this contract complies with the min version requirement.
int verresult = util::version_compare(cfgversion, std::string(util::MIN_CONTRACT_VERSION));
int verresult = util::version_compare(std::string(cfgversion), std::string(util::MIN_CONTRACT_VERSION));
if (verresult == -1)
{
std::cerr << "Contract version too old. Minimum "

View File

@@ -45,7 +45,7 @@ void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string
* @param seckey Secret key bytes.
* @return Signature bytes.
*/
std::string sign(const std::string &msg, const std::string &seckey)
std::string sign(std::string_view msg, std::string_view seckey)
{
//Generate the signature using libsodium.
@@ -68,7 +68,7 @@ std::string sign(const std::string &msg, const std::string &seckey)
* @param seckeyb64 Base64 secret key string.
* @return Base64 signature string.
*/
std::string sign_b64(const std::string &msg, const std::string &seckeyb64)
std::string sign_b64(std::string_view msg, std::string_view seckeyb64)
{
//Decode b64 string and generate the signature using libsodium.
@@ -96,7 +96,7 @@ std::string sign_b64(const std::string &msg, const std::string &seckeyb64)
* @param pubkey Public key bytes.
* @return 0 for successful verification. -1 for failure.
*/
int verify(const std::string &msg, const std::string &sig, const std::string &pubkey)
int verify(std::string_view msg, std::string_view sig, std::string_view pubkey)
{
return crypto_sign_verify_detached(
reinterpret_cast<const unsigned char *>(sig.data()),
@@ -113,7 +113,7 @@ int verify(const std::string &msg, const std::string &sig, const std::string &pu
* @param pubkeyb64 Base64 secret key.
* @return 0 for successful verification. -1 for failure.
*/
int verify_b64(const std::string &msg, const std::string &sigb64, const std::string &pubkeyb64)
int verify_b64(std::string_view msg, std::string_view sigb64, std::string_view pubkeyb64)
{
//Decode b64 string and verify the signature using libsodium.

View File

@@ -12,13 +12,13 @@ int init();
void generate_signing_keys(std::string &pubkey, std::string &seckey, std::string &keytype);
std::string sign(const std::string &msg, const std::string &seckey);
std::string sign(std::string_view msg, std::string_view seckey);
std::string sign_b64(const std::string &msg, const std::string &seckeyb64);
std::string sign_b64(std::string_view msg, std::string_view seckeyb64);
int verify(const std::string &msg, const std::string &sig, const std::string &pubkey);
int verify(std::string_view msg, std::string_view sig, std::string_view pubkey);
int verify_b64(const std::string &msg, const std::string &sigb64, const std::string &pubkeyb64);
int verify_b64(std::string_view msg, std::string_view sigb64, std::string_view pubkeyb64);
} // namespace crypto

View File

@@ -17,7 +17,7 @@ socket_session::socket_session(websocket::stream<beast::tcp_stream> &websocket,
}
//port and address will be used to identify from which client the message recieved in the handler
void socket_session::server_run(const std::uint16_t port, const std::string &address)
void socket_session::server_run(const std::uint16_t port, std::string_view address)
{
port_ = port;
address_ = address;
@@ -31,15 +31,11 @@ void socket_session::server_run(const std::uint16_t port, const std::string &add
}
//port and address will be used to identify from which server the message recieved in the handler
void socket_session::client_run(const std::uint16_t port, const std::string &address, error ec)
void socket_session::client_run(const std::uint16_t port, std::string_view address, error ec)
{
port_ = port;
address_ = address;
// Create a unique id for the session combining ip and port.
uniqueid_ = address + ":";
uniqueid_.append(std::to_string(port));
if (ec)
return fail(ec, "handshake");

View File

@@ -59,8 +59,8 @@ public:
// Setting and reading flags to this is completely managed by user-code.
std::bitset<8> flags_;
void server_run(const std::uint16_t port, const std::string &address);
void client_run(const std::uint16_t port, const std::string &address, error ec);
void server_run(const std::uint16_t port, std::string_view address);
void client_run(const std::uint16_t port, std::string_view address, error ec);
// Used to send message through an active websocket connection.
void send(std::shared_ptr<std::string const> const &ss);

View File

@@ -58,7 +58,7 @@ void user_session_handler::on_message(sock::socket_session *session, const std::
if (itr != usr::pending_challenges.end())
{
std::string userpubkey;
const std::string &original_challenge = itr->second;
std::string_view original_challenge = itr->second;
if (usr::verify_user_challenge_response(userpubkey, message, original_challenge) == 0)
{
// Challenge verification successful.

View File

@@ -23,13 +23,13 @@ namespace usr
* Global user list. (Exposed to other sub systems)
* Map key: User socket session id (<ip:port>)
*/
std::map<std::string, util::contract_user> users;
std::map<std::string, util::contract_user, std::less<>> users;
/**
* Keep track of verification-pending challenges issued to newly connected users.
* Map key: User socket session id (<ip:port>)
*/
std::map<std::string, std::string> pending_challenges;
std::map<std::string, std::string, std::less<>> pending_challenges;
/**
* User session handler instance. This instance's methods will be fired for any user socket activity.
@@ -127,7 +127,7 @@ void create_user_challenge(std::string &msg, std::string &challengeb64)
* @param original_challenge The original base64 challenge string issued to the user.
* @return 0 if challenge response is verified. -1 if challenge not met or an error occurs.
*/
int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::string &response, const std::string &original_challenge)
int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string_view response, std::string_view original_challenge)
{
// We load response raw bytes into json document.
rapidjson::Document d;
@@ -167,10 +167,10 @@ int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::
}
// Verify the challenge signature. We do this last due to signature verification cost.
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)
if (crypto::verify_b64(
original_challenge,
util::getsv(d[CHALLENGE_RESP_SIG]),
util::getsv(d[CHALLENGE_RESP_PUBKEY])) != 0)
{
std::cerr << "User challenge response signature verification failed.\n";
return -1;
@@ -187,7 +187,7 @@ int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::
* @param pubkeyb64 User's base64 public key.
* @return 0 on successful additions. -1 on failure.
*/
int add_user(const std::string &sessionid, const std::string &pubkeyb64)
int add_user(std::string_view sessionid, std::string_view pubkeyb64)
{
if (users.count(sessionid) == 1)
{
@@ -228,7 +228,7 @@ int add_user(const std::string &sessionid, const std::string &pubkeyb64)
*
* @return 0 on successful removals. -1 on failure.
*/
int remove_user(const std::string &sessionid)
int remove_user(std::string_view sessionid)
{
auto itr = users.find(sessionid);

View File

@@ -2,7 +2,7 @@
#define _HP_USR_H_
#include <cstdio>
#include <vector>
#include <string_view>
#include <map>
#include "../util.hpp"
@@ -15,27 +15,22 @@ namespace usr
/**
* Global authenticated (challenge-verified) user list.
*/
extern std::map<std::string, util::contract_user> users;
extern std::map<std::string, util::contract_user, std::less<>> users;
/**
* Keep track of verification-pending challenges issued to newly connected users.
*/
extern std::map<std::string, std::string> pending_challenges;
/**
* Keep track of verification-pending challenges issued to newly connected users.
*/
extern std::map<std::string, std::string> pending_challenges;
extern std::map<std::string, std::string, std::less<>> pending_challenges;
int init();
void create_user_challenge(std::string &msg, std::string &challengeb64);
int verify_user_challenge_response(std::string &extracted_pubkeyb64, const std::string &response, const std::string &original_challenge);
int verify_user_challenge_response(std::string &extracted_pubkeyb64, std::string_view response, std::string_view original_challenge);
int add_user(const std::string &sessionid, const std::string &pubkeyb64);
int add_user(std::string_view sessionid, std::string_view pubkeyb64);
int remove_user(const std::string &sessionid);
int remove_user(std::string_view sessionid);
int read_contract_user_outputs();

View File

@@ -1,6 +1,7 @@
#include <string>
#include <sodium.h>
#include <sstream>
#include <rapidjson/document.h>
namespace util
{
@@ -41,7 +42,7 @@ int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t
* @param decodedbuf_len Decoded buffer size.
* @param base64_str Base64 string to decode.
*/
int base64_decode(unsigned char *decodedbuf, size_t decodedbuf_len, const std::string &base64_str)
int base64_decode(unsigned char *decodedbuf, size_t decodedbuf_len, std::string_view base64_str)
{
const char *b64_end;
size_t bin_len;
@@ -63,6 +64,11 @@ int base64_decode(unsigned char *decodedbuf, size_t decodedbuf_len, const std::s
* v1 == v2 -> returns 0
* v1 > v2 -> returns +1
* Error -> returns -2
*
* Remark on string_view: In other places of the code-base we utilize string_view
* to pass immutable string references around. However in this function we keep the 'const string&'
* syntax because istringstream doesn't support string_view. It's not worth optmising
* this code as it's not being used in high-scale processing.
*/
int version_compare(const std::string &x, const std::string &y)
{
@@ -88,4 +94,14 @@ int version_compare(const std::string &x, const std::string &y)
return 0;
}
/**
* Returns a std::string_view pointing to the rapidjson Value which is assumed
* to be a string. We use this function because rapidjson does not have build-in string_view
* support. Passing a non-string 'v' is not supported.
*/
std::string_view getsv(const rapidjson::Value &v)
{
return std::string_view(v.GetString(), v.GetStringLength());
}
} // namespace util

View File

@@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include <rapidjson/document.h>
/**
* Contains helper functions and data structures used by multiple other subsystems.
@@ -42,7 +43,7 @@ struct contract_user
int outpipe[2]; // Pipe to receive output produced by the contract
std::string outbuffer; // Holds the contract output to be processed by consensus rounds
contract_user(const std::string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
contract_user(std::string_view _pubkeyb64, int _inpipe[2], int _outpipe[2])
{
pubkeyb64 = _pubkeyb64;
inpipe[0] = _inpipe[0];
@@ -61,7 +62,7 @@ struct peer_node
int inpipe[2]; // NPL pipe from HP to SC
int outpipe[2]; // NPL pipe from SC to HP
peer_node(const std::string &_pubkeyb64, int _inpipe[2], int _outpipe[2])
peer_node(std::string_view _pubkeyb64, int _inpipe[2], int _outpipe[2])
{
pubkeyb64 = _pubkeyb64;
inpipe[0] = _inpipe[0];
@@ -73,9 +74,11 @@ struct peer_node
int base64_encode(std::string &encoded_string, const unsigned char *bin, size_t bin_len);
int base64_decode(unsigned char *decoded, size_t decoded_len, const std::string &base64_str);
int base64_decode(unsigned char *decoded, size_t decoded_len, std::string_view base64_str);
int version_compare(const std::string &v1, const std::string &v2);
int version_compare(const std::string &x, const std::string &y);
std::string_view getsv(const rapidjson::Value &v);
} // namespace util