42#include "librats/util/rats_export.h"
43#include "librats/transport/connection.h"
44#include "librats/transport/reactor_pool.h"
46#include "librats/peer/peer_table.h"
49#include "librats/security/identity.h"
50#include "librats/security/handshaker.h"
54#include "librats/node/dialer.h"
56#include "librats/node/reflexive_probe.h"
60#include "librats/wire/message_router.h"
63#include <condition_variable>
72#include <unordered_map>
80class RATS_API
Node final :
public ConnectionDelegate,
102 static_assert(std::is_base_of<Subsystem, T>::value,
"T must derive from Subsystem");
104 subsystems_.push_back(std::move(
subsystem));
121 uint16_t
listen_port() const noexcept
override {
return listen_port_; }
126 uint8_t
transports() const noexcept
override {
return transports_; }
129 const std::string&
protocol() const noexcept
override {
return config_.protocol; }
147 void connect(
const std::string& host, uint16_t port);
156 std::vector<PeerInfo>
peers()
const override {
return peers_.snapshot(); }
174 const DialProfile& profile)
override;
179 ConnRole role,
bool connected)
override;
183 ForwardedCircuit circuit)
override;
185 ForwardedCircuit circuit)
override;
188 std::shared_ptr<std::atomic<uint64_t>> bytes,
189 uint64_t rate, uint64_t burst)
override;
193 size_t max_peers() const noexcept {
return max_peers_.load(std::memory_order_relaxed); }
194 void set_max_peers(
size_t n)
noexcept { max_peers_.store(n, std::memory_order_relaxed); }
196 const size_t cap = max_peers_.load(std::memory_order_relaxed);
197 return cap != 0 && peers_.size() >= cap;
282 live_outcome_.emplace_back(type, std::move(cb));
287 std::optional<PathStats>
path_stats(
const PeerId&
id)
const override {
return peers_.path(
id); }
291 void on(std::string_view channel, MessageRouter::Handler cb) { router_.on_channel(channel, std::move(cb)); }
298 for (
auto& s : subsystems_)
if (
auto* p =
dynamic_cast<T*
>(s.get()))
return p;
307 SendOptions options = {})
override;
312 router_.on_type(type, std::move(cb));
319 bool admit_inbound()
override;
320 void on_established(Connection& conn)
override;
321 void on_frame(Connection& conn,
const Frame& frame)
override;
322 void on_closed(Connection& conn, CloseReason reason)
override;
323 void on_writable_changed(Connection& conn,
bool writable)
override;
324 void on_path_sample(Connection& conn,
const PathStats& stats)
override;
325 void on_moved(Connection& conn)
override;
327 void on_dial_aborted(uint8_t reactor_index, ConnId
id,
328 const std::string& host, uint16_t port)
override;
332 bool open_listeners();
334 void report_dial_failed(
const std::string& host, uint16_t port);
336 std::optional<PeerRoute> datagram_route(
const PeerId&
id)
const;
338 Peer make_peer(
const PeerId&
id, PeerRoute route) {
return Peer(
id, route, *
this); }
341 void route_send(PeerRoute route,
FrameHeader header,
Bytes payload, Deadline deadline,
342 uint64_t tag, uint8_t rank, std::shared_ptr<std::atomic<size_t>> owed);
349 size_t send_low_water() const noexcept;
350 void route_close(PeerRoute route);
352 void close_duplicate(PeerRoute route);
355 void take_up(Connection& conn);
360 void hold_standby(const
PeerInfo& info, PeerRoute route);
362 void watch_standby(const
PeerId&
id, uint64_t watch);
365 void check_standby(const
PeerId&
id, uint8_t reactor, uint64_t watch);
368 bool take_over(const
PeerId&
id, PeerRoute from,
bool close_from);
371 void send_identify(Connection& conn);
372 void handle_identify(Connection& conn, const
Frame& frame);
373 std::vector<
Address> advertised_addresses() const;
374 void rebuild_advertised_addresses(const
std::vector<
std::
string>& local_ips);
375 void record_observed_address(const
Address& addr);
378 bool is_own_endpoint(const
Address& addr) const;
380 void start_network_monitor();
381 void stop_network_monitor();
382 void maintenance_loop();
386 std::unique_ptr<SecurityProvider> security_;
388 MessageRouter router_;
391 std::unique_ptr<ReactorPool> reactors_;
392 std::unique_ptr<Dialer> dialer_;
399 std::unique_ptr<NetworkMonitor> monitor_;
400 std::thread maintenance_thread_;
401 std::mutex maintenance_mutex_;
402 std::condition_variable maintenance_cv_;
403 std::vector<
std::
string> pending_addresses_;
404 bool maintenance_pending_ = false;
405 bool maintenance_stop_ = false;
407 socket_t listen_socket_ = RATS_INVALID_SOCKET;
408 socket_t udp_socket_ = RATS_INVALID_SOCKET;
409 uint16_t listen_port_ = 0;
410 uint8_t transports_ = 0;
411 std::atomic<
bool> running_{
false};
412 std::atomic<size_t> max_peers_{0};
414 std::vector<PeerNetwork::PeerEventHandler> peer_connected_;
415 std::vector<PeerNetwork::PeerDisconnectHandler> peer_disconnected_;
416 std::vector<PeerNetwork::DialFailedHandler> dial_failed_;
417 std::vector<PeerNetwork::PeerEventHandler> peer_writable_;
418 std::vector<PeerNetwork::PeerEventHandler> peer_rerouted_;
419 std::vector<PeerNetwork::PeerEventHandler> peer_moved_;
420 std::vector<PeerNetwork::PeerPathHandler> peer_path_;
421 std::vector<std::pair<MessageType, PeerNetwork::LiveOutcomeHandler>> live_outcome_;
428 std::chrono::steady_clock::time_point until;
431 mutable std::mutex standby_mutex_;
432 std::unordered_map<PeerId, Standby, PeerId::Hash> standbys_;
433 uint64_t standby_watches_ = 0;
437 mutable std::mutex ceilings_mutex_;
438 std::unordered_map<PeerId, uint64_t, PeerId::Hash> ceilings_;
441 mutable std::mutex observed_mutex_;
442 std::vector<Address> observed_addresses_;
448 NatStatus nat_status_;
451 ReflexiveProbe reflexive_;
457 mutable std::mutex advertised_mutex_;
458 std::vector<Address> advertised_addresses_;
A dialable transport endpoint: a numeric IP + port.
Turning a relayed byte stream into a peer connection — the capability a relay module needs and PeerNe...
Non-owning view over a contiguous run of bytes.
MessageJson * json() noexcept
The JSON messaging module if one was attached (add_subsystem<MessageJson>), else nullptr.
void wake_circuit(PeerRoute route, uint32_t events) override
Deliver poll-equivalent events (PollIn / PollOut / PollErr, see core/io_poller.h) to a circuit connec...
Node(NodeConfig config)
Construct a node from its configuration (see NodeConfig).
std::optional< PathStats > path_stats(const PeerId &id) const override
The latest path sample for a peer — safe from any thread.
std::vector< Address > observed_addresses() const
Our own addresses as remote peers reported observing us at — their observed IP paired with our listen...
void on_peer_moved(PeerNetwork::PeerEventHandler cb) override
Subscribe to "the path to this peer changed: one end moved" (see PeerNetwork::on_peer_moved).
Node & operator=(const Node &)=delete
ServiceRegistry & services() noexcept
std::optional< PeerRoute > adopt_circuit(const PeerId &carrier, std::unique_ptr< Link > link, ConnRole role, bool connected) override
Adopt link as a connection carried by the peer carrier, on the reactor that owns the carrier's own co...
std::optional< PeerRoute > expect_relayed(const PeerId &carrier, uint64_t cid, ForwardedCircuit circuit) override
Accept the dial that will come through carrier, the relay, as an Inbound connection — under the same ...
void connect(const Address &address) override
Dial a peer.
std::optional< PeerRoute > dial_relayed(const PeerId &carrier, uint64_t cid, ForwardedCircuit circuit) override
Dial the far end through carrier, the relay. The connection is Outbound.
void stop_forwarding(uint64_t cid) override
const std::string & protocol() const noexcept override
Application protocol identity bound into the handshake (see NodeConfig).
std::vector< PeerId > connected_peers() const override
bool peer_writable(const PeerId &id) const override
Whether a peer's send queue has room for more.
bool peer_limit_reached() const noexcept
T * add_subsystem(std::unique_ptr< T > subsystem)
Attach a subsystem (DHT, GossipSub, PingService…).
void on_peer_disconnected(PeerNetwork::PeerDisconnectHandler cb) override
Subscribe to peer-disconnected events. The handler runs on a reactor thread.
void on_peer_connected(PeerNetwork::PeerEventHandler cb) override
Subscribe to peer-connected events. The handler runs on a reactor thread.
void on_dial_failed(PeerNetwork::DialFailedHandler cb) override
Subscribe to failed-outbound-dial events. The handler runs on a reactor thread.
const PeerId & local_id() const noexcept override
Our self-certifying peer identity (the public key peers authenticate).
bool broadcast(std::string_view channel, ByteView payload, SendOptions options={})
Send raw bytes on a named channel to every connected peer.
size_t standbys() const
Links held as standbys now: duplicates the peer table turned down, kept a while in case the one they ...
uint8_t transports() const noexcept override
Transports this node is actually running, as a PeerTransports bitmask.
~Node() override
Stops the node if still running, then releases all resources.
void set_send_ceiling(const PeerId &id, uint64_t bits_per_second) override
Send to id no faster than bits_per_second, whatever its congestion controller paces at; 0 lifts the c...
void on(MessageType type, PeerNetwork::MessageHandler cb) override
void on_peer_rerouted(PeerNetwork::PeerEventHandler cb) override
Subscribe to "this peer's traffic moved to another connection" (see PeerNetwork::on_peer_rerouted).
size_t peer_count() const noexcept
Number of currently-established peers.
uint16_t listen_port() const noexcept override
The bound listen port (the actual port when the config requested 0).
bool start()
Bring the node up: open the listener (if enabled), start the reactor pool, then start every attached ...
Node(const Node &)=delete
void connect(const std::string &host, uint16_t port)
Dial a peer.
EventBus & events() noexcept
void on_with_deadline(MessageType type, PeerNetwork::DeadlineMessageHandler cb) override
on(), with each message's deadline.
bool broadcast(MessageType type, ByteView payload, SendOptions options={}) override
Send to every connected peer.
std::vector< PeerInfo > peers() const override
Snapshot of all established peers (id, addresses, direction, timing).
bool send(const PeerId &to, std::string_view channel, ByteView payload, SendOptions options={})
Send raw bytes to one peer on a named channel.
void close_circuit(PeerRoute route, CloseReason reason) override
Tear a circuit connection down.
void on_peer_path(PeerNetwork::PeerPathHandler cb) override
Subscribe to periodic path samples of every connected peer (see PathStats): the estimate to size a li...
void set_max_peers(size_t n) noexcept
bool dial_direct(const Address &addr, TransportKind kind, const DialProfile &profile) override
Start exactly one dial to addr over kind, bypassing the transport race.
void on_peer_writable(PeerNetwork::PeerEventHandler cb) override
Subscribe to "this peer can be written to again" — fired when a peer whose send queue had filled past...
std::optional< Peer > peer(const PeerId &id)
Handle to a connected peer by id, or std::nullopt if not connected.
void stop()
Tear the node down: stop subsystems (reverse order), close all connections, and join the reactor pool...
const NatStatus & nat_status() const noexcept
What the mesh has shown about our own side of the NAT, from the endpoints datagram peers report obser...
void on(std::string_view channel, MessageRouter::Handler cb)
Register a handler for inbound messages on a named channel.
bool forward_datagrams(const PeerId &dialer, const PeerId &responder, uint64_t cid, std::shared_ptr< std::atomic< uint64_t > > bytes, uint64_t rate, uint64_t burst) override
As the relay: forward the packets of cid between dialer and responder, counting their bytes into byte...
void on_live_outcome(MessageType type, PeerNetwork::LiveOutcomeHandler cb) override
Subscribe to what becomes of the live messages of type sent with a tag (SendOptions::tag): delivered,...
size_t max_peers() const noexcept
std::function< void(const Peer &, ByteView, Deadline)> DeadlineMessageHandler
A message handler that is also told each message's deadline: for a live one (SendOptions::lifetime),...
std::function< void(const Address &)> DialFailedHandler
std::function< void(const PeerId &, CloseReason)> PeerDisconnectHandler
A peer went away, and why.
std::function< void(const Peer &, ByteView)> MessageHandler
std::function< void(const Peer &, const PathStats &)> PeerPathHandler
std::function< void(const Peer &, uint64_t tag, bool delivered)> LiveOutcomeHandler
What became of a live message sent with a tag: delivered, or given up on (see LiveOutcome).
std::function< void(const Peer &)> PeerEventHandler
A pluggable network subsystem.
Node construction options.
Dialing a specific endpoint over a specific wire — the capability a NAT-traversal module needs and th...
std::vector< uint8_t > Bytes
MessageType
Inner-message kind. Application traffic uses App, addressed by channel.
What the mesh has told us about our own side of the NAT.
What a subsystem receives at attach() — the node's gift to its plugins.
A lightweight handle to a connected peer.
Self-certifying peer identity.
Addressing/metadata for a peer — the shareable, persistable identity.
The narrow contract a subsystem needs from the node — and nothing more.
A decoded inner message. payload is a non-owning view into the source bytes.
What became of a live message sent with a tag (SendOptions::tag), as far as its sender can tell.