|
|
|
@ -7,6 +7,7 @@
|
|
|
|
|
#include <llarp/messages/exit.hpp>
|
|
|
|
|
#include <llarp/messages/path.hpp>
|
|
|
|
|
#include <llarp/nodedb.hpp>
|
|
|
|
|
#include <llarp/path/path.hpp>
|
|
|
|
|
#include <llarp/router/rc_lookup_handler.hpp>
|
|
|
|
|
#include <llarp/router/router.hpp>
|
|
|
|
|
|
|
|
|
@ -123,6 +124,8 @@ namespace llarp
|
|
|
|
|
|
|
|
|
|
} // namespace link
|
|
|
|
|
|
|
|
|
|
using messages::serialize_response;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::for_each_connection(std::function<void(link::Connection&)> func)
|
|
|
|
|
{
|
|
|
|
@ -135,13 +138,31 @@ namespace llarp
|
|
|
|
|
void
|
|
|
|
|
LinkManager::register_commands(std::shared_ptr<oxen::quic::BTRequestStream>& s)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& [name, func] : rpc_commands)
|
|
|
|
|
{
|
|
|
|
|
s->register_command(name, [this, f = func](oxen::quic::message m) {
|
|
|
|
|
_router.loop()->call([this, func = f, msg = std::move(m)]() mutable {
|
|
|
|
|
std::invoke(func, this, std::move(msg));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
assert(ep.connid_map.count(s->conn_id()));
|
|
|
|
|
const RouterID& rid = ep.connid_map[s->conn_id()];
|
|
|
|
|
|
|
|
|
|
s->register_command("path_build"s, [this, rid](oxen::quic::message m) {
|
|
|
|
|
_router.loop()->call(
|
|
|
|
|
[this, &rid, msg = std::move(m)]() mutable { handle_path_build(std::move(msg), rid); });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
s->register_command("path_control"s, [this, rid](oxen::quic::message m) {
|
|
|
|
|
_router.loop()->call(
|
|
|
|
|
[this, &rid, msg = std::move(m)]() mutable { handle_path_control(std::move(msg), rid); });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (auto& method : direct_requests)
|
|
|
|
|
{
|
|
|
|
|
s->register_command(
|
|
|
|
|
std::string{method.first}, [this, func = method.second](oxen::quic::message m) {
|
|
|
|
|
_router.loop()->call([this, msg = std::move(m), func = std::move(func)]() mutable {
|
|
|
|
|
auto body = msg.body_str();
|
|
|
|
|
auto respond = [m = std::move(msg)](std::string response) mutable {
|
|
|
|
|
m.respond(std::move(response));
|
|
|
|
|
};
|
|
|
|
|
std::invoke(func, this, body, std::move(respond));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -194,12 +215,7 @@ namespace llarp
|
|
|
|
|
std::string body,
|
|
|
|
|
std::function<void(oxen::quic::message m)> func)
|
|
|
|
|
{
|
|
|
|
|
if (not func and rpc_responses.count(endpoint))
|
|
|
|
|
{
|
|
|
|
|
func = [&](oxen::quic::message m) {
|
|
|
|
|
std::invoke(rpc_responses[endpoint], this, std::move(m));
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
assert(func); // makes no sense to send control message and ignore response
|
|
|
|
|
|
|
|
|
|
if (func)
|
|
|
|
|
{
|
|
|
|
@ -416,8 +432,6 @@ namespace llarp
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
util::Lock l(m);
|
|
|
|
|
|
|
|
|
|
LogInfo("stopping links");
|
|
|
|
|
is_stopping = true;
|
|
|
|
|
|
|
|
|
@ -430,8 +444,6 @@ namespace llarp
|
|
|
|
|
if (is_stopping)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
util::Lock l(m);
|
|
|
|
|
|
|
|
|
|
persisting_conns[remote] = std::max(until, persisting_conns[remote]);
|
|
|
|
|
if (have_client_connection_to(remote))
|
|
|
|
|
{
|
|
|
|
@ -513,29 +525,30 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_find_name(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_find_name(std::string_view body, std::function<void(std::string)> respond)
|
|
|
|
|
{
|
|
|
|
|
std::string name_hash;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdp{m.body()};
|
|
|
|
|
oxenc::bt_dict_consumer btdp{body};
|
|
|
|
|
|
|
|
|
|
name_hash = btdp.require<std::string>("H");
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", FindNameMessage::EXCEPTION}}), true);
|
|
|
|
|
respond(messages::ERROR_RESPONSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_router.rpc_client()->lookup_ons_hash(
|
|
|
|
|
name_hash,
|
|
|
|
|
[msg = std::move(m)]([[maybe_unused]] std::optional<service::EncryptedName> maybe) mutable {
|
|
|
|
|
[respond = std::move(respond)](
|
|
|
|
|
[[maybe_unused]] std::optional<service::EncryptedName> maybe) mutable {
|
|
|
|
|
if (maybe)
|
|
|
|
|
msg.respond(serialize_response({{"NAME", maybe->ciphertext}}));
|
|
|
|
|
respond(serialize_response({{"NAME", maybe->ciphertext}}));
|
|
|
|
|
else
|
|
|
|
|
msg.respond(serialize_response({{"STATUS", FindNameMessage::NOT_FOUND}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, FindNameMessage::NOT_FOUND}}));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -553,7 +566,7 @@ namespace llarp
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
payload = btdc.require<std::string>(m ? "NAME" : "STATUS");
|
|
|
|
|
payload = btdc.require<std::string>(m ? "NAME" : messages::STATUS_KEY);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
@ -567,7 +580,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (payload == FindNameMessage::EXCEPTION)
|
|
|
|
|
if (payload == "ERROR")
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "FindNameMessage failed with unkown error!");
|
|
|
|
|
|
|
|
|
@ -583,17 +596,15 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: add callback to relayed messages (calls to send_control_message so the
|
|
|
|
|
// response finds its way back)
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_find_router(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_find_router(std::string_view body, std::function<void(std::string)> respond)
|
|
|
|
|
{
|
|
|
|
|
std::string target_key;
|
|
|
|
|
bool is_exploratory, is_iterative;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
oxenc::bt_dict_consumer btdc{body};
|
|
|
|
|
|
|
|
|
|
is_exploratory = btdc.require<bool>("E");
|
|
|
|
|
is_iterative = btdc.require<bool>("I");
|
|
|
|
@ -602,8 +613,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{"STATUS", FindRouterMessage::EXCEPTION}, {"TARGET", ""}}), true);
|
|
|
|
|
respond(messages::ERROR_RESPONSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -633,9 +643,8 @@ namespace llarp
|
|
|
|
|
neighbors += rid.bt_encode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{"STATUS", FindRouterMessage::RETRY_EXP}, {"TARGET", neighbors}}),
|
|
|
|
|
true);
|
|
|
|
|
respond(serialize_response(
|
|
|
|
|
{{messages::STATUS_KEY, FindRouterMessage::RETRY_EXP}, {"TARGET", neighbors}}));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -651,13 +660,13 @@ namespace llarp
|
|
|
|
|
target_rid,
|
|
|
|
|
"find_router",
|
|
|
|
|
FindRouterMessage::serialize(target_rid, false, false),
|
|
|
|
|
[original = std::move(m)](oxen::quic::message msg) mutable {
|
|
|
|
|
original.respond(msg.body_str(), not msg);
|
|
|
|
|
[respond = std::move(respond)](oxen::quic::message msg) mutable {
|
|
|
|
|
respond(msg.body_str());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m.respond(serialize_response({{"RC", closest_rc.view()}}));
|
|
|
|
|
respond(serialize_response({{"RC", closest_rc.view()}}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (not is_iterative)
|
|
|
|
@ -668,26 +677,22 @@ namespace llarp
|
|
|
|
|
closest_rid,
|
|
|
|
|
"find_router",
|
|
|
|
|
FindRouterMessage::serialize(closest_rid, false, false),
|
|
|
|
|
[original = std::move(m)](oxen::quic::message msg) mutable {
|
|
|
|
|
original.respond(msg.body_str(), not msg);
|
|
|
|
|
[respond = std::move(respond)](oxen::quic::message msg) mutable {
|
|
|
|
|
respond(msg.body_str());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response(
|
|
|
|
|
{{"STATUS", FindRouterMessage::RETRY_ITER},
|
|
|
|
|
{"TARGET", reinterpret_cast<const char*>(target_addr.data())}}),
|
|
|
|
|
true);
|
|
|
|
|
respond(serialize_response(
|
|
|
|
|
{{messages::STATUS_KEY, FindRouterMessage::RETRY_ITER},
|
|
|
|
|
{"TARGET", reinterpret_cast<const char*>(target_addr.data())}}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response(
|
|
|
|
|
{{"STATUS", FindRouterMessage::RETRY_NEW},
|
|
|
|
|
{"TARGET", reinterpret_cast<const char*>(closest_rid.data())}}),
|
|
|
|
|
true);
|
|
|
|
|
respond(serialize_response(
|
|
|
|
|
{{messages::STATUS_KEY, FindRouterMessage::RETRY_NEW},
|
|
|
|
|
{"TARGET", reinterpret_cast<const char*>(closest_rid.data())}}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -727,7 +732,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (status == FindRouterMessage::EXCEPTION)
|
|
|
|
|
if (status == "ERROR")
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "FindRouterMessage failed with remote exception!");
|
|
|
|
|
// Do something smart here probably
|
|
|
|
@ -781,7 +786,7 @@ namespace llarp
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status == FindRouterMessage::EXCEPTION)
|
|
|
|
|
if (status == "ERROR")
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "FindRouterMessage failed with remote exception!");
|
|
|
|
|
// Do something smart here probably
|
|
|
|
@ -811,7 +816,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_publish_intro(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_publish_intro(std::string_view body, std::function<void(std::string)> respond)
|
|
|
|
|
{
|
|
|
|
|
std::string introset, derived_signing_key, payload, sig, nonce;
|
|
|
|
|
uint64_t is_relayed, relay_order;
|
|
|
|
@ -819,7 +824,7 @@ namespace llarp
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc_a{m.body()};
|
|
|
|
|
oxenc::bt_dict_consumer btdc_a{body};
|
|
|
|
|
|
|
|
|
|
introset = btdc_a.require<std::string>("I");
|
|
|
|
|
relay_order = btdc_a.require<uint64_t>("O");
|
|
|
|
@ -836,7 +841,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PublishIntroMessage::EXCEPTION}}), true);
|
|
|
|
|
respond(messages::ERROR_RESPONSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -847,14 +852,14 @@ namespace llarp
|
|
|
|
|
if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig))
|
|
|
|
|
{
|
|
|
|
|
log::error(link_cat, "Received PublishIntroMessage with invalid introset: {}", introset);
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PublishIntroMessage::INVALID_INTROSET}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INVALID_INTROSET}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (now + service::MAX_INTROSET_TIME_DELTA > signed_at + path::DEFAULT_LIFETIME)
|
|
|
|
|
{
|
|
|
|
|
log::error(link_cat, "Received PublishIntroMessage with expired introset: {}", introset);
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PublishIntroMessage::EXPIRED}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::EXPIRED}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -864,7 +869,7 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
log::error(
|
|
|
|
|
link_cat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PublishIntroMessage::INSUFFICIENT}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INSUFFICIENT}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -876,7 +881,7 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
log::error(
|
|
|
|
|
link_cat, "Received PublishIntroMessage with invalide relay order: {}", relay_order);
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PublishIntroMessage::INVALID_ORDER}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INVALID_ORDER}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -893,7 +898,7 @@ namespace llarp
|
|
|
|
|
relay_order);
|
|
|
|
|
|
|
|
|
|
_router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)});
|
|
|
|
|
m.respond(serialize_response({{"STATUS", ""}}));
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, ""}}));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -903,7 +908,12 @@ namespace llarp
|
|
|
|
|
send_control_message(
|
|
|
|
|
peer_key,
|
|
|
|
|
"publish_intro",
|
|
|
|
|
PublishIntroMessage::serialize(introset, relay_order, is_relayed));
|
|
|
|
|
PublishIntroMessage::serialize(introset, relay_order, is_relayed),
|
|
|
|
|
[respond = std::move(respond)](oxen::quic::message m) {
|
|
|
|
|
if (m.timed_out)
|
|
|
|
|
return; // drop if timed out; requester will have timed out as well
|
|
|
|
|
respond(m.body_str());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
@ -926,7 +936,7 @@ namespace llarp
|
|
|
|
|
log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}");
|
|
|
|
|
|
|
|
|
|
_router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)});
|
|
|
|
|
m.respond(serialize_response());
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, ""}}));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
log::warning(
|
|
|
|
@ -949,7 +959,7 @@ namespace llarp
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
payload = btdc.require<std::string>("STATUS");
|
|
|
|
|
payload = btdc.require<std::string>(messages::STATUS_KEY);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
@ -963,7 +973,7 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (payload == PublishIntroMessage::EXCEPTION)
|
|
|
|
|
if (payload == "ERROR")
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "PublishIntroMessage failed with remote exception!");
|
|
|
|
|
// Do something smart here probably
|
|
|
|
@ -984,14 +994,14 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_find_intro(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_find_intro(std::string_view body, std::function<void(std::string)> respond)
|
|
|
|
|
{
|
|
|
|
|
ustring location;
|
|
|
|
|
uint64_t relay_order, is_relayed;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
oxenc::bt_dict_consumer btdc{body};
|
|
|
|
|
|
|
|
|
|
relay_order = btdc.require<uint64_t>("O");
|
|
|
|
|
is_relayed = btdc.require<uint64_t>("R");
|
|
|
|
@ -1000,7 +1010,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", FindIntroMessage::EXCEPTION}}), true);
|
|
|
|
|
respond(messages::ERROR_RESPONSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1012,7 +1022,7 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
log::warning(
|
|
|
|
|
link_cat, "Received FindIntroMessage with invalid relay order: {}", relay_order);
|
|
|
|
|
m.respond(serialize_response({{"STATUS", FindIntroMessage::INVALID_ORDER}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INVALID_ORDER}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1022,7 +1032,7 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
log::error(
|
|
|
|
|
link_cat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", FindIntroMessage::INSUFFICIENT_NODES}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INSUFFICIENT_NODES}}));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1035,7 +1045,7 @@ namespace llarp
|
|
|
|
|
peer_key,
|
|
|
|
|
"find_intro",
|
|
|
|
|
FindIntroMessage::serialize(dht::Key_t{peer_key}, is_relayed, relay_order),
|
|
|
|
|
[original_msg = std::move(m)](oxen::quic::message relay_response) mutable {
|
|
|
|
|
[respond = std::move(respond)](oxen::quic::message relay_response) mutable {
|
|
|
|
|
if (relay_response)
|
|
|
|
|
log::info(
|
|
|
|
|
link_cat,
|
|
|
|
@ -1048,19 +1058,19 @@ namespace llarp
|
|
|
|
|
log::critical(
|
|
|
|
|
link_cat, "Relayed FindIntroMessage failed! Notifying initial requester");
|
|
|
|
|
|
|
|
|
|
original_msg.respond(relay_response.body_str(), not relay_response);
|
|
|
|
|
respond(relay_response.body_str());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (auto maybe_intro = _router.contacts()->get_introset_by_location(addr))
|
|
|
|
|
m.respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}}));
|
|
|
|
|
respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}}));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log::warning(
|
|
|
|
|
link_cat,
|
|
|
|
|
"Received FindIntroMessage with relayed == false and no local introset entry");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", FindIntroMessage::NOT_FOUND}}), true);
|
|
|
|
|
respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::NOT_FOUND}}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1079,7 +1089,7 @@ namespace llarp
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
payload = btdc.require<std::string>((m) ? "INTROSET" : "STATUS");
|
|
|
|
|
payload = btdc.require<std::string>((m) ? "INTROSET" : messages::STATUS_KEY);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
@ -1101,12 +1111,12 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_path_build(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from)
|
|
|
|
|
{
|
|
|
|
|
if (!_router.path_context().AllowingTransit())
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "got path build request when not permitting transit");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::NO_TRANSIT}}), true);
|
|
|
|
|
m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::NO_TRANSIT}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try
|
|
|
|
@ -1136,7 +1146,8 @@ namespace llarp
|
|
|
|
|
shared.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data()))
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "DH server initialization failed during path build");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1149,14 +1160,16 @@ namespace llarp
|
|
|
|
|
shared))
|
|
|
|
|
{
|
|
|
|
|
log::error(link_cat, "HMAC failed on path build request");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!std::equal(
|
|
|
|
|
digest.begin(), digest.end(), reinterpret_cast<const unsigned char*>(hash.data())))
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "HMAC mismatch on path build request");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1168,7 +1181,8 @@ namespace llarp
|
|
|
|
|
outer_nonce.data()))
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "Decrypt failed on path build request");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1189,17 +1203,14 @@ namespace llarp
|
|
|
|
|
if (frame.empty())
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "Path build request received invalid frame");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_FRAMES}}), true);
|
|
|
|
|
m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_FRAMES}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// populate transit hop object with hop info
|
|
|
|
|
// TODO: how to get downstream hop RouterID from here (all we have is oxen::quic::message)
|
|
|
|
|
// could do message->btstream->stream->connection_interface->connectionid
|
|
|
|
|
// and check our mapping, but that feels ugly as sin (and message->stream is private)
|
|
|
|
|
// TODO: also need downstream for IP / path build limiting clients
|
|
|
|
|
// TODO: IP / path build limiting clients
|
|
|
|
|
auto hop = std::make_shared<path::TransitHop>();
|
|
|
|
|
// hop->info.downstream = m.from(); // TODO: RouterID m.from() or similar
|
|
|
|
|
hop->info.downstream = from;
|
|
|
|
|
|
|
|
|
|
// extract pathIDs and check if zero or used
|
|
|
|
|
auto& hop_info = hop->info;
|
|
|
|
@ -1209,22 +1220,16 @@ namespace llarp
|
|
|
|
|
if (hop_info.txID.IsZero() || hop_info.rxID.IsZero())
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Invalid PathID; PathIDs must be non-zero");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true);
|
|
|
|
|
m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_PATHID}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hop_info.upstream.from_string(upstream);
|
|
|
|
|
|
|
|
|
|
// TODO: need downstream (above), and also the whole transit hop container is garbage.
|
|
|
|
|
// namely the PathID uniqueness checking uses the PathIDs and upstream/downstream
|
|
|
|
|
// but if someone made a path with txid, rxid, and downstream the same but
|
|
|
|
|
// a different upstream, that would be "unique" but we wouldn't know where
|
|
|
|
|
// to route messages (nevermind that messages don't currently know the RouterID
|
|
|
|
|
// they came from).
|
|
|
|
|
if (_router.path_context().HasTransitHop(hop_info))
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Invalid PathID; PathIDs must be unique");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true);
|
|
|
|
|
m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_PATHID}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1232,11 +1237,13 @@ namespace llarp
|
|
|
|
|
hop->pathKey.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data()))
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "DH failed during path build.");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_CRYPTO}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// generate hash of hop key for nonce mutation
|
|
|
|
|
crypto::shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size());
|
|
|
|
|
ShortHash xor_hash;
|
|
|
|
|
crypto::shorthash(xor_hash, hop->pathKey.data(), hop->pathKey.size());
|
|
|
|
|
hop->nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate
|
|
|
|
|
|
|
|
|
|
// set and check path lifetime
|
|
|
|
|
hop->lifetime = 1ms * lifetime;
|
|
|
|
@ -1244,7 +1251,8 @@ namespace llarp
|
|
|
|
|
if (hop->lifetime >= path::DEFAULT_LIFETIME)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Path build attempt with too long of a lifetime.");
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_LIFETIME}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_LIFETIME}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1253,9 +1261,10 @@ namespace llarp
|
|
|
|
|
|
|
|
|
|
if (hop_info.upstream == _router.pubkey())
|
|
|
|
|
{
|
|
|
|
|
hop->terminal_hop = true;
|
|
|
|
|
// we are terminal hop and everything is okay
|
|
|
|
|
_router.path_context().PutTransitHop(hop);
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::OK}}), false);
|
|
|
|
|
m.respond(messages::OK_RESPONSE, false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1287,52 +1296,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", PathBuildMessage::EXCEPTION}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_path_build_response(oxen::quic::message m)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
// m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_path_confirm(oxen::quic::message m)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_path_confirm_response(oxen::quic::message m)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
// m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1347,7 +1311,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1362,7 +1326,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
// m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
// m.respond(serialize_response({{messages::STATUS_KEY, "EXCEPTION"}}), true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1377,7 +1341,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1392,7 +1356,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1416,8 +1380,8 @@ namespace llarp
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
|
|
|
|
|
RouterID target{pubkey.data()};
|
|
|
|
|
auto transit_hop = std::static_pointer_cast<path::TransitHop>(
|
|
|
|
|
_router.path_context().GetByUpstream(target, PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto transit_hop =
|
|
|
|
|
_router.path_context().GetTransitHop(target, PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
const auto rx_id = transit_hop->info.rxID;
|
|
|
|
|
|
|
|
|
@ -1431,7 +1395,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", ObtainExitMessage::EXCEPTION}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1461,8 +1425,7 @@ namespace llarp
|
|
|
|
|
sig = to_usv(btlc.consume_string_view());
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
|
|
|
|
|
auto path_ptr = std::static_pointer_cast<path::Path>(
|
|
|
|
|
_router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig))
|
|
|
|
|
path_ptr->enable_exit_traffic();
|
|
|
|
@ -1490,8 +1453,8 @@ namespace llarp
|
|
|
|
|
path_id = btdc.require<std::string_view>("P");
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
|
|
|
|
|
auto transit_hop = std::static_pointer_cast<path::TransitHop>(
|
|
|
|
|
_router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto transit_hop =
|
|
|
|
|
_router.path_context().GetTransitHop(_router.pubkey(), PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
if (auto exit_ep =
|
|
|
|
|
_router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()}))
|
|
|
|
@ -1500,7 +1463,9 @@ namespace llarp
|
|
|
|
|
{
|
|
|
|
|
(exit_ep->UpdateLocalPath(transit_hop->info.rxID))
|
|
|
|
|
? m.respond(UpdateExitMessage::sign_and_serialize_response(_router.identity(), tx_id))
|
|
|
|
|
: m.respond(serialize_response({{"STATUS", UpdateExitMessage::UPDATE_FAILED}}), true);
|
|
|
|
|
: m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, UpdateExitMessage::UPDATE_FAILED}}),
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
// If we fail to verify the message, no-op
|
|
|
|
|
}
|
|
|
|
@ -1508,7 +1473,7 @@ namespace llarp
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", UpdateExitMessage::EXCEPTION}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1538,8 +1503,7 @@ namespace llarp
|
|
|
|
|
sig = to_usv(btlc.consume_string_view());
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
|
|
|
|
|
auto path_ptr = std::static_pointer_cast<path::Path>(
|
|
|
|
|
_router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig))
|
|
|
|
|
{
|
|
|
|
@ -1574,8 +1538,8 @@ namespace llarp
|
|
|
|
|
sig = to_usv(btlc.consume_string_view());
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
|
|
|
|
|
auto transit_hop = std::static_pointer_cast<path::TransitHop>(
|
|
|
|
|
_router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto transit_hop =
|
|
|
|
|
_router.path_context().GetTransitHop(_router.pubkey(), PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
const auto rx_id = transit_hop->info.rxID;
|
|
|
|
|
|
|
|
|
@ -1588,12 +1552,13 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.respond(serialize_response({{"STATUS", CloseExitMessage::UPDATE_FAILED}}), true);
|
|
|
|
|
m.respond(
|
|
|
|
|
serialize_response({{messages::STATUS_KEY, CloseExitMessage::UPDATE_FAILED}}), true);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
|
m.respond(serialize_response({{"STATUS", CloseExitMessage::EXCEPTION}}), true);
|
|
|
|
|
m.respond(messages::ERROR_RESPONSE, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1624,8 +1589,7 @@ namespace llarp
|
|
|
|
|
tx_id = btdc.require<std::string_view>("T");
|
|
|
|
|
nonce = btdc.require<std::string_view>("Y");
|
|
|
|
|
|
|
|
|
|
auto path_ptr = std::static_pointer_cast<path::Path>(
|
|
|
|
|
_router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()}));
|
|
|
|
|
auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()});
|
|
|
|
|
|
|
|
|
|
if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC)
|
|
|
|
|
and crypto::verify(_router.pubkey(), to_usv(dict_data), sig))
|
|
|
|
@ -1639,16 +1603,51 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_path_control(oxen::quic::message m)
|
|
|
|
|
LinkManager::handle_path_control(oxen::quic::message m, const RouterID& from)
|
|
|
|
|
{
|
|
|
|
|
if (m.timed_out)
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "Path control message timed out!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
oxenc::bt_dict_consumer btdc{m.body()};
|
|
|
|
|
auto nonce = SymmNonce{btdc.require<ustring_view>("NONCE").data()};
|
|
|
|
|
auto path_id_str = btdc.require<ustring_view>("PATHID");
|
|
|
|
|
auto payload = btdc.require<std::string>("PAYLOAD");
|
|
|
|
|
auto path_id = PathID_t{path_id_str.data()};
|
|
|
|
|
auto hop = _router.path_context().GetTransitHop(from, path_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;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{}
|
|
|
|
|
// if terminal hop, payload should contain a request (e.g. "find_router"); handle and respond.
|
|
|
|
|
if (hop->terminal_hop)
|
|
|
|
|
{
|
|
|
|
|
hop->onion(payload, nonce, false);
|
|
|
|
|
handle_inner_request(std::move(m), std::move(payload), std::move(hop));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto next_id = path_id == hop->info.rxID ? hop->info.txID : hop->info.rxID;
|
|
|
|
|
auto next_router = path_id == hop->info.rxID ? hop->info.upstream : hop->info.downstream;
|
|
|
|
|
auto new_payload = hop->onion_and_payload(payload, next_id, nonce);
|
|
|
|
|
send_control_message(
|
|
|
|
|
next_router,
|
|
|
|
|
"path_control"s,
|
|
|
|
|
std::move(new_payload),
|
|
|
|
|
[hop_weak = hop->weak_from_this(), path_id, prev_message = std::move(m)](
|
|
|
|
|
oxen::quic::message response) mutable {
|
|
|
|
|
auto hop = hop_weak.lock();
|
|
|
|
|
if (not hop)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
oxenc::bt_dict_consumer resp_btdc{response.body()};
|
|
|
|
|
auto nonce = SymmNonce{resp_btdc.require<ustring_view>("NONCE").data()};
|
|
|
|
|
auto payload = resp_btdc.require<std::string>("PAYLOAD");
|
|
|
|
|
auto resp_payload = hop->onion_and_payload(payload, path_id, nonce);
|
|
|
|
|
prev_message.respond(std::move(resp_payload), false);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
log::warning(link_cat, "Exception: {}", e.what());
|
|
|
|
@ -1656,6 +1655,34 @@ namespace llarp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_inner_request(
|
|
|
|
|
oxen::quic::message m, std::string payload, std::shared_ptr<path::TransitHop> hop)
|
|
|
|
|
{
|
|
|
|
|
oxenc::bt_dict_consumer btdc{payload};
|
|
|
|
|
auto body = btdc.require<std::string_view>("BODY");
|
|
|
|
|
auto method = btdc.require<std::string_view>("METHOD");
|
|
|
|
|
|
|
|
|
|
// If a handler exists for "method", call it; else drop request on the floor.
|
|
|
|
|
auto itr = path_requests.find(method);
|
|
|
|
|
if (itr == path_requests.end())
|
|
|
|
|
{
|
|
|
|
|
log::info(link_cat, "Received path control request \"{}\", which has no handler.", method);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto respond = [m = std::move(m),
|
|
|
|
|
hop_weak = hop->weak_from_this()](std::string response) mutable {
|
|
|
|
|
auto hop = hop_weak.lock();
|
|
|
|
|
if (not hop)
|
|
|
|
|
return; // transit hop gone, drop response
|
|
|
|
|
|
|
|
|
|
m.respond(hop->onion_and_payload(response, hop->info.rxID), false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::invoke(itr->second, this, std::move(body), std::move(respond));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
LinkManager::handle_convo_intro(oxen::quic::message m)
|
|
|
|
|
{
|
|
|
|
|