Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
path control handling
Browse files Browse the repository at this point in the history
dr7ana committed Oct 28, 2024
1 parent f8d625b commit 2b0f8d3
Showing 14 changed files with 131 additions and 93 deletions.
2 changes: 1 addition & 1 deletion llarp/bootstrap.cpp
Original file line number Diff line number Diff line change
@@ -156,7 +156,7 @@ namespace llarp

if (not fs::exists(fpath))
{
log::critical(logcat, "Bootstrap RC file non-existant at path:{}", fpath);
log::critical(logcat, "Bootstrap RC file non-existent at path:{}", fpath);
return result;
}

2 changes: 1 addition & 1 deletion llarp/contact/client_contact.hpp
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ namespace llarp
};

// TESTNET:
inline static constexpr auto CC_PUBLISH_INTERVAL{1min};
inline static constexpr auto CC_PUBLISH_INTERVAL{30s};

/** ClientContact
On the wire we encode the data as a dict containing:
24 changes: 21 additions & 3 deletions llarp/handlers/session.cpp
Original file line number Diff line number Diff line change
@@ -236,9 +236,9 @@ namespace llarp::handlers
if (auto s = btdc.maybe<std::string>(messages::STATUS_KEY))
status = s;
}
catch (...)
catch (const std::exception& e)
{
log::warning(logcat, "Exception caught parsing 'find_name' response!");
log::warning(logcat, "Exception caught parsing 'find_name' response: {}", e.what());
}

log::warning(logcat, "Call to endpoint 'lookup_name' failed -- status:{}", status.value_or("<none given>"));
@@ -414,7 +414,25 @@ 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, 0, [](std::string response) {
log::info(logcat, "Received response to PublishClientContact...");

std::optional<std::string> status = std::nullopt;
try
{
oxenc::bt_dict_consumer btdc{response};

if (auto s = btdc.maybe<std::string>(messages::STATUS_KEY))
status = s;
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
}

log::warning(
logcat, "Call to PublishClientContact failed -- status:{}", status.value_or("<none given>"));
});
}
}

2 changes: 1 addition & 1 deletion llarp/handlers/tun.cpp
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ namespace llarp::handlers
auto pkt_hook = [this]() {
for (auto pkt = _net_if->read_next_packet(); not pkt.empty(); pkt = _net_if->read_next_packet())
{
log::debug(logcat, "packet router receiving {}", pkt.info_line());
log::trace(logcat, "packet router receiving {}", pkt.info_line());
_packet_router->handle_ip_packet(std::move(pkt));
}
};
23 changes: 16 additions & 7 deletions llarp/link/link_manager.cpp
Original file line number Diff line number Diff line change
@@ -1292,6 +1292,8 @@ namespace llarp

void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */)
{
log::debug(logcat, "{} called", __PRETTY_FUNCTION__);

HopID hop_id;
std::string payload;
SymmNonce nonce;
@@ -1313,12 +1315,20 @@ namespace llarp
// bidirectional, will need to check if we have a Path with path_id.
if (not hop)
{
// if (auto path = _router.path_context()->get_path(hop_id))
// {
// log::info(logcat, "Received path control corresponding to known path!");
// //
// }

log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id);
return m.respond(messages::ERROR_RESPONSE, true);
}

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

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

// if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond.
if (hop->terminal_hop)
@@ -1332,7 +1342,7 @@ namespace llarp
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));
std::string new_payload = ONION::serialize_hop(next_id.to_view(), onion_nonce, std::move(payload));

send_control_message(
next_router,
@@ -1344,7 +1354,7 @@ namespace llarp

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

@@ -1366,7 +1376,6 @@ namespace llarp
{
log::warning(logcat, "Exception: {}", e.what());
return prev_message.respond(messages::ERROR_RESPONSE, true);
;
}

auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload));
@@ -1451,8 +1460,8 @@ namespace llarp
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception: {}", e.what());
return;
log::warning(logcat, "Exception: {}; Payload: {}", e.what(), buffer_printer{payload});
return m.respond(messages::serialize_response({{messages::STATUS_KEY, e.what()}}), true);
}

// If a handler exists for "method", call it; else drop request on the floor.
23 changes: 3 additions & 20 deletions llarp/messages/path.hpp
Original file line number Diff line number Diff line change
@@ -51,29 +51,12 @@ namespace llarp
}
catch (const std::exception& e)
{
throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())};
throw std::runtime_error{"Exception caught deserializing onion data: {}"_format(e.what())};
}

return {std::move(hop_id), std::move(nonce), std::move(payload)};
}

inline static std::tuple<ustring, ustring, ustring> deserialize_hop(oxenc::bt_dict_consumer& btdc)
{
ustring hopid, nonce, payload;

try
{
hopid = btdc.require<ustring>("k");
nonce = btdc.require<ustring>("n");
payload = btdc.require<ustring>("x");
}
catch (const std::exception& e)
{
throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())};
}

return {std::move(hopid), std::move(nonce), std::move(payload)};
}
} // namespace ONION

namespace PATH
@@ -170,7 +153,7 @@ namespace llarp
}
catch (const std::exception& e)
{
log::warning(logcat, "Exception caught deserializing hop dict:{}", e.what());
log::warning(logcat, "Exception caught deserializing hop dict: {}", e.what());
throw;
}

@@ -227,7 +210,7 @@ namespace llarp
}
catch (const std::exception& e)
{
throw std::runtime_error{"Exception caught deserializing path control:{}"_format(e.what())};
throw std::runtime_error{"Exception caught deserializing path control: {}"_format(e.what())};
}

return {std::move(endpoint), std::move(payload)};
78 changes: 44 additions & 34 deletions llarp/path/path.cpp
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@
#include <llarp/router/router.hpp>
#include <llarp/util/buffer.hpp>

#include <ranges>

namespace llarp::path
{
static auto logcat = log::Cat("path");
@@ -19,31 +21,34 @@ namespace llarp::path
bool is_client)
: handler{std::move(_handler)}, _router{rtr}, _is_session_path{is_session}, _is_client{is_client}
{
hops.resize(_hops.size());
size_t hsz = _hops.size();
size_t n_hops = _hops.size();
// transit_hops.resize(n_hops);
hops.resize(n_hops);

for (size_t idx = 0; idx < hsz; ++idx)
for (size_t idx = 0; idx < n_hops; ++idx)
{
// transit_hops[idx]
hops[idx].rc = _hops[idx];
do
{
hops[idx].txID.Randomize();
} while (hops[idx].txID.is_zero());

do
{
hops[idx].rxID.Randomize();
} while (hops[idx].rxID.is_zero());
hops[idx].txID = HopID::make_random();
// transit_hops[idx]._txid = HopID::make_random();
hops[idx].rxID = HopID::make_random();
// transit_hops[idx]._rxid = HopID::make_random();
}

for (size_t idx = 0; idx < hsz - 1; ++idx)
for (size_t idx = 0; idx < n_hops - 1; ++idx)
{
// transit_hops[idx]._txid = transit_hops[idx + 1]._rxid;
hops[idx].txID = hops[idx + 1].rxID;
}

// initialize parts of the clientintro
intro.pivot_rid = hops[hsz - 1].rc.router_id();
intro.pivot_hid = hops[hsz - 1].txID;
// intro.pivot_rid = transit_hops.back().rc.router_id();
// intro.pivot_hid = transit_hops.back()._txid;
intro.pivot_rid = hops.back().rc.router_id();
intro.pivot_hid = hops.back().txID;

log::info(
logcat, "Path client intro holding pivot_rid ({}) and pivot_hid ({})", intro.pivot_rid, intro.pivot_hid);
}

void Path::link_session(recv_session_dgram_cb cb)
@@ -75,8 +80,8 @@ namespace llarp::path

bool Path::operator<(const Path& other) const
{
auto& first_hop = hops[0];
auto& other_first = other.hops[0];
auto& first_hop = hops.front();
auto& other_first = other.hops.front();
return std::tie(first_hop.txID, first_hop.rxID, first_hop.upstream)
< std::tie(other_first.txID, other_first.rxID, other_first.upstream);
}
@@ -148,14 +153,14 @@ namespace llarp::path
{
auto nonce = SymmNonce::make_random();

for (const auto& hop : hops)
for (const auto& hop : std::ranges::reverse_view(hops))
{
nonce = crypto::onion(
reinterpret_cast<unsigned char*>(inner_payload.data()),
inner_payload.size(),
hop.shared,
hop.nonce,
hop.nonce);
nonce,
hop.nonceXOR);
}

return ONION::serialize_hop(upstream_txid().to_view(), nonce, std::move(inner_payload));
@@ -182,7 +187,7 @@ namespace llarp::path
auto self = weak.lock();
if (not self)
{
log::warning(logcat, "Received response to path control message with non-existant path!");
log::warning(logcat, "Received response to path control message with non-existent path!");
return;
}

@@ -193,12 +198,12 @@ namespace llarp::path
return;
}

log::debug(logcat, "Received response to path control message...");
log::debug(logcat, "Received response to path control message: {}", buffer_printer{m.body()});

if (m.timed_out)
if (not m)
{
log::info(logcat, "Path control message returned as time out!");
return response_cb(messages::TIMEOUT_RESPONSE);
log::warning(logcat, "Path control message returned error!");
return response_cb(m.body_str());
}

HopID hop_id;
@@ -211,7 +216,7 @@ namespace llarp::path
}
catch (const std::exception& e)
{
log::warning(logcat, "Error parsing path control message response: {}", e.what());
log::warning(logcat, "Exception parsing path control message response: {}", e.what());
return response_cb(messages::ERROR_RESPONSE);
}

@@ -227,43 +232,48 @@ namespace llarp::path

// TODO: DISCUSS:
// Parsing and handling of the contents (errors, etc.) is the currently responsibility of the callback
response_cb(std::string{reinterpret_cast<const char*>(payload.data()), payload.size()});
response_cb(std::move(payload));
});
}

bool Path::is_ready(std::chrono::milliseconds now) const
{
return _established ? is_expired(now) : false;
return _established ? !is_expired(now) : false;
}

PathHopConfig Path::upstream()
{
return hops.front();
}

RouterID Path::upstream_rid()
{
return hops[0].rc.router_id();
return hops.front().rc.router_id();
}

const RouterID& Path::upstream_rid() const
{
return hops[0].rc.router_id();
return hops.front().rc.router_id();
}

HopID Path::upstream_txid()
{
return hops[0].txID;
return hops.front().txID;
}

const HopID& Path::upstream_txid() const
{
return hops[0].txID;
return hops.front().txID;
}

HopID Path::upstream_rxid()
{
return hops[0].rxID;
return hops.front().rxID;
}

const HopID& Path::upstream_rxid() const
{
return hops[0].rxID;
return hops.front().rxID;
}

RouterID Path::pivot_rid()
10 changes: 7 additions & 3 deletions llarp/path/path.hpp
Original file line number Diff line number Diff line change
@@ -42,6 +42,8 @@ namespace llarp
{
std::vector<PathHopConfig> hops;

// std::vector<TransitHop> transit_hops;

std::weak_ptr<PathHandler> handler;

ClientIntro intro{};
@@ -128,6 +130,8 @@ namespace llarp

bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const;

PathHopConfig upstream();

RouterID upstream_rid();
const RouterID& upstream_rid() const;

@@ -178,9 +182,9 @@ namespace llarp

recv_session_dgram_cb _recv_dgram;

std::chrono::milliseconds last_recv_msg = 0s;
std::chrono::milliseconds last_latency_test = 0s;
uint64_t last_latency_test_id = 0;
std::chrono::milliseconds last_recv_msg{0s};
std::chrono::milliseconds last_latency_test{0s};
uint64_t last_latency_test_id{};
};
} // namespace path
} // namespace llarp
3 changes: 3 additions & 0 deletions llarp/path/path_context.cpp
Original file line number Diff line number Diff line change
@@ -39,6 +39,9 @@ namespace llarp::path
{
Lock_t l{paths_mutex};

// TESTNET: TODO: once PathHopConfig -> TransitHop, remove this association
put_transit_hop(TransitHop::from_hop_config(path->upstream()));

_path_map.emplace(path->upstream_rxid(), path);
_path_map.emplace(path->upstream_txid(), path);

22 changes: 5 additions & 17 deletions llarp/path/path_handler.cpp
Original file line number Diff line number Diff line change
@@ -166,19 +166,6 @@ namespace llarp::path
return selected;
}

size_t PathHandler::paths_at_time(std::chrono::milliseconds futureTime) const
{
size_t num = 0;
Lock_t l{paths_mutex};

for (const auto& item : _paths)
{
if (item.second->is_ready() && !item.second->is_expired(futureTime))
++num;
}
return num;
}

void PathHandler::reset_path_state()
{
build_interval_limit = PATH_BUILD_RATE;
@@ -424,7 +411,6 @@ namespace llarp::path
}

RemoteRC remote_rc;
to_exclude.insert(remote_rc.router_id()); // we will manually add this last

if (const auto maybe = _router.node_db()->get_rc(pivot))
{
@@ -433,6 +419,8 @@ namespace llarp::path
else
return std::nullopt;

to_exclude.insert(remote_rc.router_id()); // we will manually add this last

// leave one extra spot for the terminal node
auto hops_needed = num_hops - hops.size() - 1;

@@ -508,7 +496,7 @@ namespace llarp::path

last_build = llarp::time_now_ms();
const auto& edge = hops[0].router_id();
const auto& terminus = hops.back().router_id();
const auto& pivot = hops.back().router_id();

if (not _router.pathbuild_limiter().Attempt(edge))
{
@@ -519,9 +507,9 @@ namespace llarp::path
{
Lock_t l{paths_mutex};

if (auto [it, b] = _paths.try_emplace(terminus, nullptr); not b)
if (auto [it, b] = _paths.try_emplace(pivot, nullptr); not b)
{
log::warning(logcat, "Pending build to {} already underway... aborting...", terminus);
log::warning(logcat, "Pending build to {} already underway... aborting...", pivot);
return false;
}
}
3 changes: 0 additions & 3 deletions llarp/path/path_handler.hpp
Original file line number Diff line number Diff line change
@@ -184,9 +184,6 @@ namespace llarp
std::optional<std::vector<std::shared_ptr<Path>>> get_n_random_paths_conditional(
size_t n, std::function<bool(std::shared_ptr<Path>)> filter, bool exact = false);

/// count the number of paths that will exist at this timestamp in future
size_t paths_at_time(std::chrono::milliseconds futureTime) const;

virtual void reset_path_state();

/// return true if we hit our soft limit for building paths too fast
7 changes: 7 additions & 0 deletions llarp/path/path_types.hpp
Original file line number Diff line number Diff line change
@@ -11,6 +11,13 @@ namespace llarp
struct HopID final : public AlignedBuffer<PATHIDSIZE>
{
using AlignedBuffer<PATHIDSIZE>::AlignedBuffer;

static HopID make_random()
{
HopID h;
h.Randomize();
return h;
}
};

namespace path
16 changes: 15 additions & 1 deletion llarp/path/transit_hop.cpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,20 @@ namespace llarp::path
{
static auto logcat = log::Cat("transit-hop");

std::shared_ptr<TransitHop> TransitHop::from_hop_config(PathHopConfig hop_config)
{
auto hop = std::make_shared<TransitHop>();

hop->_txid = {hop_config.txID};
hop->_rxid = {hop_config.rxID};
hop->_upstream = {hop_config.upstream};
hop->shared = {hop_config.shared};
hop->nonce = {hop_config.nonce};
hop->nonceXOR = {hop_config.nonceXOR};

return hop;
}

std::shared_ptr<TransitHop> TransitHop::deserialize_hop(
oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret)
{
@@ -33,7 +47,7 @@ namespace llarp::path
if (hop->lifetime > path::DEFAULT_LIFETIME)
throw std::runtime_error{PATH::BUILD::BAD_LIFETIME};

hop->downstream() = src;
hop->_downstream = src;
hop->shared = std::move(secret);

if (r.path_context()->has_transit_hop(hop))
9 changes: 7 additions & 2 deletions llarp/path/transit_hop.hpp
Original file line number Diff line number Diff line change
@@ -10,18 +10,22 @@ namespace llarp
{
struct Router;

/** TODO: combine PathHopConfig into TransitHop
- Add RelayContact
*/

namespace path
{
struct TransitHop : std::enable_shared_from_this<TransitHop>
{
private:
HopID _txid, _rxid;
RouterID _upstream;
RouterID _downstream;

public:
TransitHop() = default;

static std::shared_ptr<TransitHop> from_hop_config(PathHopConfig hop_config);

TransitHop(Router& r, const RouterID& src, ustring symmkey, ustring symmnonce);

// This static factory function is used in path-build logic. The exceptions thrown are the exact response
@@ -30,6 +34,7 @@ namespace llarp
oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret);

SharedSecret shared;
SymmNonce nonce;
SymmNonce nonceXOR;
std::chrono::milliseconds started{0s};
// 10 minutes default

0 comments on commit 2b0f8d3

Please sign in to comment.