Build a driver
hop-core has no bearer system of its own, it only moves bytes. A drivergives it bearers: it implements the HopContract protocol for one transport or platform and registers it with the node. Everything else, sealing, addressing, routing, fragmentation, retransmit, dedup, delivery, stays in the core.
What the core does vs. what your driver does
hop-core owns
- Sealing & addressing (keys, not IPs)
- Routing & multipath epidemic forward
- Fragmentation & reassembly
- Retransmit, dedup, delivery acks, custody
Your driver owns
- Discovery & connection lifecycle
- Framing & moving raw bytes
- Background operation & power for the platform
- Transport authentication & link cost
The Bearer protocol
Under HopContract, a bearer is defined by lifecycle control (start and stop), sending bytes over identified links (send), and optional teardown hooks (closeand authenticated).
// HopContract: universal Bearer protocol in Swift public protocol Bearer: AnyObject { var sink: LinkSink? { get set } var transportName: String { get } // e.g. "BT", "LAN", "Relay" // Lifecycle: start radio / advertising; stop and release resources func start() func stop() // Send frame bytes over an active link func send(_ bytes: Data, on link: LinkId) // Optional link lifecycle hooks func close(_ link: LinkId) func authenticated(_ link: LinkId) }
Reporting link events with LinkSink
Your transport drives the core through LinkSink. Surface links as they connect, feed inbound byte buffers directly in, and signal disconnection or authentication updates.
// Report link events and inbound bytes back to the node via LinkSink: sink?.linkUp(linkId, role: .initiator, peerId: peerKey) // link formed with peer sink?.linkBytes(linkId, bytes: data) // inbound frame arrived sink?.linkDown(linkId) // link disconnected sink?.linkAuthenticated(linkId, peerId: peerKey) // authenticated session ready sink?.linkCost(linkId, cost: 10) // route metric / cost
Multiplexing bearers with BearerManager
Add one bearer or several. BearerManager translates local link identifiers from each bearer into a single process-wide LinkId space and handles priority across BLE, Wi-Fi/LAN, and relays.
// BearerManager multiplexes multiple bearers into a single id space let manager = BearerManager() manager.register(CoreBluetoothBearer()) manager.register(LanBearer()) manager.sink = node manager.start()
Android Kotlin implementation
On Android, the driver implements the exact same Bearer contract in Kotlin via JNA over the C ABI. The method signatures and lifecycle expectations mirror the Swift protocol:
// HopContract: universal Bearer interface in Kotlin (sh.hop.Bearer) interface Bearer { var sink: LinkSink? val transportName: String fun start() fun stop() fun send(bytes: ByteArray, link: LinkId) fun close(link: LinkId) {} fun authenticated(link: LinkId) {} }
The universal C ABI floor
The shared foundation beneath all platform SDKs is the C ABI (sdk/hop.h). Native and embedded drivers (Linux/server, ESP32) bind this interface directly without intermediate wrapper runtimes.
Checklist
- Implement
start(),stop(), andsend(). - On connection established, call
sink.linkUp(). - On every inbound frame, call
sink.linkBytes(), never reassemble yourself. - On disconnect, call
sink.linkDown(). - Register bearer instances with
BearerManagerfor unified routing.
Illustrative, the shape of the interface, not the exact signatures; the real contract ships with the SDK in HopContract. Bringing an unusual transport or platform?Tell us.