mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Websocket re-architecture with websocketd and websocat (#89)
- Replaced beast with websocketd and websocat. #79 #83 #84 - Implemented inbound/outbound peer connection merging. - Added graceful shutdown of hpcore with sigint. #87
This commit is contained in:
111
src/usr/usr.cpp
111
src/usr/usr.cpp
@@ -1,8 +1,7 @@
|
||||
#include "../pchheader.hpp"
|
||||
#include "../jsonschema/usrmsg_helpers.hpp"
|
||||
#include "../sock/socket_server.hpp"
|
||||
#include "../sock/socket_session.hpp"
|
||||
#include "../sock/socket_session_handler.hpp"
|
||||
#include "../comm/comm_server.hpp"
|
||||
#include "../comm/comm_session.hpp"
|
||||
#include "../util.hpp"
|
||||
#include "../conf.hpp"
|
||||
#include "../crypto.hpp"
|
||||
@@ -19,9 +18,6 @@ namespace usr
|
||||
// Holds global connected-users and related objects.
|
||||
connected_context ctx;
|
||||
|
||||
// Holds objects used by socket listener.
|
||||
listener_context listener_ctx;
|
||||
|
||||
/**
|
||||
* Initializes the usr subsystem. Must be called once during application startup.
|
||||
* @return 0 for successful initialization. -1 for failure.
|
||||
@@ -29,20 +25,29 @@ listener_context listener_ctx;
|
||||
int init()
|
||||
{
|
||||
// Start listening for incoming user connections.
|
||||
start_listening();
|
||||
return 0;
|
||||
return start_listening();
|
||||
}
|
||||
|
||||
std::string issue_challenge(const std::string sessionid)
|
||||
/**
|
||||
* Cleanup any running processes.
|
||||
*/
|
||||
void deinit()
|
||||
{
|
||||
std::string msgstr;
|
||||
std::string challengehex;
|
||||
jusrmsg::create_user_challenge(msgstr, challengehex);
|
||||
ctx.listener.stop();
|
||||
}
|
||||
|
||||
// Create an entry in pending_challenges for later tracking upon challenge response.
|
||||
ctx.pending_challenges.try_emplace(std::move(sessionid), challengehex);
|
||||
/**
|
||||
* Starts listening for incoming user websocket connections.
|
||||
*/
|
||||
int start_listening()
|
||||
{
|
||||
const uint64_t metric_thresholds[] = {conf::cfg.pubmaxcpm, 0, 0, conf::cfg.pubmaxbadmpm};
|
||||
if (ctx.listener.start(
|
||||
conf::cfg.pubport, ".sock-user", comm::SESSION_TYPE::USER, false, metric_thresholds, std::set<conf::ip_port_pair>(), conf::cfg.pubmaxsize) == -1)
|
||||
return -1;
|
||||
|
||||
return msgstr;
|
||||
LOG_INFO << "Started listening for user connections on " << std::to_string(conf::cfg.pubport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,18 +56,17 @@ std::string issue_challenge(const std::string sessionid)
|
||||
* @param session The socket session that received the response.
|
||||
* @return 0 for successful verification. -1 for failure.
|
||||
*/
|
||||
int verify_challenge(std::string_view message, sock::socket_session<user_outbound_message> *session)
|
||||
int verify_challenge(std::string_view message, comm::comm_session &session)
|
||||
{
|
||||
// The received message must be the challenge response. We need to verify it.
|
||||
const auto itr = ctx.pending_challenges.find(session->uniqueid);
|
||||
if (itr == ctx.pending_challenges.end())
|
||||
if (session.issued_challenge.empty())
|
||||
{
|
||||
LOG_DBG << "No challenge found for the session " << session->uniqueid;
|
||||
LOG_DBG << "No challenge found for the session " << session.uniqueid;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string userpubkeyhex;
|
||||
std::string_view original_challenge = itr->second;
|
||||
std::string_view original_challenge = session.issued_challenge;
|
||||
if (jusrmsg::verify_user_challenge_response(userpubkeyhex, message, original_challenge) == 0)
|
||||
{
|
||||
// Challenge singature verification successful.
|
||||
@@ -82,23 +86,23 @@ int verify_challenge(std::string_view message, sock::socket_session<user_outboun
|
||||
// All good. Unique public key.
|
||||
// Promote the connection from pending-challenges to authenticated users.
|
||||
|
||||
session->flags.reset(sock::SESSION_FLAG::USER_CHALLENGE_ISSUED); // Clear challenge-issued flag
|
||||
session->flags.set(sock::SESSION_FLAG::USER_AUTHED); // Set the user-authed flag
|
||||
add_user(session, userpubkey); // Add the user to the global authed user list
|
||||
ctx.pending_challenges.erase(session->uniqueid); // Remove the stored challenge
|
||||
session.flags.reset(comm::SESSION_FLAG::USER_CHALLENGE_ISSUED); // Clear challenge-issued flag
|
||||
session.flags.set(comm::SESSION_FLAG::USER_AUTHED); // Set the user-authed flag
|
||||
add_user(session, userpubkey); // Add the user to the global authed user list
|
||||
session.issued_challenge.clear(); // Remove the stored challenge
|
||||
|
||||
LOG_DBG << "User connection " << session->uniqueid << " authenticated. Public key "
|
||||
LOG_DBG << "User connection " << session.uniqueid << " authenticated. Public key "
|
||||
<< userpubkeyhex;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DBG << "Duplicate user public key " << session->uniqueid;
|
||||
LOG_DBG << "Duplicate user public key " << session.uniqueid;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DBG << "Challenge verification failed " << session->uniqueid;
|
||||
LOG_DBG << "Challenge verification failed " << session.uniqueid;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -144,7 +148,7 @@ int handle_user_message(connected_user &user, std::string_view message)
|
||||
{
|
||||
std::string msg;
|
||||
jusrmsg::create_status_response(msg);
|
||||
user.session->send(user_outbound_message(std::move(msg)));
|
||||
user.session.send(msg);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -165,14 +169,11 @@ int handle_user_message(connected_user &user, std::string_view message)
|
||||
/**
|
||||
* Send the specified status result via the provided session.
|
||||
*/
|
||||
void send_request_status_result(sock::socket_session<user_outbound_message> *session, std::string_view status, std::string_view reason, std::string_view origin_type, std::string_view origin_extra_data)
|
||||
void send_request_status_result(const comm::comm_session &session, std::string_view status, std::string_view reason, std::string_view origin_type, std::string_view origin_extra_data)
|
||||
{
|
||||
if (session != NULL)
|
||||
{
|
||||
std::string msg;
|
||||
jusrmsg::create_request_status_result(msg, status, reason, origin_type, origin_extra_data);
|
||||
session->send(usr::user_outbound_message(std::move(msg)));
|
||||
}
|
||||
std::string msg;
|
||||
jusrmsg::create_request_status_result(msg, status, reason, origin_type, origin_extra_data);
|
||||
session.send(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +184,9 @@ void send_request_status_result(sock::socket_session<user_outbound_message> *ses
|
||||
* @param pubkey User's binary public key.
|
||||
* @return 0 on successful additions. -1 on failure.
|
||||
*/
|
||||
int add_user(sock::socket_session<user_outbound_message> *session, const std::string &pubkey)
|
||||
int add_user(const comm::comm_session &session, const std::string &pubkey)
|
||||
{
|
||||
const std::string &sessionid = session->uniqueid;
|
||||
const std::string &sessionid = session.uniqueid;
|
||||
if (ctx.users.count(sessionid) == 1)
|
||||
{
|
||||
LOG_INFO << sessionid << " already exist. Cannot add user.";
|
||||
@@ -236,41 +237,17 @@ int remove_user(const std::string &sessionid)
|
||||
* @param pubkey User binary pubkey.
|
||||
* @return Pointer to the socket session. NULL of not found.
|
||||
*/
|
||||
sock::socket_session<usr::user_outbound_message> *get_session_by_pubkey(const std::string &pubkey)
|
||||
const comm::comm_session *get_session_by_pubkey(const std::string &pubkey)
|
||||
{
|
||||
const auto sessionid_itr = usr::ctx.sessionids.find(pubkey);
|
||||
if (sessionid_itr != usr::ctx.sessionids.end())
|
||||
const auto sessionid_itr = ctx.sessionids.find(pubkey);
|
||||
if (sessionid_itr != ctx.sessionids.end())
|
||||
{
|
||||
const auto user_itr = usr::ctx.users.find(sessionid_itr->second);
|
||||
if (user_itr != usr::ctx.users.end())
|
||||
return user_itr->second.session;
|
||||
const auto user_itr = ctx.users.find(sessionid_itr->second);
|
||||
if (user_itr != ctx.users.end())
|
||||
return &user_itr->second.session;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening for incoming user websocket connections.
|
||||
*/
|
||||
void start_listening()
|
||||
{
|
||||
|
||||
auto address = net::ip::make_address(conf::cfg.listenip);
|
||||
listener_ctx.default_sess_opts.max_socket_read_len = conf::cfg.pubmaxsize;
|
||||
listener_ctx.default_sess_opts.max_rawbytes_per_minute = conf::cfg.pubmaxcpm;
|
||||
listener_ctx.default_sess_opts.max_badmsgs_per_minute = conf::cfg.pubmaxbadmpm;
|
||||
|
||||
std::make_shared<sock::socket_server<user_outbound_message>>(
|
||||
listener_ctx.ioc,
|
||||
listener_ctx.ssl_ctx,
|
||||
tcp::endpoint{address, conf::cfg.pubport},
|
||||
listener_ctx.global_usr_session_handler,
|
||||
listener_ctx.default_sess_opts)
|
||||
->run();
|
||||
|
||||
listener_ctx.listener_thread = std::thread([&] { listener_ctx.ioc.run(); });
|
||||
|
||||
LOG_INFO << "Started listening for incoming user connections...";
|
||||
}
|
||||
|
||||
} // namespace usr
|
||||
Reference in New Issue
Block a user