Hyperswarm Relay
🧪 This project is still experimental. Do not use it in production.
Relaying the Hyperswarm DHT over framed streams to bring decentralized networking to everyone.
Installation
npm install @hyperswarm/dht-relay
Usage
On the relaying side:
import DHT from 'hyperdht'
import { relay } from '@hyperswarm/dht-relay'
relay(new DHT(), stream)
On the relayed side:
import DHT from '@hyperswarm/dht-relay'
const dht = new DHT(stream)
From here, the API matches that of the Hyperswarm DHT: https://github.com/holepunchto/hyperdht#api
Transports
As a convenience, we provide stream wrappers for common transport protocols. These may or may not be appropriate for your particular use case and so your mileage may vary.
TCP
The TCP wrapper is a re-export of https://github.com/holepunchto/hyperswarm-secret-stream which adds both framing and encryption.
On the relaying side:
import net from 'net'
import DHT from 'hyperdht'
import { relay } from '@hyperswarm/dht-relay'
import Stream from '@hyperswarm/dht-relay/tcp'
const dht = new DHT()
const server = net.createServer().listen(8080)
server.on('connection', (socket) => {
relay(dht, new Stream(false, socket))
})
On the relayed side:
import net from 'net'
import DHT from '@hyperswarm/dht-relay'
import Stream from '@hyperswarm/dht-relay/tcp'
const socket = net.connect(8080)
const dht = new DHT(new Stream(true, socket))
WebSocket
The WebSocket wrapper is a simple Duplex
stream that only adapts the interface of the WebSocket as the WebSocket API already provides its own framing and encryption.
On the relaying side:
import { WebSocketServer } from 'ws'
import DHT from 'hyperdht'
import { relay } from '@hyperswarm/dht-relay'
import Stream from '@hyperswarm/dht-relay/ws'
const dht = new DHT()
const server = new WebSocketServer({ port: 8080 })
server.on('connection', (socket) => {
relay(dht, new Stream(false, socket))
})
On the relayed side:
import DHT from '@hyperswarm/dht-relay'
import Stream from '@hyperswarm/dht-relay/ws'
const socket = new WebSocket('ws://localhost:8080')
const dht = new DHT(new Stream(true, socket))
CLI
You can start a DHT relay in the command line:
npm install -g @hyperswarm/dht-relay
Run a DHT relay server:
dht-relay # [--port 49443] [--host 0.0.0.0] [--cert <path fullchain.pem>] [--key <path privkey.pem>]
If running behind a proxy like NGINX then add --behind-proxy
so logging info is correct.
Protocol
A reference implementation of the relay protocol can be found in the lib/protocol.js
module. The protocol is versioned and built on top of https://github.com/mafintosh/protomux.
Messages
All types are specified as their corresponding compact-encoding codec.
handshake
(0
)
-
uint8
Flags-
custodial
:1
-
-
fixed(32)
The public key of the peer - (if
custodial
is set)fixed(64)
The secret key
ping
(1
)
Empty
pong
(2
)
Empty
connect
(3
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The alias of the stream -
fixed(32)
The public key of the peer - (if
custodial
is set)fixed(64)
The secret key -
fixed(32)
The public key of the remote peer
connection
(4
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The alias of the stream -
uint32
The alias of the server -
fixed(32)
The public key of the remote peer - (if
custodial
is set)fixed(64)
The Noise handshake hash - (if
custodial
is not set)uint32
The ID of the Noise handshake session
connected
(5
)
-
uint32
The alias of the stream -
uint32
The remote alias of the stream
incoming
(6
)
-
uint32
The ID of the request -
uint32
The alias of the server -
fixed(32)
The public key of the remote peer -
buffer
The Noise handshake payload
deny
(7
)
-
uint32
The ID of the request
accept
(8
)
-
uint32
The ID of the request
destroy
(9
)
-
uint8
Flags-
paired
:1
-
error
:2
-
- (if
paired
is set)uint32
The alias of the stream - (if
paired
is not set)uint32
The remote alias of the stream - (if
error
is set)string
The reason the stream was destroyed
listen
(10
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The alias of the server -
fixed(32)
The public key of the server - (if
custodial
is set)fixed(64)
The secret key
listening
(11
)
-
uint32
The alias of the server -
uint32
The remote alias of the server -
ipv4Address
The address of the server
close
(12
)
-
uint32
The alias of the server
closed
(13
)
-
uint32
The alias of the server
open
(14
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The alias of the stream -
uint32
The alias of the server - (if
custodial
is set)fixed(64)
The Noise handshake hash - (if
custodial
is not set)uint32
The ID of the Noise handshake session
end
(15
)
-
uint32
The alias of the stream
data
(16
)
-
uint32
The alias of the stream -
array(buffer)
The data sent
result
(17
)
-
uint32
The query ID -
buffer
The query specific data
finished
(18
)
-
uint32
The query ID
lookup
(19
)
-
uint32
The query ID -
fixed(32)
The topic to look up
announce
(20
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The query ID -
fixed(32)
The topic to announce -
fixed(32)
The public key to announce on - (if
custodial
is set)fixed(64)
The secret key
unannounce
(21
)
-
uint8
Flags-
custodial
:1
-
-
uint32
The query ID -
fixed(32)
The topic to unannounce -
fixed(32)
The public key that was announced on - (if
custodial
is set)fixed(64)
The secret key
signAnnounce
(22
)
-
uint32
The ID of the request -
uint32
The alias of the signee -
fixed(32)
The roundtrip token of the peer -
buffer
The ID of the peer -
array(
ipv4Address
)
The addresses that may relay messages
signUnannounce
(23
)
-
uint32
The ID of the request -
uint32
The alias of the signee -
fixed(32)
The roundtrip token of the peer -
buffer
The ID of the peer -
array(
ipv4Address
)
The addresses that may relay messages
signature
(24
)
-
uint32
The ID of the request -
buffer
The signature
noiseSend
(25
)
-
uint8
Flags-
isInitiator
:1
-
-
uint32
The ID of the handshake session - (if
isInitiator
is set) The alias of the remote stream -
buffer
The Noise handshake payload
noiseReceive
(26
)
-
uint8
Flags-
isInitiator
:1
-
-
uint32
The ID of the handshake session - (if
isInitiator
is not set) The alias of the server -
buffer
The Noise handshake payload
noiseReply
(27
)
-
uint8
Flags-
isInitiator
:1
-
complete
:2
-
-
uint32
The ID of the handshake session -
buffer
The Noise handshake payload - (if
isInitiator
andcomplete
are not set)fixed(32)
The public key of the remote peer - (if
complete
is set)fixed(32)
The ID of the remote stream - (if
complete
is set)fixed(32)
The holepunch secret
License
ISC