lokinet/llarp/link/server.hpp
Thomas Winget 4c630e0437 Large collection of changes to make android work
- Previous android java and jni code updated to work, but with much love
  still needed to make it work nicely, e.g. handling when the VPN is
  turned off.

- DNS handling refactored to allow android to intercept and handle DNS
  requests as we can't set the system DNS to use a high port
  (and apparently Chrome ignores system DNS settings anyway)

- add packet router structure to allow separate handling of specific
  intercepted traffic, e.g. UDP traffic to port 53 gets handled by our
  DNS handler rather than being naively forwarded as exit traffic.

- For now, android lokinet is exit-only and hard-coded to use exit.loki
  as its exit.  The exit will be configurable before release, but
  allowing to not use exit-only mode is more of a challenge.

- some old gitignore remnants which were matching to things we don't
  want them to (and are no longer relevant) removed

- some minor changes to CI configuration
2021-03-02 13:18:22 -05:00

287 lines
7.9 KiB
C++

#ifndef LLARP_LINK_SERVER_HPP
#define LLARP_LINK_SERVER_HPP
#include <crypto/types.hpp>
#include <ev/ev.h>
#include <link/session.hpp>
#include <net/sock_addr.hpp>
#include <router_contact.hpp>
#include <util/status.hpp>
#include <util/thread/logic.hpp>
#include <util/thread/threading.hpp>
#include <config/key_manager.hpp>
#include <list>
#include <memory>
#include <unordered_map>
namespace llarp
{
/// handle a link layer message. this allows for the message to be handled by "upper layers"
///
/// currently called from iwp::Session when messages are sent or received.
using LinkMessageHandler = std::function<bool(ILinkSession*, const llarp_buffer_t&)>;
/// sign a buffer with identity key. this function should take the given `llarp_buffer_t` and
/// sign it, prividing the signature in the out variable `Signature&`.
///
/// currently called from iwp::Session for signing LIMs (link introduction messages)
using SignBufferFunc = std::function<bool(Signature&, const llarp_buffer_t&)>;
/// handle connection timeout
///
/// currently called from ILinkLayer::Pump() when an unestablished session times out
using TimeoutHandler = std::function<void(ILinkSession*)>;
/// get our RC
///
/// currently called by iwp::Session to include as part of a LIM (link introduction message)
using GetRCFunc = std::function<const llarp::RouterContact&(void)>;
/// handler of session established
/// return false to reject
/// return true to accept
///
/// currently called in iwp::Session when a valid LIM is received.
using SessionEstablishedHandler = std::function<bool(ILinkSession*, bool)>;
/// f(new, old)
/// handler of session renegotiation
/// returns true if the new rc is valid
/// returns false otherwise and the session is terminated
///
/// currently called from iwp::Session when we receive a renegotiation LIM
using SessionRenegotiateHandler = std::function<bool(llarp::RouterContact, llarp::RouterContact)>;
/// handles close of all sessions with pubkey
///
/// Note that this handler is called while m_AuthedLinksMutex is held
///
/// currently called from iwp::ILinkSession when a previously established session times out
using SessionClosedHandler = std::function<void(llarp::RouterID)>;
/// notifies router that a link session has ended its pump and we should flush
/// messages to upper layers
///
/// currently called at the end of every iwp::Session::Pump() call
using PumpDoneHandler = std::function<void(void)>;
using Work_t = std::function<void(void)>;
/// queue work to worker thread
using WorkerFunc_t = std::function<void(Work_t)>;
/// before connection hook, called before we try connecting via outbound link
using BeforeConnectFunc_t = std::function<void(llarp::RouterContact)>;
struct ILinkLayer
{
ILinkLayer(
std::shared_ptr<KeyManager> keyManager,
GetRCFunc getrc,
LinkMessageHandler handler,
SignBufferFunc signFunc,
BeforeConnectFunc_t before,
SessionEstablishedHandler sessionEstablish,
SessionRenegotiateHandler renegotiate,
TimeoutHandler timeout,
SessionClosedHandler closed,
PumpDoneHandler pumpDone,
WorkerFunc_t doWork);
virtual ~ILinkLayer();
/// get current time via event loop
llarp_time_t
Now() const
{
return llarp_ev_loop_time_now_ms(m_Loop);
}
bool
HasSessionTo(const RouterID& pk);
void
ForEachSession(std::function<void(const ILinkSession*)> visit, bool randomize = false) const
EXCLUDES(m_AuthedLinksMutex);
void
ForEachSession(std::function<void(ILinkSession*)> visit) EXCLUDES(m_AuthedLinksMutex);
static void
udp_tick(llarp_udp_io* udp);
void
SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt)
{
llarp_ev_udp_sendto(&m_udp, to, pkt);
}
virtual bool
Configure(llarp_ev_loop_ptr loop, const std::string& ifname, int af, uint16_t port);
virtual std::shared_ptr<ILinkSession>
NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0;
/// fetch a session by the identity pubkey it claims
std::shared_ptr<ILinkSession>
FindSessionByPubkey(RouterID pk);
virtual void
Pump();
virtual void
RecvFrom(const SockAddr& from, ILinkSession::Packet_t pkt) = 0;
bool
PickAddress(const RouterContact& rc, AddressInfo& picked) const;
bool
TryEstablishTo(RouterContact rc);
bool
Start(std::shared_ptr<llarp::Logic> l);
virtual void
Stop();
virtual const char*
Name() const = 0;
util::StatusObject
ExtractStatus() const EXCLUDES(m_AuthedLinksMutex);
void
CloseSessionTo(const RouterID& remote);
void
KeepAliveSessionTo(const RouterID& remote);
virtual bool
SendTo(
const RouterID& remote,
const llarp_buffer_t& buf,
ILinkSession::CompletionHandler completed);
virtual bool
GetOurAddressInfo(AddressInfo& addr) const;
bool
VisitSessionByPubkey(const RouterID& pk, std::function<bool(ILinkSession*)> visit)
EXCLUDES(m_AuthedLinksMutex);
virtual uint16_t
Rank() const = 0;
const byte_t*
TransportPubKey() const;
const SecretKey&
RouterEncryptionSecret() const
{
return m_RouterEncSecret;
}
const SecretKey&
TransportSecretKey() const;
bool
IsCompatable(const llarp::RouterContact& other) const
{
const std::string us = Name();
for (const auto& ai : other.addrs)
if (ai.dialect == us)
return true;
return false;
}
virtual bool
MapAddr(const RouterID& pk, ILinkSession* s);
void
Tick(llarp_time_t now);
LinkMessageHandler HandleMessage;
TimeoutHandler HandleTimeout;
SignBufferFunc Sign;
GetRCFunc GetOurRC;
BeforeConnectFunc_t BeforeConnect;
SessionEstablishedHandler SessionEstablished;
SessionClosedHandler SessionClosed;
SessionRenegotiateHandler SessionRenegotiate;
PumpDoneHandler PumpDone;
std::shared_ptr<KeyManager> keyManager;
WorkerFunc_t QueueWork;
std::shared_ptr<Logic>
logic()
{
return m_Logic;
}
bool
operator<(const ILinkLayer& other) const
{
return Rank() < other.Rank() || Name() < other.Name() || m_ourAddr < other.m_ourAddr;
}
/// called by link session to remove a pending session who is timed out
// void
// RemovePending(ILinkSession* s) EXCLUDES(m_PendingMutex);
/// count the number of sessions that are yet to be fully connected
size_t
NumberOfPendingSessions() const
{
Lock_t lock(m_PendingMutex);
return m_Pending.size();
}
int
GetUDPSocket() const
{
return m_udp.fd;
}
private:
void
OnTick();
void
ScheduleTick(llarp_time_t interval);
uint32_t tick_id;
const SecretKey& m_RouterEncSecret;
protected:
#ifdef TRACY_ENABLE
using Lock_t = std::lock_guard<LockableBase(std::mutex)>;
using Mutex_t = std::mutex;
#else
using Lock_t = util::NullLock;
using Mutex_t = util::NullMutex;
#endif
bool
PutSession(const std::shared_ptr<ILinkSession>& s);
std::shared_ptr<llarp::Logic> m_Logic = nullptr;
llarp_ev_loop_ptr m_Loop;
SockAddr m_ourAddr;
llarp_udp_io m_udp;
SecretKey m_SecretKey;
using AuthedLinks =
std::unordered_multimap<RouterID, std::shared_ptr<ILinkSession>, RouterID::Hash>;
using Pending =
std::unordered_multimap<SockAddr, std::shared_ptr<ILinkSession>, SockAddr::Hash>;
mutable DECLARE_LOCK(Mutex_t, m_AuthedLinksMutex, ACQUIRED_BEFORE(m_PendingMutex));
AuthedLinks m_AuthedLinks GUARDED_BY(m_AuthedLinksMutex);
mutable DECLARE_LOCK(Mutex_t, m_PendingMutex, ACQUIRED_AFTER(m_AuthedLinksMutex));
Pending m_Pending GUARDED_BY(m_PendingMutex);
std::unordered_map<SockAddr, llarp_time_t, SockAddr::Hash> m_RecentlyClosed;
};
using LinkLayer_ptr = std::shared_ptr<ILinkLayer>;
} // namespace llarp
#endif