uniwrtc 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,7 +70,7 @@ await client.connect();
70
70
  ## How It Works
71
71
 
72
72
  1. **Durable Objects** - One per room, manages peer discovery
73
- 2. **WebSocket** - Browsers connect for signaling
73
+ 2. **HTTP polling** - Browsers connect for signaling
74
74
  3. **Signaling Only** - Offers/answers/ICE via Worker
75
75
  4. **P2P Data** - WebRTC data channels bypass Cloudflare
76
76
  5. **Free Tier** - Plenty of capacity for small deployments
@@ -109,7 +109,7 @@ const serverUrl = 'http://localhost:8787/';
109
109
 
110
110
  ## Troubleshooting
111
111
 
112
- **WebSocket errors**: Ensure your domain is on Cloudflare with SSL enabled
112
+ **Connection errors**: Ensure your domain is on Cloudflare with SSL enabled
113
113
 
114
114
  **Connection refused**: Check the Worker route pattern in `wrangler.toml`
115
115
 
package/README.md CHANGED
@@ -1,21 +1,53 @@
1
1
  # UniWRTC
2
2
 
3
- A universal WebRTC signaling service that provides a simple and flexible WebSocket-based signaling server for WebRTC applications.
3
+ A universal WebRTC signaling service that provides a simple and flexible **HTTP polling** signaling server for WebRTC applications.
4
4
 
5
5
  Available on npm: https://www.npmjs.com/package/uniwrtc
6
6
 
7
7
  ## Features
8
8
 
9
- - 🚀 **Simple WebSocket-based signaling** - Easy to integrate with any WebRTC application
9
+ - 🚀 **Simple signaling** - HTTP polling (works locally and on Cloudflare Durable Objects)
10
10
  - 🏠 **Session-based architecture** - Support for multiple sessions with isolated peer groups
11
11
  - 🔌 **Flexible client library** - Ready-to-use JavaScript client for browser and Node.js
12
12
  - 📡 **Real-time messaging** - Efficient message routing between peers
13
13
  - 🔄 **Auto-reconnection** - Built-in reconnection logic for reliable connections
14
14
  - 📊 **Health monitoring** - HTTP health check endpoint for monitoring
15
- - 🎯 **Minimal dependencies** - Lightweight implementation using only the `ws` package
15
+ - 🎯 **Minimal dependencies** - Lightweight implementation with minimal runtime deps
16
16
 
17
17
  ## Quick Start
18
18
 
19
+ ## Using with `simple-peer` (SDP text-only)
20
+
21
+ This repo's signaling format sends **SDP as plain text** for offers/answers.
22
+ `simple-peer` uses `{ type, sdp }` objects, so use the adapter in [simple-peer-adapter.js](simple-peer-adapter.js).
23
+
24
+ Example (browser):
25
+
26
+ ```js
27
+ import Peer from 'simple-peer';
28
+ import UniWRTCClient from './client-browser.js';
29
+ import { sendSimplePeerSignal, attachUniWRTCToSimplePeer, chooseDeterministicInitiator } from './simple-peer-adapter.js';
30
+
31
+ const client = new UniWRTCClient('https://your-signal-server', { roomId: 'my-room' });
32
+ await client.connect();
33
+
34
+ // Join a session (peers in the same session can connect)
35
+ await client.joinSession('my-room');
36
+
37
+ // Ensure exactly ONE side initiates for a given pair
38
+ const initiator = chooseDeterministicInitiator(client.clientId, targetId);
39
+ const peer = new Peer({ initiator, trickle: true });
40
+ const cleanup = attachUniWRTCToSimplePeer(client, peer);
41
+
42
+ peer.on('signal', (signal) => {
43
+ // targetId must be the other peer's UniWRTC client id
44
+ sendSimplePeerSignal(client, signal, targetId);
45
+ });
46
+
47
+ // When done:
48
+ // cleanup();
49
+ ```
50
+
19
51
  ### Installation
20
52
 
21
53
  #### From npm (recommended)
@@ -63,7 +95,7 @@ The interactive demo is available live at **https://signal.peer.ooo/** (Cloudfla
63
95
  5. Open the P2P chat and send messages between tabs
64
96
 
65
97
  **Or run locally:**
66
- 1. Start the server: `npm start` (signaling at `ws://localhost:8080`)
98
+ 1. Start the server: `npm start` (signaling at `http://localhost:8080`)
67
99
  2. Start the Vite dev server: `npm run dev` (demo at `http://localhost:5173/`)
68
100
  3. Open the demo in two browser tabs
69
101
  4. Enter the same session ID in both, then Connect
@@ -73,7 +105,8 @@ The interactive demo is available live at **https://signal.peer.ooo/** (Cloudfla
73
105
 
74
106
  ### Server API
75
107
 
76
- The signaling server accepts WebSocket connections and supports the following message types:
108
+ The signaling server supports:
109
+ - HTTP polling signaling (no WebSockets)
77
110
 
78
111
  #### Client → Server Messages
79
112
 
@@ -97,7 +130,7 @@ The signaling server accepts WebSocket connections and supports the following me
97
130
  ```json
98
131
  {
99
132
  "type": "offer",
100
- "offer": { /* RTCSessionDescription */ },
133
+ "offer": "v=0\r\n...",
101
134
  "targetId": "peer-client-id",
102
135
  "sessionId": "session-123"
103
136
  }
@@ -107,7 +140,7 @@ The signaling server accepts WebSocket connections and supports the following me
107
140
  ```json
108
141
  {
109
142
  "type": "answer",
110
- "answer": { /* RTCSessionDescription */ },
143
+ "answer": "v=0\r\n...",
111
144
  "targetId": "peer-client-id",
112
145
  "sessionId": "session-123"
113
146
  }
@@ -117,7 +150,7 @@ The signaling server accepts WebSocket connections and supports the following me
117
150
  ```json
118
151
  {
119
152
  "type": "ice-candidate",
120
- "candidate": { /* RTCIceCandidate */ },
153
+ "candidate": "candidate:...|0|0",
121
154
  "targetId": "peer-client-id",
122
155
  "sessionId": "session-123"
123
156
  }
@@ -175,16 +208,13 @@ Use directly from npm:
175
208
  ```javascript
176
209
  // ESM (browser)
177
210
  import UniWRTCClient from 'uniwrtc/client-browser.js';
178
-
179
- // CommonJS (Node.js)
180
- const UniWRTCClient = require('uniwrtc/client.js');
181
211
  ```
182
212
 
183
213
  The `client.js` library provides a convenient wrapper for the signaling protocol:
184
214
 
185
215
  ```javascript
186
216
  // Create a client instance
187
- const client = new UniWRTCClient('ws://localhost:8080');
217
+ const client = new UniWRTCClient('http://localhost:8080', { roomId: 'my-room' });
188
218
 
189
219
  // Set up event handlers
190
220
  client.on('connected', (data) => {
@@ -220,7 +250,7 @@ client.on('ice-candidate', (data) => {
220
250
  await client.connect();
221
251
 
222
252
  // Join a session
223
- client.joinSession('my-session');
253
+ await client.joinSession('my-session');
224
254
 
225
255
  // Send WebRTC signaling messages
226
256
  client.sendOffer(offerObject, targetPeerId);
@@ -233,7 +263,7 @@ client.sendIceCandidate(candidateObject, targetPeerId);
233
263
  Here's a complete example of creating a WebRTC peer connection:
234
264
 
235
265
  ```javascript
236
- const client = new UniWRTCClient('ws://localhost:8080');
266
+ const client = new UniWRTCClient('http://localhost:8080', { roomId: 'my-room' });
237
267
  const peerConnections = new Map();
238
268
 
239
269
  // ICE server configuration
@@ -281,7 +311,7 @@ client.on('peer-joined', async (data) => {
281
311
  client.on('offer', async (data) => {
282
312
  const pc = createPeerConnection(data.peerId);
283
313
 
284
- await pc.setRemoteDescription(data.offer);
314
+ await pc.setRemoteDescription({ type: 'offer', sdp: data.offer });
285
315
  const answer = await pc.createAnswer();
286
316
  await pc.setLocalDescription(answer);
287
317
  client.sendAnswer(answer, data.peerId);
@@ -291,7 +321,7 @@ client.on('offer', async (data) => {
291
321
  client.on('answer', async (data) => {
292
322
  const pc = peerConnections.get(data.peerId);
293
323
  if (pc) {
294
- await pc.setRemoteDescription(data.answer);
324
+ await pc.setRemoteDescription({ type: 'answer', sdp: data.answer });
295
325
  }
296
326
  });
297
327
 
@@ -299,7 +329,12 @@ client.on('answer', async (data) => {
299
329
  client.on('ice-candidate', async (data) => {
300
330
  const pc = peerConnections.get(data.peerId);
301
331
  if (pc) {
302
- await pc.addIceCandidate(data.candidate);
332
+ const [candidate, sdpMidRaw, sdpMLineIndexRaw] = String(data.candidate).split('|');
333
+ await pc.addIceCandidate(new RTCIceCandidate({
334
+ candidate,
335
+ sdpMid: sdpMidRaw || undefined,
336
+ sdpMLineIndex: sdpMLineIndexRaw !== undefined && sdpMLineIndexRaw !== '' ? Number(sdpMLineIndexRaw) : undefined
337
+ }));
303
338
  }
304
339
  });
305
340
 
@@ -307,8 +342,8 @@ client.on('ice-candidate', async (data) => {
307
342
  await client.connect();
308
343
  client.joinSession('my-video-session');
309
344
 
310
- // Or use Cloudflare Durable Objects deployment
311
- const cfClient = new UniWRTCClient('wss://signal.peer.ooo?room=my-session');
345
+ // Or use Cloudflare Durable Objects deployment (HTTP polling; no WebSockets)
346
+ const cfClient = new UniWRTCClient('https://signal.peer.ooo');
312
347
  await cfClient.connect();
313
348
  cfClient.joinSession('my-session');
314
349
  ```
@@ -323,7 +358,7 @@ new UniWRTCClient(serverUrl, options)
323
358
  ```
324
359
 
325
360
  **Parameters:**
326
- - `serverUrl` (string): WebSocket URL of the signaling server
361
+ - `serverUrl` (string): HTTP(S) URL of the signaling server
327
362
  - `options` (object, optional):
328
363
  - `autoReconnect` (boolean): Enable automatic reconnection (default: true)
329
364
  - `reconnectDelay` (number): Delay between reconnection attempts in ms (default: 3000)
@@ -382,20 +417,25 @@ Response:
382
417
 
383
418
  ### Message Flow
384
419
 
385
- 1. Client connects via WebSocket (or WS-over-HTTP for Cloudflare)
420
+ 1. Client connects via HTTPS (Cloudflare DO HTTP polling)
386
421
  2. Server/Durable Object assigns a unique client ID
387
422
  3. Client sends join message with session ID
388
423
  4. Server broadcasts `peer-joined` to other peers in the same session only
389
424
  5. Peers exchange WebRTC offers/answers/ICE candidates via the server
390
425
  6. Server routes signaling messages to specific peers by target ID (unicast, not broadcast)
391
426
 
427
+ Notes:
428
+ - Cloudflare signaling uses JSON over HTTPS requests to `/api` (polling).
429
+ - Offers/answers are transmitted as SDP strings (text-only) in the `offer`/`answer` fields.
430
+ - ICE candidates are transmitted as a compact text string: `candidate|sdpMid|sdpMLineIndex`.
431
+
392
432
  ## Security Considerations
393
433
 
394
434
  This is a basic signaling server suitable for development and testing. For production use, consider:
395
435
 
396
436
  - Adding authentication and authorization
397
437
  - Implementing rate limiting
398
- - Using TLS/WSS for encrypted connections
438
+ - Using TLS/HTTPS for encrypted connections
399
439
  - Adding room access controls
400
440
  - Implementing message validation
401
441
  - Monitoring and logging
package/demo.html CHANGED
@@ -270,7 +270,7 @@
270
270
  </div>
271
271
 
272
272
  <div class="connection-controls">
273
- <input type="text" id="serverUrl" placeholder="wss://signal.peer.ooo" value="wss://signal.peer.ooo">
273
+ <input type="text" id="serverUrl" placeholder="https://signal.peer.ooo" value="https://signal.peer.ooo">
274
274
  <input type="text" id="customPeerId" placeholder="Custom Peer ID (optional)">
275
275
  <button class="btn-primary" id="connectBtn" onclick="connect()">Connect</button>
276
276
  </div>
@@ -53,20 +53,27 @@ name = "uniwrtc"
53
53
  main = "src/index.js"
54
54
  compatibility_date = "2024-12-20"
55
55
 
56
+ assets = { directory = "./dist", binding = "ASSETS" }
57
+
58
+ [[durable_objects.bindings]]
59
+ name = "ROOMS"
60
+ class_name = "Room"
61
+
62
+ [[migrations]]
63
+ tag = "v1"
64
+ new_classes = ["Room"]
65
+
56
66
  [env.production]
57
67
  routes = [
58
68
  { pattern = "${FULL_DOMAIN}/*", zone_name = "${DOMAIN}" }
59
69
  ]
60
70
 
61
- [[durable_objects.bindings]]
71
+ assets = { directory = "./dist", binding = "ASSETS" }
72
+
73
+ [[env.production.durable_objects.bindings]]
62
74
  name = "ROOMS"
63
75
  class_name = "Room"
64
76
 
65
- [durable_objects]
66
- migrations = [
67
- { tag = "v1", new_classes = ["Room"] }
68
- ]
69
-
70
77
  [build]
71
78
  command = "npm install"
72
79
  EOF
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniwrtc",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "A universal WebRTC signaling service",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -15,15 +15,12 @@
15
15
  "keywords": [
16
16
  "webrtc",
17
17
  "signaling",
18
- "websocket",
19
18
  "peer-to-peer",
20
19
  "real-time"
21
20
  ],
22
21
  "author": "",
23
22
  "license": "MIT",
24
- "dependencies": {
25
- "ws": "^8.17.1"
26
- },
23
+ "dependencies": {},
27
24
  "devDependencies": {
28
25
  "@playwright/test": "^1.57.0",
29
26
  "vite": "^6.0.6"