A generic, public WebRTC signaling server. It relays SDP offers/answers and ICE candidates between two peers — nothing else.
Safe to be public: WebRTC data channels are end-to-end encrypted (DTLS). This server never sees your application data — it only forwards opaque connection-setup blobs.
1. Create a room:
curl -X POST https://signal.snomiao.com/room
# → {"token":"V4bNa22vpR8e7Ky...","ws":"wss://signal.snomiao.com/room/V4bNa22vpR8e7Ky..."}
2. Both peers connect via WebSocket:
const ws = new WebSocket("wss://signal.snomiao.com/room/TOKEN");
3. Exchange SDP/ICE through the WebSocket:
// Peer A (host) sends offer:
ws.send(JSON.stringify({ type: "offer", sdp: offer.sdp }));
// Peer B (guest) receives it, sends answer:
ws.send(JSON.stringify({ type: "answer", sdp: answer.sdp }));
// Both exchange ICE candidates:
ws.send(JSON.stringify({ type: "ice", candidate: candidate }));
4. Once WebRTC connects, close the signaling WebSocket. You're peer-to-peer now.
| Client → Server | Description |
|---|---|
{"type":"offer","sdp":"..."} | SDP offer (relayed to peer) |
{"type":"answer","sdp":"..."} | SDP answer (relayed to peer) |
{"type":"ice","candidate":"..."} | ICE candidate (relayed to peer) |
| Server → Client | Description |
|---|---|
{"type":"peer-joined"} | The other peer connected |
{"type":"peer-left"} | The other peer disconnected |
{"type":"error","message":"..."} | Room full / invalid message |
POST /room | Create a room → {"token","ws"} |
GET /room/:token | WebSocket upgrade for signaling |
GET /room/:token/status | Room status → {"peers":0|1|2} |
Rooms expire after 10 min of inactivity. Max 2 peers per room. No data is stored or logged.
Rate limit: 30 rooms/min per IP.