#include <node.h>
Public Member Functions | |
| Node (NodeConfig config) | |
| Construct a node from its configuration (see NodeConfig). | |
| ~Node () override | |
| Stops the node if still running, then releases all resources. | |
| Node (const Node &)=delete | |
| Node & | operator= (const Node &)=delete |
| template<class T > | |
| T * | add_subsystem (std::unique_ptr< T > subsystem) |
| Attach a subsystem (DHT, GossipSub, PingService…). | |
| bool | start () |
| Bring the node up: open the listener (if enabled), start the reactor pool, then start every attached subsystem. | |
| void | stop () |
| Tear the node down: stop subsystems (reverse order), close all connections, and join the reactor pool. | |
| const PeerId & | local_id () const noexcept override |
| Our self-certifying peer identity (the public key peers authenticate). | |
| uint16_t | listen_port () const noexcept override |
| The bound listen port (the actual port when the config requested 0). | |
| uint8_t | transports () const noexcept override |
| Transports this node is actually running, as a PeerTransports bitmask. | |
| const std::string & | protocol () const noexcept override |
| Application protocol identity bound into the handshake (see NodeConfig). | |
| EventBus & | events () noexcept |
| ServiceRegistry & | services () noexcept |
| void | connect (const Address &address) override |
| Dial a peer. | |
| void | connect (const std::string &host, uint16_t port) |
| Dial a peer. | |
| size_t | peer_count () const noexcept |
| Number of currently-established peers. | |
| std::vector< PeerInfo > | peers () const override |
| Snapshot of all established peers (id, addresses, direction, timing). | |
| std::optional< Peer > | peer (const PeerId &id) |
| Handle to a connected peer by id, or std::nullopt if not connected. | |
| std::vector< Address > | observed_addresses () const |
| Our own addresses as remote peers reported observing us at — their observed IP paired with our listen port. | |
| const NatStatus & | nat_status () const noexcept |
| What the mesh has shown about our own side of the NAT, from the endpoints datagram peers report observing our shared UDP socket at (see nat_status.h). | |
| bool | dial_direct (const Address &addr, TransportKind kind, const DialProfile &profile) override |
Start exactly one dial to addr over kind, bypassing the transport race. | |
| 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 connection. | |
| void | wake_circuit (PeerRoute route, uint32_t events) override |
| Deliver poll-equivalent events (PollIn / PollOut / PollErr, see core/io_poller.h) to a circuit connection — the events a socket-backed link would have got from the poller. | |
| void | close_circuit (PeerRoute route, CloseReason reason) override |
| Tear a circuit connection down. | |
| size_t | max_peers () const noexcept |
| void | set_max_peers (size_t n) noexcept |
| bool | peer_limit_reached () const noexcept |
| bool | send (const PeerId &to, std::string_view channel, ByteView payload) |
| Send raw bytes to one peer on a named channel. | |
| bool | broadcast (std::string_view channel, ByteView payload) |
| Send raw bytes on a named channel to every connected peer. | |
| bool | peer_writable (const PeerId &id) const override |
| Whether a peer's send queue has room for more. | |
| void | on_peer_connected (PeerNetwork::PeerEventHandler cb) override |
| Subscribe to peer-connected events. The handler runs on a reactor thread. | |
| void | on_peer_disconnected (PeerNetwork::PeerDisconnectHandler cb) override |
| Subscribe to peer-disconnected 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. | |
| 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 its mark has drained back under it. | |
| void | on (std::string_view channel, MessageRouter::Handler cb) |
| Register a handler for inbound messages on a named channel. | |
| template<class T > | |
| T * | subsystem () noexcept |
| MessageJson * | json () noexcept |
| The JSON messaging module if one was attached (add_subsystem<MessageJson>), else nullptr. | |
| bool | send (const PeerId &to, MessageType type, ByteView payload) override |
| Send to one peer. | |
| bool | broadcast (MessageType type, ByteView payload) override |
| Send to every connected peer. | |
| std::vector< PeerId > | connected_peers () const override |
| void | on (MessageType type, PeerNetwork::MessageHandler cb) override |
Public Member Functions inherited from librats::PeerNetwork | |
| virtual | ~PeerNetwork ()=default |
Public Member Functions inherited from librats::DialService | |
| virtual | ~DialService ()=default |
Public Member Functions inherited from librats::CircuitService | |
| virtual | ~CircuitService ()=default |
Friends | |
| class | Peer |
Additional Inherited Members | |
Public Types inherited from librats::PeerNetwork | |
| using | MessageHandler = std::function< void(const Peer &, ByteView)> |
| using | PeerEventHandler = std::function< void(const Peer &)> |
| using | PeerDisconnectHandler = std::function< void(const PeerId &, CloseReason)> |
| A peer went away, and why. | |
| using | DialFailedHandler = std::function< void(const Address &)> |
|
explicit |
Construct a node from its configuration (see NodeConfig).
This only loads the identity and prepares the layers; no socket is opened until start().
|
override |
Stops the node if still running, then releases all resources.
|
delete |
|
inline |
Attach a subsystem (DHT, GossipSub, PingService…).
Call before start(); the node owns it (single ownership), gives it a PeerNetwork on start(), and stops it on stop(). Returns a non-owning pointer to the just-added subsystem so the caller can drive its API without a separate get()/move dance — valid for the node's lifetime: auto* files = node.add_subsystem(std::make_unique<FileTransfer>("./dl"));
|
overridevirtual |
Adopt link as a connection carried by the peer carrier, on the reactor that owns the carrier's own connection.
| role | Outbound for a circuit we opened, Inbound for one opened to us. It is what the secure handshake and the peer table's duplicate resolution read, so it must say who asked. |
| connected | whether the far end is already there. An inbound circuit is (the opener would not have sent it otherwise); an outbound one is not until its acceptance arrives, and until then the connection waits in Connecting for a PollOut. |
link is released. Implements librats::CircuitService.
|
overridevirtual |
Send to every connected peer.
Implements librats::PeerNetwork.
| bool librats::Node::broadcast | ( | std::string_view | channel, |
| ByteView | payload | ||
| ) |
Send raw bytes on a named channel to every connected peer.
Coarser than send(): the answer is the reactors' view as they last left it and does not count what this call has just handed over, because a broadcast is dispatched per reactor rather than per peer. Good enough to pace a periodic fan-out; when precise backpressure matters — a file transfer, a large stream — address peers individually with send().
|
overridevirtual |
Tear a circuit connection down.
Thread-safe; a no-op for a route that is already gone.
Implements librats::CircuitService.
|
overridevirtual |
Dial a peer.
Non-blocking: the connection (transport + handshake) completes asynchronously and surfaces via on_peer_connected. A duplicate or self-connection is detected and dropped after the handshake.
The transport is chosen by the dialer (see node/dialer.h): the preferred one first, the other raced in after NodeConfig::transport_fallback_ms if the first has not come up. Whichever completes its handshake first wins.
Implements librats::PeerNetwork.
| void librats::Node::connect | ( | const std::string & | host, |
| uint16_t | port | ||
| ) |
Dial a peer.
Non-blocking: the connection (transport + handshake) completes asynchronously and surfaces via on_peer_connected. A duplicate or self-connection is detected and dropped after the handshake.
The transport is chosen by the dialer (see node/dialer.h): the preferred one first, the other raced in after NodeConfig::transport_fallback_ms if the first has not come up. Whichever completes its handshake first wins.
|
overridevirtual |
Implements librats::PeerNetwork.
|
overridevirtual |
Start exactly one dial to addr over kind, bypassing the transport race.
Non-blocking; the outcome surfaces through the node's ordinary peer-connected event. Returns false when the node cannot carry that transport at all (no datagram socket, or an address family the one socket cannot reach), in which case nothing was started and no failure event will follow.
Implements librats::DialService.
|
noexcept |
The JSON messaging module if one was attached (add_subsystem<MessageJson>), else nullptr.
Convenience over subsystem<MessageJson>(); defined in node.cpp.
|
inlineoverridevirtualnoexcept |
The bound listen port (the actual port when the config requested 0).
Both transports share it, so one advertised address is dialable over either.
Implements librats::PeerNetwork.
|
inlineoverridevirtualnoexcept |
Our self-certifying peer identity (the public key peers authenticate).
Implements librats::PeerNetwork.
|
inlinenoexcept |
What the mesh has shown about our own side of the NAT, from the endpoints datagram peers report observing our shared UDP socket at (see nat_status.h).
Also published in services() as ExternalAddressService, which is how a NAT-traversal subsystem reaches it.
| std::vector< Address > librats::Node::observed_addresses | ( | ) | const |
Our own addresses as remote peers reported observing us at — their observed IP paired with our listen port.
De-duplicated and bounded; populated as peers send their identify message. Useful for NAT awareness / advertising.
|
inlineoverridevirtual |
Implements librats::PeerNetwork.
|
inline |
|
inlineoverridevirtual |
Subscribe to failed-outbound-dial events. The handler runs on a reactor thread.
Implements librats::PeerNetwork.
|
inlineoverridevirtual |
Subscribe to peer-connected events. The handler runs on a reactor thread.
Implements librats::PeerNetwork.
|
inlineoverridevirtual |
Subscribe to peer-disconnected events. The handler runs on a reactor thread.
Implements librats::PeerNetwork.
|
inlineoverridevirtual |
Subscribe to "this peer can be written to again" — fired when a peer whose send queue had filled past its mark has drained back under it.
The other half of send() returning false; an application that never checks that return never needs this. The handler runs on a reactor thread.
Reimplemented from librats::PeerNetwork.
Handle to a connected peer by id, or std::nullopt if not connected.
|
inlinenoexcept |
|
inlinenoexcept |
|
overridevirtual |
Whether a peer's send queue has room for more.
False for a peer that is not connected.
The same question send() answers, asked without sending anything: it weighs both halves of what the peer is carrying — the bytes the reactor has queued, and the bytes a caller has handed to send() that the reactor has not taken up yet. So it is safe to poll: a caller that has just filled the queue in a tight loop keeps being told "no room" until the reactor has actually looked at what it was given, rather than being told "go on" because nothing observable has changed yet.
It stays a hint about a queue that drains as it is read, so the ordinary flow is unchanged: the signal to stop is the return of send(), and the signal to resume is on_peer_writable. This is for a caller that must wait for room on a thread of its own — the event alone cannot serve it, because a queue that filled only with bytes still in transit never crossed anything on the connection and so raises no event when they drain.
Reimplemented from librats::PeerNetwork.
|
inlineoverridevirtual |
Snapshot of all established peers (id, addresses, direction, timing).
Implements librats::PeerNetwork.
|
inlineoverridevirtualnoexcept |
Application protocol identity bound into the handshake (see NodeConfig).
Implements librats::PeerNetwork.
|
overridevirtual |
Send to one peer.
Implements librats::PeerNetwork.
Send raw bytes to one peer on a named channel.
Non-blocking; the payload is copied into the peer's send queue. No-op if the peer is not connected.
| to | destination peer id |
| channel | application channel name (interned to a 16-bit id) |
| payload | message bytes (copied) |
"Stop" is meant literally, and yielding is part of it: the mark is re-tested inside the reactor task this call hands off to, and it is that test which flips the peer to unwritable and later raises on_peer_writable. A caller that answers a false by looping straight back into send() therefore starves the very thread that would tell it to stop — the queue keeps growing while the signal it is waiting for never gets a turn to be produced.
|
inlinenoexcept |
| bool librats::Node::start | ( | ) |
Bring the node up: open the listener (if enabled), start the reactor pool, then start every attached subsystem.
Register callbacks and attach subsystems BEFORE calling this.
| void librats::Node::stop | ( | ) |
Tear the node down: stop subsystems (reverse order), close all connections, and join the reactor pool.
Safe to call once; idempotent.
|
inlinenoexcept |
|
inlineoverridevirtualnoexcept |
Transports this node is actually running, as a PeerTransports bitmask.
May be narrower than the config asked for — a UDP socket that could not be bound leaves the node TCP-only rather than failing to start.
Reimplemented from librats::PeerNetwork.
|
overridevirtual |
Deliver poll-equivalent events (PollIn / PollOut / PollErr, see core/io_poller.h) to a circuit connection — the events a socket-backed link would have got from the poller.
Thread-safe, and a no-op for a route that is already gone.
Implements librats::CircuitService.