Skip to main content

Module hub

Module hub 

Source
Available on crate feature hub only.
Expand description

An async GridConnect hub (feature hub).

Every frame received on one Port is forwarded to every other port. Ports can be TCP GridConnect clients (JMRI, desktop apps, other tools), uplinks to another hub, or serial adapters (feature serial). Applications can also attach their own ports with Hub::port, e.g. to run an OpenLCB node inside the same process as the hub.

§Semantics

The hub behaves like a CAN bus segment for GridConnect links:

  • Fan-out. A frame sent by one port is delivered to every other attached port, in order.
  • No echo. A port never receives its own frames. (On a real CAN bus a transmitter does not receive its own frame either, and OpenLCB alias logic depends on that: seeing “your” alias from someone else means a collision.)
  • No routing or filtering. Frames are relayed verbatim; the hub does not parse messages or track aliases, so it is not an OpenLCB node and never appears on the network. Malformed GridConnect input is dropped.
  • Back-pressure by dropping. All ports share one broadcast ring of 4096 frames (a tokio::sync::broadcast channel); each port reads it at its own pace. A port that falls more than 4096 frames behind skips the frames it missed and carries on from the oldest one still in the ring, like a congested CAN interface, instead of slowing down everybody else. The skip is reported through the log feature.
  • Reads never wait for writes. Each stream is read and written concurrently, so a peer that stops reading cannot stop the hub from draining what that peer sends.

§Logging

The library prints nothing by default. With the log feature, connections, disconnections, accept errors and lagging ports are reported through the log crate (target rolcb::hub). The rolcb-hub binary enables it and prints to stderr.

  JMRI ──TCP:12021──┐                     ┌── desktop app (TCP :12021)
                    │      ┌───────┐      │
  other hub ◄─uplink┼─────►│  Hub  │◄─────┼── your app: hub.port()
                    │      └───────┘      │
  USB buffer ─serial┘                     └── rolcb-hub -v monitor

Outgoing frames are written as newline-terminated GridConnect text; frames already queued are coalesced into a single write (up to 64 frames) to keep latency and syscall counts low.

§Example

use rolcb::hub::{self, Hub};
use tokio::net::TcpListener;

let hub = Hub::new();
tokio::spawn(hub::serve_tcp(hub.clone(), TcpListener::bind("0.0.0.0:12021").await?));
tokio::spawn(hub::uplink_tcp(hub.clone(), "jmri.local:12021".to_string()));

// Watch the traffic from inside the process.
let mut port = hub.port();
while let Some(frame) = port.recv().await {
    println!("{}", rolcb::gridconnect::format(&frame));
}

See the hub guide for the command-line tool and for embedding the hub in your own program.

Structs§

Hub
The shared frame bus. Create with Hub::new and attach ports.
Port
One attachment point on a Hub.

Constants§

CHANNEL_DEPTH
Capacity of the broadcast ring shared by all ports, in frames.

Functions§

run_gridconnect_stream
Relay GridConnect text between a byte stream (TCP socket, serial port) and the hub until the stream closes.
serve_tcp
Accept GridConnect TCP clients forever.
uplink_serialserial
Keep a USB/serial GridConnect adapter attached, reopening it forever.
uplink_tcp
Keep a connection to an upstream GridConnect TCP hub, reconnecting forever.