Back to Site
Loading...
Searching...
No Matches
circuit_service.h File Reference

Turning a relayed byte stream into a peer connection — the capability a relay module needs and PeerNetwork deliberately does not offer. More...

#include "librats/core/types.h"
#include "librats/peer/peer_id.h"
#include "librats/peer/peer_table.h"
#include "librats/transport/link.h"
#include <cstdint>
#include <memory>
#include <optional>
Include dependency graph for circuit_service.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  librats::CircuitService
 

Namespaces

namespace  librats
 

Detailed Description

Turning a relayed byte stream into a peer connection — the capability a relay module needs and PeerNetwork deliberately does not offer.

A relay module speaks a protocol (who forwards what to whom) and owns the byte stream that comes out of it (transport/relay_link.h). What it cannot do on its own is the one remaining step: making that stream a Connection, so the ordinary Noise handshake, framing, identify and peer table all run over it and the peer at the far end becomes an ordinary peer. That step needs the reactor pool, which a Subsystem has no business holding.

So this is the narrow escape hatch, published by the Node in its ServiceRegistry next to DialService, and resolved by whoever needs it:

if (auto* circuits = ctx.services.get<CircuitService>())
    auto route = circuits->adopt_circuit(relay_id, std::move(link),
                                         ConnRole::Outbound, false);

── One thread, chosen for you ────────────────────────────────────────────── The node places the circuit on the reactor that owns the CARRIER's connection, and that is the whole reason this call exists rather than a bare "adopt this link somewhere". Every byte of a circuit arrives on the carrier's connection and leaves through it, so putting the two on one thread means the entire relayed path is handled without a lock, a queue or a hand-off — the same shared-nothing property every other connection has. Any other placement would move bytes between reactor threads twice per message.

The route comes back synchronously (the ConnId is reserved before the adoption is posted, exactly as Reactor::connect does), so the caller can wake and close the circuit from the moment it asks for one.

── What is deliberately NOT here ─────────────────────────────────────────── Nothing about relaying: no relay selection, no protocol, no policy about when a circuit is worth opening. Those belong to the module. This interface would serve any transport that arrives from outside the reactor pool.

Definition in file circuit_service.h.