mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
flow layer wireup.
This commit is contained in:
parent
852d57169b
commit
fe9766f26e
21 changed files with 462 additions and 93 deletions
|
@ -21,8 +21,8 @@ namespace llarp::layers::flow
|
|||
decode_addr(std::string_view str)
|
||||
{
|
||||
llarp::AlignedBuffer<32>::Data data{};
|
||||
if (auto sz = oxenc::to_base32z_size(str.size()); sz != data.size())
|
||||
throw std::invalid_argument{"data decode size {} != {}"_format(sz, data.size())};
|
||||
if (auto sz = oxenc::to_base32z_size(data.size()); sz != str.size())
|
||||
throw std::invalid_argument{"data decode size {} != {}"_format(sz, str.size())};
|
||||
oxenc::from_base32z(str.begin(), str.end(), data.begin());
|
||||
return data;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace llarp::layers::flow
|
|||
{}
|
||||
|
||||
FlowAddr::FlowAddr(EndpointBase::AddressVariant_t addr)
|
||||
: FlowAddr{var::visit([](auto&& a) { return a.ToString(); }, addr)}
|
||||
: FlowAddr{var::visit([](auto&& a) -> std::string { return a.ToString(); }, addr)}
|
||||
{}
|
||||
|
||||
std::string
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <optional>
|
||||
namespace llarp::layers::flow
|
||||
{
|
||||
static auto logcat = log::Cat("flow-layer");
|
||||
|
||||
FlowEstablish::FlowEstablish(
|
||||
std::function<void(std::optional<FlowInfo>, std::string)> completiton_handler,
|
||||
|
@ -12,10 +13,10 @@ namespace llarp::layers::flow
|
|||
{}
|
||||
|
||||
void
|
||||
FlowEstablish::fail(std::string name)
|
||||
FlowEstablish::fail(std::string info)
|
||||
{
|
||||
_result = std::nullopt;
|
||||
enter_phase(FlowAuthPhase::auth_nack, std::move(name));
|
||||
enter_phase(FlowAuthPhase::auth_nack, std::move(info));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
#include "flow_identity.hpp"
|
||||
|
||||
#include <oxenc/bt_serialize.h>
|
||||
#include <chrono>
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/router/abstractrouter.hpp>
|
||||
#include <llarp/service/endpoint.hpp>
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <variant>
|
||||
|
||||
namespace llarp::layers::flow
|
||||
{
|
||||
|
||||
static auto logcat = log::Cat("flow-layer");
|
||||
|
||||
FlowIdentityPrivateKeys
|
||||
FlowIdentityPrivateKeys::keygen()
|
||||
{
|
||||
|
@ -41,14 +47,11 @@ namespace llarp::layers::flow
|
|||
}
|
||||
|
||||
FlowIdentity::FlowIdentity(
|
||||
FlowLayer& parent,
|
||||
FlowAddr remote_addr,
|
||||
FlowTag flow_tag_,
|
||||
const FlowIdentityPrivateKeys& privkeys)
|
||||
FlowLayer& parent, FlowAddr remote_addr, const FlowIdentityPrivateKeys& privkeys)
|
||||
: _parent{parent}
|
||||
, _local_privkeys{privkeys}
|
||||
, _state{}
|
||||
, flow_info{privkeys.public_addr(), std::move(remote_addr), std::move(flow_tag_)}
|
||||
, _state{nullptr}
|
||||
, _flow_info{privkeys.public_addr(), std::move(remote_addr), FlowTag{}}
|
||||
{}
|
||||
|
||||
bool
|
||||
|
@ -74,33 +77,88 @@ namespace llarp::layers::flow
|
|||
}
|
||||
}
|
||||
|
||||
struct deprecated_path_ensure_handler
|
||||
service::ProtocolType
|
||||
to_proto_type(const FlowDataKind& kind)
|
||||
{
|
||||
FlowEstablish handshaker;
|
||||
FlowInfo flow_info;
|
||||
|
||||
void
|
||||
operator()(std::optional<service::ConvoTag> maybe_tag)
|
||||
switch (kind)
|
||||
{
|
||||
if (not maybe_tag)
|
||||
{
|
||||
handshaker.fail("cannot establish flow");
|
||||
return;
|
||||
}
|
||||
|
||||
handshaker.ready(flow_info);
|
||||
case FlowDataKind::exit_ip_unicast:
|
||||
return service::ProtocolType::Exit;
|
||||
case FlowDataKind::direct_ip_unicast:
|
||||
// todo: change to direct after we swap to new
|
||||
// route layer.
|
||||
return service::ProtocolType::TrafficV4;
|
||||
case FlowDataKind::stream_unicast:
|
||||
return service::ProtocolType::QUIC;
|
||||
case FlowDataKind::auth:
|
||||
return service::ProtocolType::Auth;
|
||||
default:
|
||||
return service::ProtocolType::Control;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
struct deprecated_path_ensure_handler
|
||||
{
|
||||
FlowIdentity& flow;
|
||||
FlowEstablish handshaker;
|
||||
|
||||
void
|
||||
operator()(std::optional<service::ConvoTag> maybe_tag)
|
||||
{
|
||||
if (not maybe_tag)
|
||||
{
|
||||
log::warning(logcat, "flow establish to {} failed", flow.flow_info.dst);
|
||||
handshaker.fail("cannot establish flow");
|
||||
return;
|
||||
}
|
||||
|
||||
flow._flow_info.tag = FlowTag{maybe_tag->as_array()};
|
||||
log::debug(logcat, "flow established: {}", flow.flow_info);
|
||||
handshaker.ready(flow.flow_info);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
FlowIdentity::async_ensure_flow(FlowEstablish handshaker)
|
||||
{
|
||||
handshaker.fail("not wired up");
|
||||
const auto& ep = _parent.local_deprecated_loki_endpoint();
|
||||
if (not ep)
|
||||
{
|
||||
log::error(logcat, "no deprecated endpoint");
|
||||
handshaker.fail("no deprecated endpoint");
|
||||
return;
|
||||
}
|
||||
|
||||
_parent.wakeup_send->Trigger();
|
||||
auto timeout = ep->PathAlignmentTimeout();
|
||||
|
||||
log::info(logcat, "ensure flow to {}", flow_info.dst);
|
||||
|
||||
ep->MarkAddressOutbound(to_addr_variant(flow_info.dst));
|
||||
|
||||
auto ok = ep->EnsurePathTo(
|
||||
to_addr_variant(flow_info.dst), deprecated_path_ensure_handler{*this, handshaker}, timeout);
|
||||
if (ok)
|
||||
return;
|
||||
|
||||
log::info(
|
||||
logcat,
|
||||
"failed to establish flow to {}: llarp::service::EnsurePathTo() failed",
|
||||
flow_info.dst);
|
||||
handshaker.fail("service::EnsurePathTo() failed");
|
||||
}
|
||||
|
||||
void
|
||||
FlowIdentity::send_to_remote(std::vector<byte_t>, FlowDataKind)
|
||||
{}
|
||||
FlowIdentity::send_to_remote(std::vector<byte_t> data, FlowDataKind kind)
|
||||
{
|
||||
_parent.wakeup_send->Trigger();
|
||||
auto sz = data.size();
|
||||
log::trace(logcat, "send {} bytes of {} on {}", sz, kind, flow_info);
|
||||
auto ok = _parent.local_deprecated_loki_endpoint()->send_to_or_queue(
|
||||
to_addr_variant(flow_info.dst), std::move(data), to_proto_type(kind));
|
||||
if (not ok)
|
||||
log::warning(logcat, "failed to send {} bytes of {} on {}", sz, kind, flow_info);
|
||||
}
|
||||
|
||||
} // namespace llarp::layers::flow
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace llarp::layers::flow
|
|||
mutable dht::Key_t _derived_pubkey;
|
||||
};
|
||||
|
||||
struct deprecated_path_ensure_handler;
|
||||
|
||||
/// the local end of a one to one flow to a remote given a flow isolation metric (flow_tag)
|
||||
/// flows do not change their source/destination address or their flow tag/convo tag.
|
||||
/// note: historically path handovers were allowed, but going forward this is discontinued.
|
||||
|
@ -54,23 +56,23 @@ namespace llarp::layers::flow
|
|||
{
|
||||
FlowLayer& _parent;
|
||||
const FlowIdentityPrivateKeys& _local_privkeys;
|
||||
|
||||
/// internal state holder.
|
||||
/// effectively a pimpl to abstract away .loki vs .snode codepaths.
|
||||
std::unique_ptr<FlowState_Base> _state;
|
||||
|
||||
protected:
|
||||
friend struct deprecated_path_ensure_handler;
|
||||
FlowInfo _flow_info;
|
||||
|
||||
public:
|
||||
/// holds the local/remote flow layer address and any flow isolation metric
|
||||
const FlowInfo flow_info;
|
||||
const FlowInfo& flow_info{_flow_info};
|
||||
|
||||
FlowIdentity(const FlowIdentity&) = delete;
|
||||
FlowIdentity(FlowIdentity&&) = delete;
|
||||
|
||||
FlowIdentity(
|
||||
FlowLayer& parent,
|
||||
FlowAddr remote_addr,
|
||||
FlowTag flow_tag,
|
||||
const FlowIdentityPrivateKeys& local_keys);
|
||||
FlowLayer& parent, FlowAddr remote_addr, const FlowIdentityPrivateKeys& local_keys);
|
||||
|
||||
/// ensure we have a flow to the remote endpoint.
|
||||
/// pass in a handshaker to do any additional steps after establishment.
|
||||
|
|
|
@ -13,4 +13,10 @@ namespace llarp::layers::flow
|
|||
{
|
||||
return fmt::format("[flow src={} dst={} tag={} mtu={}]", src, dst, tag, int{mtu});
|
||||
}
|
||||
|
||||
service::ConvoTag
|
||||
FlowInfo::convo_tag() const
|
||||
{
|
||||
return service::ConvoTag{tag.as_array()};
|
||||
}
|
||||
} // namespace llarp::layers::flow
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "flow_tag.hpp"
|
||||
#include "flow_constants.hpp"
|
||||
|
||||
#include <llarp/service/convotag.hpp>
|
||||
|
||||
namespace llarp::layers::flow
|
||||
{
|
||||
|
||||
|
@ -24,6 +26,9 @@ namespace llarp::layers::flow
|
|||
std::string
|
||||
ToString() const;
|
||||
|
||||
service::ConvoTag
|
||||
convo_tag() const;
|
||||
|
||||
bool
|
||||
operator==(const FlowInfo& other) const;
|
||||
};
|
||||
|
|
|
@ -66,12 +66,13 @@ namespace llarp::layers::flow
|
|||
/// cycle.
|
||||
struct flow_layer_waker
|
||||
{
|
||||
path::PathContext& paths;
|
||||
FlowLayer& flow_layer;
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
flow_layer.local_deprecated_loki_endpoint()->Pump(time_now_ms());
|
||||
// take the things we need to send out on paths and send them out.
|
||||
paths.PumpUpstream();
|
||||
flow_layer.router.pathContext().PumpUpstream();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -80,7 +81,7 @@ namespace llarp::layers::flow
|
|||
, _privkeys{FlowIdentityPrivateKeys::keygen()}
|
||||
, _name_cache{}
|
||||
, _deprecated_endpoint{std::make_shared<service::Endpoint>(r)}
|
||||
, _wakeup_send{r.loop()->make_waker(flow_layer_waker{r.pathContext()})}
|
||||
, _wakeup_send{r.loop()->make_waker(flow_layer_waker{*this})}
|
||||
, _wakeup_recv{r.loop()->make_waker(platform_layer_waker{*this})}
|
||||
, name_resolver{_name_cache, *this}
|
||||
, router{r}
|
||||
|
@ -118,12 +119,26 @@ namespace llarp::layers::flow
|
|||
log::info(logcat, "flow layer up");
|
||||
}
|
||||
|
||||
void
|
||||
FlowLayer::tick()
|
||||
{
|
||||
if (_deprecated_endpoint)
|
||||
{
|
||||
log::trace(logcat, "tick");
|
||||
_deprecated_endpoint->Tick(router.Now());
|
||||
}
|
||||
log::trace(logcat, "ticked");
|
||||
}
|
||||
|
||||
void
|
||||
FlowLayer::stop()
|
||||
{
|
||||
log::info(logcat, "flow layer stopping");
|
||||
if (not _deprecated_endpoint->Stop())
|
||||
throw std::runtime_error{"deprecated endpoint did not stop"};
|
||||
if (_deprecated_endpoint)
|
||||
{
|
||||
if (not _deprecated_endpoint->Stop())
|
||||
throw std::runtime_error{"deprecated endpoint did not stop"};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -202,12 +217,11 @@ namespace llarp::layers::flow
|
|||
std::shared_ptr<FlowIdentity>
|
||||
FlowLayer::flow_to(const FlowAddr& addr)
|
||||
{
|
||||
for (auto& local_flow : _local_flows)
|
||||
for (const auto& local_flow : _local_flows)
|
||||
{
|
||||
if (local_flow->flow_info.dst == addr)
|
||||
return local_flow;
|
||||
}
|
||||
return _local_flows.emplace_back(
|
||||
std::make_shared<FlowIdentity>(*this, addr, unique_flow_tag(), _privkeys));
|
||||
return _local_flows.emplace_back(std::make_shared<FlowIdentity>(*this, addr, _privkeys));
|
||||
}
|
||||
} // namespace llarp::layers::flow
|
||||
|
|
|
@ -104,6 +104,9 @@ namespace llarp::layers::flow
|
|||
void
|
||||
stop();
|
||||
|
||||
void
|
||||
tick();
|
||||
|
||||
NameResolver name_resolver;
|
||||
|
||||
AbstractRouter& router;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
namespace llarp::layers::flow
|
||||
{
|
||||
|
||||
static auto logcat = log::Cat("flow-layer");
|
||||
|
||||
NameResolver::NameResolver(NameCache& name_cache, FlowLayer& parent)
|
||||
: _name_cache{name_cache}, _parent{parent}
|
||||
{}
|
||||
|
@ -18,7 +20,7 @@ namespace llarp::layers::flow
|
|||
std::string name, std::function<void(std::optional<FlowAddr>)> result_handler)
|
||||
{
|
||||
_parent.local_deprecated_loki_endpoint()->LookupNameAsync(
|
||||
name, [result_handler = std::move(result_handler)](auto maybe_addr) {
|
||||
name, [result_handler = std::move(result_handler), name](auto maybe_addr) {
|
||||
if (not maybe_addr)
|
||||
{
|
||||
result_handler(std::nullopt);
|
||||
|
|
|
@ -43,4 +43,23 @@ namespace llarp::layers
|
|||
flow->stop();
|
||||
onion->stop();
|
||||
}
|
||||
|
||||
Layers::~Layers()
|
||||
{
|
||||
if (platform)
|
||||
platform->stop();
|
||||
if (flow)
|
||||
flow->stop();
|
||||
if (onion)
|
||||
onion->stop();
|
||||
}
|
||||
|
||||
util::StatusObject
|
||||
Layers::deprecated_status() const
|
||||
{
|
||||
util::StatusObject obj{};
|
||||
obj["exitMap"] = platform->addr_mapper.exit_map().ExtractStatus();
|
||||
|
||||
return obj;
|
||||
}
|
||||
} // namespace llarp::layers
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
#include <llarp/layers/flow/flow_layer.hpp>
|
||||
#include <llarp/layers/route/route_layer.hpp>
|
||||
#include <llarp/layers/onion/onion_layer.hpp>
|
||||
#include <llarp/util/status.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
// forward declare
|
||||
|
@ -34,6 +37,12 @@ namespace llarp::layers
|
|||
|
||||
void
|
||||
stop_all() const;
|
||||
|
||||
~Layers();
|
||||
|
||||
/// dump debug status.
|
||||
util::StatusObject
|
||||
deprecated_status() const;
|
||||
};
|
||||
|
||||
/// this lets us hide which implementation we are using durring the refactor
|
||||
|
|
|
@ -7,16 +7,12 @@
|
|||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <llarp/layers/flow/flow_layer.hpp>
|
||||
#include "llarp/layers/flow/flow_addr.hpp"
|
||||
#include "llarp/layers/flow/flow_info.hpp"
|
||||
#include "llarp/layers/platform/platform_addr.hpp"
|
||||
#include "llarp/layers/platform/platform_layer.hpp"
|
||||
#include "llarp/net/ip_range.hpp"
|
||||
#include "llarp/net/net_int.hpp"
|
||||
|
||||
namespace llarp::layers::platform
|
||||
{
|
||||
|
||||
static auto logcat = log::Cat("platform-layer");
|
||||
|
||||
AddressMapping&
|
||||
AddressMappingEntry::access()
|
||||
{
|
||||
|
@ -52,6 +48,18 @@ namespace llarp::layers::platform
|
|||
return std::find(owned_ranges.begin(), owned_ranges.end(), range) != std::end(owned_ranges);
|
||||
}
|
||||
|
||||
bool
|
||||
AddressMappingEntry::routes_addr(const PlatformAddr& dst) const
|
||||
{
|
||||
for (const auto& range : _entry.owned_ranges)
|
||||
{
|
||||
log::trace(logcat, "check range {} owns {}", range, dst);
|
||||
if (range.Contains(dst.ip))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string
|
||||
AddressMapping::ToString() const
|
||||
{
|
||||
|
@ -129,7 +137,8 @@ namespace llarp::layers::platform
|
|||
{
|
||||
for (auto& ent : _addrs)
|
||||
{
|
||||
if (ent.has_addr(src, dst))
|
||||
log::trace(logcat, "check {}", ent.view());
|
||||
if (ent.has_addr(src, dst) or ent.routes_addr(dst))
|
||||
return ent.access();
|
||||
}
|
||||
return std::nullopt;
|
||||
|
@ -140,7 +149,7 @@ namespace llarp::layers::platform
|
|||
{
|
||||
std::vector<AddressMapping> exits;
|
||||
view_all_entries([&exits](const auto& ent) {
|
||||
if (not ent.owned_ranges.empty())
|
||||
if (ent.is_exit())
|
||||
exits.emplace_back(ent);
|
||||
return true;
|
||||
});
|
||||
|
@ -233,6 +242,12 @@ namespace llarp::layers::platform
|
|||
return mappings;
|
||||
}
|
||||
|
||||
bool
|
||||
AddressMapping::is_exit() const
|
||||
{
|
||||
return not owned_ranges.empty();
|
||||
}
|
||||
|
||||
} // namespace llarp::layers::platform
|
||||
|
||||
namespace llarp
|
||||
|
|
|
@ -33,6 +33,9 @@ namespace llarp::layers::platform
|
|||
|
||||
std::string
|
||||
ToString() const;
|
||||
|
||||
bool
|
||||
is_exit() const;
|
||||
};
|
||||
|
||||
/// container that holds an addressmapping and extra metadata we need in the addrmapper.
|
||||
|
@ -48,6 +51,10 @@ namespace llarp::layers::platform
|
|||
bool
|
||||
has_addr(const PlatformAddr& src, const PlatformAddr& dst) const;
|
||||
|
||||
/// return true if we can route to this destination address.
|
||||
bool
|
||||
routes_addr(const PlatformAddr& dst) const;
|
||||
|
||||
/// return true if this entry is for this flow info.
|
||||
bool
|
||||
has_flow_info(const flow::FlowInfo& flow_info) const;
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#include "platform_layer.hpp"
|
||||
#include "dns_bridge.hpp"
|
||||
#include "llarp/layers/flow/flow_addr.hpp"
|
||||
#include "llarp/layers/platform/addr_mapper.hpp"
|
||||
#include "llarp/layers/platform/platform_addr.hpp"
|
||||
#include "llarp/net/ip_packet.hpp"
|
||||
#include "llarp/net/ip_range.hpp"
|
||||
#include "oxen/log.hpp"
|
||||
|
||||
#include <llarp/config/config.hpp>
|
||||
#include <llarp/ev/ev.hpp>
|
||||
|
@ -22,6 +18,8 @@
|
|||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp::layers::platform
|
||||
|
@ -83,8 +81,9 @@ namespace llarp::layers::platform
|
|||
OSTraffic_IO_Base::attach(
|
||||
std::shared_ptr<vpn::NetworkInterface> netif, std::shared_ptr<EventLoopWakeup> wakeup_recv)
|
||||
{
|
||||
log::debug(logcat, "attach OSTraffic_IO_Base to {}", netif->Info().ifname);
|
||||
_netif = std::move(netif);
|
||||
|
||||
log::debug(logcat, "attach OSTraffic_IO_Base to {}", _netif->Info().ifname);
|
||||
_our_addr = PlatformAddr{_netif->Info().addrs[0].range.addr};
|
||||
|
||||
// set up event loop reader.
|
||||
|
@ -278,6 +277,82 @@ namespace llarp::layers::platform
|
|||
, addr_mapper{_netconf.ifaddr(router.Net())}
|
||||
{}
|
||||
|
||||
/// a functor that will try to map exits that are not currently mapped.
|
||||
struct map_initial_exits : std::enable_shared_from_this<map_initial_exits>
|
||||
{
|
||||
PlatformLayer& plat;
|
||||
|
||||
net::IPRangeMap<std::string> exits;
|
||||
std::unordered_map<std::string, service::AuthInfo> auths;
|
||||
|
||||
std::unordered_set<std::string> pending;
|
||||
|
||||
explicit map_initial_exits(PlatformLayer& _plat)
|
||||
: plat{_plat}, exits{_plat._netconf.m_LNSExitMap}, auths{_plat._netconf.m_LNSExitAuths}
|
||||
|
||||
{
|
||||
const auto& netconf = _plat._netconf;
|
||||
|
||||
for (const auto& [addr, auth] : netconf.m_ExitAuths)
|
||||
auths[fmt::format("{}", addr)] = auth;
|
||||
|
||||
netconf.m_ExitMap.ForEachEntry([this](const auto& range, const auto& addr) {
|
||||
exits.Insert(range, fmt::format("{}", addr));
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
operator()()
|
||||
{
|
||||
if (exits.Empty() and pending.empty())
|
||||
{
|
||||
// die if we have nothing left to do.
|
||||
_self.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
exits.ForEachEntry([this](const auto& range, const auto& exit) {
|
||||
const auto& auth = auths[exit];
|
||||
auto [itr, inserted] = pending.emplace(exit);
|
||||
if (inserted)
|
||||
{
|
||||
log::info(logcat, "map {} via {}", range, exit);
|
||||
plat.map_exit(
|
||||
exit,
|
||||
auth.token,
|
||||
std::vector{range},
|
||||
[this, exit = exit, range = range](bool ok, auto msg) {
|
||||
on_result(ok, msg, exit, range);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
keep_alive()
|
||||
{
|
||||
_self = shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
on_result(bool ok, std::string msg, std::string exit, IPRange range)
|
||||
{
|
||||
pending.erase(exit);
|
||||
if (ok)
|
||||
{
|
||||
log::info(logcat, "got exit from {}: {}", exit, msg);
|
||||
|
||||
exits.RemoveIf([entry = std::make_pair(range, exit)](auto itr) { return itr == entry; });
|
||||
}
|
||||
else
|
||||
log::info(logcat, "failed to map exit {}: {}", exit, msg);
|
||||
}
|
||||
|
||||
/// a copy of itself, cleared to destroy itself.
|
||||
std::shared_ptr<map_initial_exits> _self;
|
||||
};
|
||||
|
||||
void
|
||||
PlatformLayer::start()
|
||||
{
|
||||
|
@ -303,6 +378,10 @@ namespace llarp::layers::platform
|
|||
// attach vpn interface to dns and start it.
|
||||
if (const auto& dns = _router.get_dns())
|
||||
dns->Start(netif->Info().index);
|
||||
|
||||
auto mapper = std::make_shared<map_initial_exits>(*this);
|
||||
_router.loop()->call_every(500ms, mapper, *mapper);
|
||||
mapper->keep_alive();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -310,7 +389,8 @@ namespace llarp::layers::platform
|
|||
{
|
||||
log::info(logcat, "stop");
|
||||
// stop all io operations on our end and detach from event loop.
|
||||
_io->detach();
|
||||
if (_io)
|
||||
_io->detach();
|
||||
}
|
||||
|
||||
/// handles when we have established a flow with a remote.
|
||||
|
@ -323,7 +403,11 @@ namespace llarp::layers::platform
|
|||
void
|
||||
fail(std::string error_reason) const
|
||||
{
|
||||
result_handler(std::nullopt, "could not obtain flow to '{}': {}"_format(name, error_reason));
|
||||
std::string msg{"could not obtain flow to '{}': {}"_format(name, error_reason)};
|
||||
log::info(logcat, msg);
|
||||
mapper.remove_if_mapping(
|
||||
[this](const auto& other) { return entry.src == other.src and entry.dst == other.dst; });
|
||||
result_handler(std::nullopt, msg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -331,7 +415,7 @@ namespace llarp::layers::platform
|
|||
{
|
||||
entry.flow_info = flow_info;
|
||||
mapper.put(std::move(entry));
|
||||
|
||||
log::info(logcat, "flow established on: {}", flow_info);
|
||||
result_handler(flow_info, "");
|
||||
}
|
||||
|
||||
|
@ -358,9 +442,12 @@ namespace llarp::layers::platform
|
|||
{
|
||||
if (not maybe_addr)
|
||||
{
|
||||
flow_establisher.fail("failed to resolve name");
|
||||
std::string msg{"failed to resolve name '{}'"_format(name)};
|
||||
log::info(logcat, msg);
|
||||
flow_establisher.fail(msg);
|
||||
return;
|
||||
}
|
||||
log::info(logcat, "resolved {} to {}", name, *maybe_addr);
|
||||
// get a flow tag for this remote.
|
||||
flow_layer.flow_to(*maybe_addr)->async_ensure_flow(std::move(flow_establisher));
|
||||
}
|
||||
|
@ -379,13 +466,12 @@ namespace llarp::layers::platform
|
|||
result_handler(std::nullopt, "address map full");
|
||||
return;
|
||||
}
|
||||
// reserve a mapping.
|
||||
AddressMapping mapping = addr_mapper.allocate_mapping(src.value_or(_io->our_platform_addr()));
|
||||
// reserve a mapping. dst is set even if it is an exit.
|
||||
auto& mapping = addr_mapper.allocate_mapping(src);
|
||||
mapping.owned_ranges = std::move(dst_ranges);
|
||||
|
||||
// call this when we got a flow to the guy
|
||||
// it will wire up the mapping.
|
||||
got_flow_handler got_flow{addr_mapper, std::move(mapping), name, std::move(result_handler)};
|
||||
// call this when we got a flow to the remote.
|
||||
got_flow_handler got_flow{addr_mapper, mapping, name, std::move(result_handler)};
|
||||
|
||||
// do any extra handshaking with a flow handshaker, then call the got flow handler
|
||||
// todo: this really belongs in flow layer.
|
||||
|
@ -422,19 +508,21 @@ namespace llarp::layers::platform
|
|||
struct map_exit_handler
|
||||
{
|
||||
AbstractRouter& router;
|
||||
|
||||
std::function<void(bool, std::string)> result_handler;
|
||||
void
|
||||
operator()(std::optional<flow::FlowInfo> found, std::string msg) const
|
||||
{
|
||||
if (found)
|
||||
{
|
||||
// found the result, put firewall up.
|
||||
log::info(logcat, "got exit {}: '{}'", found->dst, msg);
|
||||
// found the result, put firewallup.
|
||||
if (const auto& poker = router.routePoker())
|
||||
poker->Up();
|
||||
result_handler(true, std::move(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
log::info(logcat, "exit not made: {}", msg);
|
||||
result_handler(false, std::move(msg));
|
||||
}
|
||||
};
|
||||
|
@ -446,6 +534,8 @@ namespace llarp::layers::platform
|
|||
std::vector<IPRange> ranges,
|
||||
std::function<void(bool, std::string)> result_handler)
|
||||
{
|
||||
log::info(logcat, "map exit {}", name);
|
||||
|
||||
map_remote(
|
||||
std::move(name),
|
||||
std::move(auth),
|
||||
|
@ -457,6 +547,7 @@ namespace llarp::layers::platform
|
|||
void
|
||||
PlatformLayer::unmap_all_exits_on_range(IPRange range)
|
||||
{
|
||||
log::info(logcat, "unmap all on {}", range);
|
||||
addr_mapper.remove_if_mapping(
|
||||
[range](const auto& mapping) -> bool { return mapping.owns_range(range); });
|
||||
}
|
||||
|
@ -464,6 +555,12 @@ namespace llarp::layers::platform
|
|||
void
|
||||
PlatformLayer::unmap_exit(flow::FlowAddr addr, std::optional<IPRange> range)
|
||||
{
|
||||
std::optional<std::string> range_str;
|
||||
if (range)
|
||||
range_str = range->ToString();
|
||||
|
||||
log::info(logcat, "unmap {} via {}", addr, range_str.value_or("all"));
|
||||
|
||||
addr_mapper.remove_if_mapping([addr, range](const auto& mapping) -> bool {
|
||||
return mapping.flow_info and mapping.flow_info->dst == addr
|
||||
and (range ? mapping.owns_range(*range) : true);
|
||||
|
@ -473,7 +570,13 @@ namespace llarp::layers::platform
|
|||
PlatformStats
|
||||
PlatformLayer::current_stats() const
|
||||
{
|
||||
return PlatformStats{};
|
||||
PlatformStats st{};
|
||||
addr_mapper.view_all_entries([&](const auto& ent) {
|
||||
st.addrs.emplace_back(ent, _flow_layer);
|
||||
return true;
|
||||
});
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
DNSZone&
|
||||
|
|
|
@ -111,12 +111,14 @@ namespace llarp::layers::platform
|
|||
};
|
||||
|
||||
struct platform_io_wakeup_handler;
|
||||
struct map_initial_exits;
|
||||
|
||||
/// responsible for bridging the os and the flow layer.
|
||||
class PlatformLayer
|
||||
{
|
||||
protected:
|
||||
friend struct platform_io_wakeup_handler;
|
||||
friend struct map_initial_exits;
|
||||
|
||||
AbstractRouter& _router;
|
||||
flow::FlowLayer& _flow_layer;
|
||||
|
|
|
@ -1,4 +1,46 @@
|
|||
#include "platform_stats.hpp"
|
||||
#include "addr_mapper.hpp"
|
||||
#include "llarp/layers/flow/flow_layer.hpp"
|
||||
#include "platform_layer.hpp"
|
||||
|
||||
namespace llarp::layers::platform
|
||||
{}
|
||||
{
|
||||
|
||||
/// return true if we want to use an exit.
|
||||
bool
|
||||
PlatformStats::wants_client_exit() const
|
||||
{
|
||||
for (const auto& addr : addrs)
|
||||
{
|
||||
if (addr.is_exit())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// return true if we want an exit and have one ready.
|
||||
bool
|
||||
PlatformStats::client_exit_ready() const
|
||||
{
|
||||
for (const auto& addr : addrs)
|
||||
{
|
||||
if (addr.is_exit() and addr.is_ready())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace stats
|
||||
{
|
||||
AddrInfo::AddrInfo(const AddressMapping& ent, const flow::FlowLayer& flow)
|
||||
: addr{ent}, _flags{0}
|
||||
{
|
||||
if (ent.is_exit())
|
||||
_flags |= _mask_exit;
|
||||
|
||||
if (ent.flow_info and flow.has_flow(*ent.flow_info))
|
||||
_flags |= _mask_ready;
|
||||
}
|
||||
} // namespace stats
|
||||
|
||||
} // namespace llarp::layers::platform
|
||||
|
|
|
@ -1,12 +1,81 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <llarp/layers/flow/flow_addr.hpp>
|
||||
#include <llarp/net/ip_range_map.hpp>
|
||||
|
||||
#include "addr_mapper.hpp"
|
||||
#include "platform_addr.hpp"
|
||||
|
||||
namespace llarp::layers::flow
|
||||
{
|
||||
class FlowLayer;
|
||||
}
|
||||
|
||||
namespace llarp::layers::platform
|
||||
{
|
||||
|
||||
namespace stats
|
||||
{
|
||||
|
||||
struct AddrInfo
|
||||
{
|
||||
AddressMapping addr;
|
||||
|
||||
AddrInfo(const AddressMapping& ent, const flow::FlowLayer& flow_layer);
|
||||
|
||||
constexpr bool
|
||||
is_exit() const
|
||||
{
|
||||
return flag(_mask_exit);
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
is_ready() const
|
||||
{
|
||||
return flag(_mask_ready) and is_authenticated();
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
is_authenticated() const
|
||||
{
|
||||
if (not flag(_mask_auth_required))
|
||||
return true;
|
||||
return flag(_mask_auth_ok);
|
||||
}
|
||||
|
||||
private:
|
||||
/// the underlying flow is ready to do io
|
||||
static inline constexpr auto _mask_ready{1 << 0};
|
||||
/// we are required to do auth with this remote.
|
||||
static inline constexpr auto _mask_auth_required{1 << 1};
|
||||
static inline constexpr auto _mask_auth_ok{1 << 2};
|
||||
static inline constexpr auto _mask_inbound{1 << 3};
|
||||
static inline constexpr auto _mask_exit{1 << 4};
|
||||
|
||||
constexpr bool
|
||||
flag(int mask) const
|
||||
{
|
||||
return _flags & mask;
|
||||
}
|
||||
|
||||
int _flags{};
|
||||
};
|
||||
} // namespace stats
|
||||
|
||||
struct PlatformStats
|
||||
{};
|
||||
{
|
||||
/// flow addr / platform addr mappings that we have allocated.
|
||||
std::vector<stats::AddrInfo> addrs;
|
||||
|
||||
/// return true if we want to use an exit.
|
||||
bool
|
||||
wants_client_exit() const;
|
||||
|
||||
/// return true if we want an exit and have one ready.
|
||||
bool
|
||||
client_exit_ready() const;
|
||||
};
|
||||
} // namespace llarp::layers::platform
|
||||
|
|
|
@ -327,6 +327,8 @@ namespace llarp
|
|||
return false;
|
||||
if (BuildCooldownHit(now))
|
||||
return false;
|
||||
if (m_router->NumberOfConnectedRouters() == 0)
|
||||
return false;
|
||||
return PathSet::ShouldBuildMore(now);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,11 +107,15 @@ namespace llarp
|
|||
if (not _running)
|
||||
util::StatusObject{{"running", false}};
|
||||
|
||||
auto services = json::object();
|
||||
|
||||
services["default"] = get_layers()->deprecated_status();
|
||||
|
||||
return util::StatusObject{
|
||||
{"running", true},
|
||||
{"numNodesKnown", _nodedb->NumLoaded()},
|
||||
{"dht", _dht->impl->ExtractStatus()},
|
||||
{"services", json::object()},
|
||||
{"services", std::move(services)},
|
||||
{"exit", json::object()},
|
||||
{"links", _linkManager.ExtractStatus()},
|
||||
{"outboundMessages", _outboundMessageHandler.ExtractStatus()}};
|
||||
|
|
|
@ -100,10 +100,13 @@ namespace llarp
|
|||
const auto itr = conf.m_LNSExitAuths.find(name);
|
||||
if (itr != conf.m_LNSExitAuths.end())
|
||||
auth = itr->second;
|
||||
LogInfo("map ", range, " to ", name);
|
||||
m_StartupLNSMappings[name] = std::make_pair(range, auth);
|
||||
});
|
||||
|
||||
return m_state->Configure(conf);
|
||||
if (not m_state->Configure(conf))
|
||||
return false;
|
||||
return LoadKeyFile();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -440,21 +443,22 @@ namespace llarp
|
|||
{
|
||||
for (const auto& item : m_StartupLNSMappings)
|
||||
{
|
||||
LogInfo("look up ", item.first, " as exit");
|
||||
LookupNameAsync(
|
||||
item.first, [name = item.first, info = item.second, this](auto maybe_addr) {
|
||||
if (maybe_addr.has_value())
|
||||
{
|
||||
const auto maybe_range = info.first;
|
||||
const auto maybe_auth = info.second;
|
||||
if (not maybe_addr)
|
||||
return;
|
||||
const auto maybe_range = info.first;
|
||||
const auto maybe_auth = info.second;
|
||||
|
||||
m_StartupLNSMappings.erase(name);
|
||||
if (auto* addr = std::get_if<service::Address>(&*maybe_addr))
|
||||
{
|
||||
if (maybe_range.has_value())
|
||||
m_ExitMap.Insert(*maybe_range, *addr);
|
||||
if (maybe_auth.has_value())
|
||||
SetAuthInfoForEndpoint(*addr, *maybe_auth);
|
||||
}
|
||||
m_StartupLNSMappings.erase(name);
|
||||
if (auto* addr = std::get_if<service::Address>(&*maybe_addr))
|
||||
{
|
||||
LogInfo(name, " resolved to ", addr->ToString());
|
||||
if (maybe_range)
|
||||
m_ExitMap.Insert(*maybe_range, *addr);
|
||||
if (maybe_auth)
|
||||
SetAuthInfoForEndpoint(*addr, *maybe_auth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1030,7 +1034,7 @@ namespace llarp
|
|||
{
|
||||
for (const auto& [name, info] : m_StartupLNSMappings)
|
||||
{
|
||||
if (info.first.has_value())
|
||||
if (info.first)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace llarp::service
|
|||
Exit = 3UL,
|
||||
Auth = 4UL,
|
||||
QUIC = 5UL,
|
||||
DirectTraffic = 6UL,
|
||||
|
||||
};
|
||||
|
||||
|
@ -24,13 +25,14 @@ namespace llarp::service
|
|||
ToString(ProtocolType t)
|
||||
{
|
||||
using namespace std::literals;
|
||||
return t == ProtocolType::Control ? "Control"sv
|
||||
: t == ProtocolType::TrafficV4 ? "TrafficV4"sv
|
||||
: t == ProtocolType::TrafficV6 ? "TrafficV6"sv
|
||||
: t == ProtocolType::Exit ? "Exit"sv
|
||||
: t == ProtocolType::Auth ? "Auth"sv
|
||||
: t == ProtocolType::QUIC ? "QUIC"sv
|
||||
: "(unknown-protocol-type)"sv;
|
||||
return t == ProtocolType::Control ? "Control"sv
|
||||
: t == ProtocolType::DirectTraffic ? "Traffic"sv
|
||||
: t == ProtocolType::TrafficV4 ? "TrafficV4"sv
|
||||
: t == ProtocolType::TrafficV6 ? "TrafficV6"sv
|
||||
: t == ProtocolType::Exit ? "Exit"sv
|
||||
: t == ProtocolType::Auth ? "Auth"sv
|
||||
: t == ProtocolType::QUIC ? "QUIC"sv
|
||||
: "(unknown-protocol-type)"sv;
|
||||
}
|
||||
|
||||
} // namespace llarp::service
|
||||
|
|
Loading…
Reference in a new issue