protoo Server Module
protoo-server is a Node.js module that forms the server-side component of the protoo signaling framework. This framework is designed for building minimalist and extensible signaling layers for multi-party Real-Time Communication (RTC) applications, such as video conferencing or collaborative tools. Currently at version 4.0.8, the library maintains a steady release cadence, evidenced by its significant major version updates. It differentiates itself by providing a clear, event-driven API for managing WebSocket connections, peers, and rooms, allowing developers to focus on RTC logic rather than low-level WebSocket intricacies. The module facilitates the creation of `Room`s to organize connected `Peer`s, enabling efficient message routing and state management within a signaling context. Its focus on being "minimalist" means it provides core signaling primitives without enforcing complex architectural patterns.
Common errors
-
TypeError: peer.send is not a function
cause Attempting to use the deprecated `send()` method on a `Peer` instance in protoo-server v4 or later.fixRename `peer.send()` calls to `peer.request()`. -
TypeError: room.spread is not a function
cause Attempting to use the removed `spread()` method on a `Room` instance in protoo-server v4 or later.fixThe `room.spread()` method has been removed. Replace its functionality with custom iteration over `room.peers` to send notifications or requests to each peer. -
Error: WebSocket connection to 'ws://localhost:8080' failed: WebSocket opening handshake timed out
cause The Node.js HTTP server or WebSocket server is not listening on the expected port, or there's a firewall/network issue preventing connection.fixVerify that `httpServer.listen()` is correctly called and that the port is not already in use. Check server logs for startup errors. Ensure the client is connecting to the correct WebSocket URL.
Warnings
- breaking The `peer.send()` method has been renamed to `peer.request()`. Calls to the old method will result in a runtime error.
- breaking The `room.spread()` method has been entirely removed from the `Room` class, affecting functionality for broadcasting messages.
- gotcha protoo-server relies on an external WebSocket server implementation (e.g., `ws` package) for the underlying transport. It does not provide its own WebSocket server.
Install
-
npm install protoo-server -
yarn add protoo-server -
pnpm add protoo-server
Imports
- Server
import { Server } from 'protoo-server';import Server from 'protoo-server';
- Room, Peer
import Room, { Peer } from 'protoo-server';import { Room, Peer } from 'protoo-server'; - protoo-server (CommonJS)
const Server = require('protoo-server'); const { Server } = require('protoo-server');const protoo = require('protoo-server'); const Server = protoo.default;
Quickstart
import * as http from 'http';
import { WebSocketServer } from 'ws';
import Server from 'protoo-server';
const httpServer = http.createServer();
const wsServer = new WebSocketServer({ server: httpServer, noServer: true });
const protooServer = new Server();
wsServer.on('connection', (ws, request) => {
const { url } = request;
if (!url) {
ws.close();
return;
}
const peerId = url.split('/').pop() || `peer-${Date.now()}`;
console.log(`New WebSocket connection from peer: ${peerId}`);
let peer;
try {
peer = protooServer.createPeer(peerId, ws);
} catch (error) {
console.error(`Error creating protoo peer: ${error}`);
ws.close();
return;
}
peer.on('request', async (request, accept, reject) => {
console.log(`Peer '${peer.id}' sent request:`, request);
try {
const response = await handlePeerRequest(peer, request);
accept(response);
} catch (error) {
reject(error);
}
});
peer.on('notification', (notification) => {
console.log(`Peer '${peer.id}' sent notification:`, notification);
});
peer.on('close', () => {
console.log(`Peer '${peer.id}' disconnected.`);
});
});
httpServer.on('upgrade', (request, socket, head) => {
wsServer.handleUpgrade(request, socket, head, (ws) => {
wsServer.emit('connection', ws, request);
});
});
async function handlePeerRequest(peer, request) {
switch (request.method) {
case 'echo':
return { message: `Echoing: ${request.data.text}` };
case 'joinRoom':
// In a real app, you'd manage rooms here and add the peer
console.log(`Peer '${peer.id}' wants to join room '${request.data.roomId}'`);
peer.notify('roomJoined', { roomId: request.data.roomId, peers: [] });
return { joined: true };
default:
throw new Error(`Unknown method: ${request.method}`);
}
}
const PORT = process.env.PORT || 8080;
httpServer.listen(PORT, () => {
console.log(`protoo-server listening on ws://localhost:${PORT}`);
console.log('Connect with protoo-client: protoo-client.createPeer(wsUrl, { requestTimeout: 3000 })');
});