WebRTC Signaling Server for P2P Communication
Rendezvous is a WebSocket-based signaling server that facilitates WebRTC peer-to-peer connections. Peers connect to named rooms, exchange public keys for identity verification, and relay ICE candidates and SDP offers/answers to establish direct connections.
Connect to a named room. The roomName can be any URL-safe string.
Use wss:// for secure connections in production.
register with public keywelcome containing peer ID and list of other peersoffer/answer/ice-candidatepeer-joined and peer-left eventsClient → Server
Register with the signaling server using your public key. The server computes a fingerprint from the key to use as your peer ID.
{
"type": "register",
"publicKey": { /* JWK public key */ }
}
| Field | Type | Description |
|---|---|---|
publicKey | JWK | Your public key in JWK format (ECDSA, Ed25519, or RSA) |
Client → Server → Peer
Send an SDP offer to initiate a WebRTC connection with a specific peer.
{
"type": "offer",
"to": "peer-fingerprint",
"sdp": { /* RTCSessionDescription */ }
}
| Field | Type | Description |
|---|---|---|
to | string | Target peer's fingerprint (peer ID) |
sdp | RTCSessionDescription | The SDP offer |
Client → Server → Peer
Send an SDP answer in response to an offer.
{
"type": "answer",
"to": "peer-fingerprint",
"sdp": { /* RTCSessionDescription */ }
}
| Field | Type | Description |
|---|---|---|
to | string | Target peer's fingerprint |
sdp | RTCSessionDescription | The SDP answer |
Client → Server → Peer
Relay an ICE candidate to a peer for NAT traversal.
{
"type": "ice-candidate",
"to": "peer-fingerprint",
"candidate": { /* RTCIceCandidate */ }
}
| Field | Type | Description |
|---|---|---|
to | string | Target peer's fingerprint |
candidate | RTCIceCandidate | The ICE candidate |
Server → Client
Sent after successful registration. Contains your assigned peer ID and a list of all other peers currently in the room.
{
"type": "welcome",
"peerId": "your-fingerprint",
"peers": [
{ "id": "peer-fingerprint", "publicKey": { /* JWK */ } },
...
]
}
| Field | Type | Description |
|---|---|---|
peerId | string | Your peer ID (SHA-256 fingerprint of your public key) |
peers | array | List of other peers in the room with their IDs and public keys |
Server → Client
Broadcast when a new peer joins the room.
{
"type": "peer-joined",
"peerId": "new-peer-fingerprint",
"publicKey": { /* JWK */ }
}
Server → Client
Broadcast when a peer leaves the room (disconnects).
{
"type": "peer-left",
"peerId": "departed-peer-fingerprint"
}
Server → Client (relayed)
Relayed messages from other peers. The to field is replaced with from indicating the sender.
{
"type": "offer",
"from": "sender-fingerprint",
"sdp": { /* RTCSessionDescription */ }
}
Server → Client
Sent when an error occurs.
{
"type": "error",
"message": "Error description"
}
Peer IDs are computed as the SHA-256 fingerprint of the public key's essential fields. This allows peers to verify each other's identity by comparing fingerprints with a pre-shared buddy list.
// Extract essential fields based on key type
if (kty === 'EC') { essential = { kty, crv, x, y } }
if (kty === 'OKP') { essential = { kty, crv, x } }
if (kty === 'RSA') { essential = { kty, n, e } }
// Compute fingerprint
fingerprint = SHA-256(JSON.stringify(essential))