WebRTC Signaling with Signal-Fire
WebRTC is a technology which allows individual peers to talk directly to each other. This requires a signaling server.
A WebRTC signaling server communicates between peers to set up peer-to-peer audio/video and/or data channels. This allows your clients to communicate directly with each other.
Years ago I developed signal-fire, a WebRTC signaling server built for node.js. There also was a browser client available which greatly reduced the burden of setting up peer connections. Lack of maintenance led to the module’s eventual demise and I recently officially retired it.
Luckily I had some inspiration for the new and improved version, and I got to work. The result was the Signal-Fire ecosystem, starting with Signal-Fire Server, a server that does exactly the same as its predecessor did, but better!
The Server
Signal-Fire Server is based on my other quite recent module Luce. Luce is a versatile WebSocket framework for node.js. An excellent pairing for my new project.
Command-Line Interface (CLI)
If you want to get started with Signal-Fire Server without too much hassle, and you’re content with the basic features (for now), you can use the CLI to start and manage Server workers.
Install the CLI globally:
> npm i -g @signal-fire/cli
To start a worker on port 3003:
> signal-fire start -p 3003
Starting the Server
The Server can be installed through npm:
> npm i @signal-fire/server
To manage client IDs the Server requires a registry. In the example below we use LocalRegistry
, an in-memory store.
import { Server } from 'http'
import createApp from './index'
import { LocalRegistry } from '@lucets/registry'
const registry = new LocalRegistry()
const app = createApp(registry)
const server = new Server()
server.on('upgrade', app.onUpgrade())
server.listen(3003, () => {
console.log('Server listening on port 3003')
})
Congratulations, you now have a basic server running!
The Client
Signal-Fire Client is the replacement of signal-fire-client, which has also been deprecated. The Client is also new and improved. The Client is designed for the browser and uses the native EventTarget
.
The Client is meant to be used with browserify.
Install the client through npm:
> npm i @signal-fire/client
Connecting to the Server is exceedingly simple:
import connect from '@signal-fire/client'
const client = await connect('ws://localhost/socket')
Sessions
Sessions are requests and responses for setting up the peer connection. One peer creates a session, which its target can either accept or deny.
This example shows how to start a session:
import connect, { PeerConnection } from '@signal-fire/client'
async function run () {
const client = await connect('ws://localhost:3003/socket')
const session = await client.createSession('<target id>')
session.addEventListener('accepted', (ev: CustomEvent<PeerConnection>) => {
console.log('Session accepted!')
const connection = ev.detail
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
})
stream.getTracks().forEach(track => connection.addTrack(track, stream))
})
session.addEventListener('rejected', () => {
console.log('Session rejected')
})
session.addEventListener('timed-out', () => {
console.log('Session timed out')
})
}
This example shows how to accept a session:
import connect, { IncomingSession } from '@signal-fire/client'
async function run () {
const client = await connect('ws://localhost:3003/socket')
client.addEventListener('session', (ev: CustomEvent<IncomingSession>) => {
const session = ev.detail
const connection = await session.accept()
})
}
Next
The Signal-Fire Server and Client are projects I intent to keep maintaining, and using myself. If you’ve checked out either and found a bug, please open an issue on GitHub, or better yet, a pull request.