Skip to content

Commit

Permalink
path control serialization, smaller overall payload
Browse files Browse the repository at this point in the history
  • Loading branch information
dr7ana committed Oct 28, 2024
1 parent de4843c commit f8d625b
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 148 deletions.
11 changes: 5 additions & 6 deletions llarp/contact/client_contact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,11 @@ namespace llarp
oxenc::bt_dict_producer btdp;
enc.bt_encode(btdp);

auto view = btdp.view_for_signing<unsigned char>();

if (not crypto::sign(enc.sig, derived_privatekey, view.data(), view.size()))
throw std::runtime_error{"Failed to sign EncryptedClientContact payload!"};

btdp.append("~", enc.sig.to_view());
btdp.append_signature("~", [&](ustring_view to_sign) {
if (not crypto::sign(enc.sig, derived_privatekey, to_sign.data(), to_sign.size()))
throw std::runtime_error{"Failed to sign EncryptedClientContact payload!"};
return enc.sig.to_view();
});

enc._bt_payload = std::move(btdp).str();
}
Expand Down
4 changes: 2 additions & 2 deletions llarp/handlers/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ namespace llarp::handlers
auto enc = client_contact.encrypt_and_sign();

if (publish_client_contact(enc))
log::debug(logcat, "Successfully republished updated EncryptedClientContact!");
log::info(logcat, "Successfully republished updated EncryptedClientContact!");
else
log::warning(logcat, "Failed to republish updated EncryptedClientContact!");
}
Expand Down Expand Up @@ -414,7 +414,7 @@ namespace llarp::handlers
{
log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid());

ret += path->publish_client_contact(ecc, true);
ret &= path->publish_client_contact(ecc, true);
}
}

Expand Down
204 changes: 110 additions & 94 deletions llarp/link/link_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,69 +706,6 @@ namespace llarp
log::warning(logcat, "NodeDB query for {} random RCs for connection returned none", num_conns);
}

void LinkManager::handle_path_data_message(bstring message)
{
ustring nonce, hop_id_str, payload;

try
{
oxenc::bt_dict_consumer btdc{message};
std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc);
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
return;
}

auto symmnonce = SymmNonce{nonce.data()};
HopID hopid{hop_id_str.data()};
auto hop = _router.path_context()->get_transit_hop(hopid);

if (not hop)
return;

symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR);

// if terminal hop, pass to the correct path expecting to receive this message
if (hop->terminal_hop)
{
NetworkAddress sender;
bstring data;

try
{
oxenc::bt_dict_consumer btdc{payload};
std::tie(sender, data) = PATH::DATA::deserialize(btdc);

if (auto session = _router.session_endpoint()->get_session(sender))
{
session->recv_path_data_message(std::move(data));
}
else
{
log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender);
}
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
}
}
else
{
// if not terminal hop, relay datagram onwards
auto hop_is_rx = hop->rxid() == hopid;

const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid();
const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream();

std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload);

send_data_message(next_router, std::move(new_payload));
}
}

void LinkManager::gossip_rc(const RouterID& last_sender, const RemoteRC& rc)
{
_router.loop()->call([this, last_sender, rc]() {
Expand Down Expand Up @@ -1153,8 +1090,13 @@ namespace llarp
"publish_cc",
PublishClientContact::serialize(std::move(enc), relay_order, is_relayed),
[respond = std::move(respond)](oxen::quic::message m) mutable {
if (m.timed_out)
return; // drop; requester will already have timed out
if (m)
log::info(logcat, "Relayed PublishClientContact returned successful! Relaying response...");
else if (m.timed_out)
log::info(logcat, "Relayed PublishClientContact timed out! Relaying response...");
else
log::info(logcat, "Relayed PublishClientContact failed! Relaying response...");

respond(m.body_str());
});
}
Expand Down Expand Up @@ -1350,90 +1292,162 @@ namespace llarp

void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */)
{
ustring nonce, hop_id_str, payload;
HopID hop_id;
std::string payload;
SymmNonce nonce;

try
{
oxenc::bt_dict_consumer btdc{m.body()};
std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc);
std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()});
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
return;
return m.respond(messages::ERROR_RESPONSE, true);
}

auto symmnonce = SymmNonce{nonce.data()};
HopID hopid{hop_id_str.data()};
auto hop = _router.path_context()->get_transit_hop(hopid);
auto hop = _router.path_context()->get_transit_hop(hop_id);

// TODO: use "path_control" for both directions? If not, drop message on
// floor if we don't have the path_id in question; if we decide to make this
// bidirectional, will need to check if we have a Path with path_id.
if (not hop)
return;
{
log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id);
return m.respond(messages::ERROR_RESPONSE, true);
}

symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR);
nonce = crypto::onion(
reinterpret_cast<unsigned char*>(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR);

// if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond.
if (hop->terminal_hop)
{
handle_inner_request(
std::move(m),
std::string{reinterpret_cast<const char*>(payload.data()), payload.size()},
std::move(hop));
return;
log::debug(logcat, "We are terminal hop for path request!");
return handle_inner_request(std::move(m), std::move(payload), std::move(hop));
}

auto hop_is_rx = hop->rxid() == hopid;
auto hop_is_rx = hop->rxid() == hop_id;

const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid();
const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream();

std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload);
std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload));

send_control_message(
next_router,
"path_control"s,
"path_control",
std::move(new_payload),
[hop_weak = hop->weak_from_this(), hopid, prev_message = std::move(m)](
[hop_weak = hop->weak_from_this(), hop_id, prev_message = std::move(m)](
oxen::quic::message response) mutable {
auto hop = hop_weak.lock();

if (not hop)
return;
{
log::warning(logcat, "Received response to path control message with non-existant TransitHop!");
return prev_message.respond(messages::ERROR_RESPONSE, true);
}

if (response.timed_out)
log::debug(logcat, "Path control message timed out!");
{
log::info(logcat, "Path control message returned as time out!");
return prev_message.respond(messages::TIMEOUT_RESPONSE, true);
}

ustring hop_id, nonce, payload;
HopID hop_id;
SymmNonce nonce;
std::string payload;

try
{
oxenc::bt_dict_consumer btdc{response.body()};
std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(btdc);
std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{response.body()});
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
return;
return prev_message.respond(messages::ERROR_RESPONSE, true);
;
}

auto symmnonce = SymmNonce{nonce.data()};
auto resp_payload = ONION::serialize_hop(hop_id, symmnonce, payload);
auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload));
prev_message.respond(std::move(resp_payload), false);
});
}

void LinkManager::handle_path_data_message(bstring message)
{
HopID hop_id;
std::string payload;
SymmNonce nonce;

try
{
std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{message});
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
return;
}

auto hop = _router.path_context()->get_transit_hop(hop_id);

if (not hop)
{
log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id);
return;
}

nonce = crypto::onion(
reinterpret_cast<unsigned char*>(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR);

// if terminal hop, pass to the correct path expecting to receive this message
if (hop->terminal_hop)
{
NetworkAddress sender;
bstring data;

try
{
oxenc::bt_dict_consumer btdc{payload};
std::tie(sender, data) = PATH::DATA::deserialize(btdc);

if (auto session = _router.session_endpoint()->get_session(sender))
{
session->recv_path_data_message(std::move(data));
}
else
{
log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender);
}
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
}
}
else
{
// if not terminal hop, relay datagram onwards
auto hop_is_rx = hop->rxid() == hop_id;

const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid();
const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream();

std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload));

send_data_message(next_router, std::move(new_payload));
}
}

void LinkManager::handle_inner_request(
oxen::quic::message m, std::string payload, std::shared_ptr<path::TransitHop> hop)
{
std::string endpoint, body;

try
{
oxenc::bt_dict_consumer btdc{payload};
std::tie(endpoint, body) = PATH::CONTROL::deserialize(btdc);
std::tie(endpoint, body) = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{payload});
}
catch (const std::exception& e)
{
Expand All @@ -1446,10 +1460,12 @@ namespace llarp

if (itr == path_requests.end())
{
log::info(logcat, "Received path control request \"{}\", which has no handler.", endpoint);
log::warning(logcat, "Received path control request `{}`, which has no handler.", endpoint);
return;
}

log::debug(logcat, "Received path control request `{}`", endpoint);

auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable {
auto hop = hop_weak.lock();
if (not hop)
Expand Down
2 changes: 1 addition & 1 deletion llarp/link/link_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ namespace llarp
void handle_convo_intro(oxen::quic::message);

// These requests come over a path (as a "path_control" request),
// may or may not need to make a request to another relay,
// we may or may not need to make a request to another relay,
// then respond (onioned) back along the path.
std::unordered_map<
std::string_view,
Expand Down
Loading

0 comments on commit f8d625b

Please sign in to comment.