@zero-server/webrtc 0.9.7

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/index.d.ts +2 -0
  4. package/index.js +53 -0
  5. package/lib/auth/index.js +1 -0
  6. package/lib/debug.js +372 -0
  7. package/lib/errors.js +1 -0
  8. package/lib/middleware/index.js +1 -0
  9. package/lib/observe/index.js +1 -0
  10. package/lib/webrtc/bot.js +361 -0
  11. package/lib/webrtc/cli.js +182 -0
  12. package/lib/webrtc/cluster.js +350 -0
  13. package/lib/webrtc/e2ee.js +282 -0
  14. package/lib/webrtc/ice.js +370 -0
  15. package/lib/webrtc/index.js +132 -0
  16. package/lib/webrtc/joinToken.js +116 -0
  17. package/lib/webrtc/observe.js +229 -0
  18. package/lib/webrtc/peer.js +116 -0
  19. package/lib/webrtc/room.js +171 -0
  20. package/lib/webrtc/sdp.js +508 -0
  21. package/lib/webrtc/sfu/index.js +201 -0
  22. package/lib/webrtc/sfu/livekit.js +301 -0
  23. package/lib/webrtc/sfu/mediasoup.js +317 -0
  24. package/lib/webrtc/sfu/memory.js +204 -0
  25. package/lib/webrtc/signaling.js +546 -0
  26. package/lib/webrtc/stun.js +492 -0
  27. package/lib/webrtc/turn/codec.js +370 -0
  28. package/lib/webrtc/turn/credentials.js +141 -0
  29. package/lib/webrtc/turn/server.js +633 -0
  30. package/lib/ws/index.js +1 -0
  31. package/package.json +62 -0
  32. package/types/app.d.ts +223 -0
  33. package/types/auth.d.ts +520 -0
  34. package/types/body.d.ts +14 -0
  35. package/types/cli.d.ts +2 -0
  36. package/types/cluster.d.ts +75 -0
  37. package/types/env.d.ts +80 -0
  38. package/types/errors.d.ts +316 -0
  39. package/types/fetch.d.ts +43 -0
  40. package/types/grpc.d.ts +432 -0
  41. package/types/index.d.ts +396 -0
  42. package/types/lifecycle.d.ts +60 -0
  43. package/types/middleware.d.ts +320 -0
  44. package/types/observe.d.ts +304 -0
  45. package/types/orm.d.ts +1887 -0
  46. package/types/request.d.ts +109 -0
  47. package/types/response.d.ts +157 -0
  48. package/types/router.d.ts +78 -0
  49. package/types/sse.d.ts +78 -0
  50. package/types/webrtc.d.ts +501 -0
  51. package/types/websocket.d.ts +126 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * @module webrtc/sfu/memory
3
+ * @description In-process "memory" SFU adapter.
4
+ *
5
+ * A passthrough router that never touches the network: every produce()
6
+ * call records a logical producer, every consume() call records a
7
+ * logical consumer, and events are emitted via {@link SfuAdapter#onEvent}.
8
+ * Perfect for unit tests, ≤ 4-peer audio-only rooms, and local dev
9
+ * where the cost of running mediasoup or LiveKit is unjustified.
10
+ *
11
+ * The adapter does NOT decode or forward media packets - it models
12
+ * bookkeeping only. Real packet forwarding lives in native adapters
13
+ * (mediasoup, LiveKit).
14
+ */
15
+ 'use strict';
16
+
17
+ const { SfuAdapter } = require('./index');
18
+ const { WebRTCError } = require('../../errors');
19
+
20
+ class MemorySfuAdapter extends SfuAdapter
21
+ {
22
+ constructor(opts)
23
+ {
24
+ super();
25
+ this._opts = opts || {};
26
+ this._counter = 0;
27
+ this._routers = new Map(); // routerId -> { id, opts, transports:Set, closed }
28
+ this._transports = new Map(); // transportId -> { id, routerId, peer, producers:Set, consumers:Set, closed }
29
+ this._producers = new Map(); // producerId -> { id, transportId, kind, rtpParams, paused, closed }
30
+ this._consumers = new Map(); // consumerId -> { id, transportId, producerId, rtpCaps, closed }
31
+ }
32
+
33
+ _nextId(prefix)
34
+ {
35
+ this._counter += 1;
36
+ return `${prefix}-${this._counter}`;
37
+ }
38
+
39
+ async createRouter(opts)
40
+ {
41
+ const id = this._nextId('router');
42
+ const router = { id, opts: opts || {}, transports: new Set(), closed: false };
43
+ this._routers.set(id, router);
44
+ this._emit('router-new', { routerId: id });
45
+ return { id, routerId: id };
46
+ }
47
+
48
+ async createTransport(router, peer)
49
+ {
50
+ const routerId = router && router.id;
51
+ const r = routerId && this._routers.get(routerId);
52
+ if (!r || r.closed)
53
+ {
54
+ throw new WebRTCError('createTransport: unknown router', { code: 'WEBRTC_SFU_NO_ROUTER' });
55
+ }
56
+ const id = this._nextId('transport');
57
+ const t = {
58
+ id,
59
+ transportId: id,
60
+ routerId,
61
+ peer: peer || null,
62
+ producers: new Set(),
63
+ consumers: new Set(),
64
+ closed: false,
65
+ iceParameters: { usernameFragment: id, password: id },
66
+ dtlsParameters: { role: 'auto', fingerprints: [] },
67
+ };
68
+ this._transports.set(id, t);
69
+ r.transports.add(id);
70
+ this._emit('transport-new', { transportId: id, routerId, peerId: peer && peer.id });
71
+ return t;
72
+ }
73
+
74
+ async produce(transport, kind, rtpParams)
75
+ {
76
+ if (kind !== 'audio' && kind !== 'video')
77
+ {
78
+ throw new WebRTCError('produce: kind must be "audio" or "video"', { code: 'WEBRTC_SFU_INVALID_KIND' });
79
+ }
80
+ const t = transport && this._transports.get(transport.id);
81
+ if (!t || t.closed)
82
+ {
83
+ throw new WebRTCError('produce: unknown transport', { code: 'WEBRTC_SFU_NO_TRANSPORT' });
84
+ }
85
+ const id = this._nextId('producer');
86
+ const p = { id, producerId: id, transportId: t.id, kind, rtpParams: rtpParams || {}, paused: false, closed: false };
87
+ this._producers.set(id, p);
88
+ t.producers.add(id);
89
+ this._emit('producer-new', { producerId: id, transportId: t.id, kind });
90
+ return p;
91
+ }
92
+
93
+ async consume(transport, producerId, rtpCaps)
94
+ {
95
+ const t = transport && this._transports.get(transport.id);
96
+ if (!t || t.closed)
97
+ {
98
+ throw new WebRTCError('consume: unknown transport', { code: 'WEBRTC_SFU_NO_TRANSPORT' });
99
+ }
100
+ const prod = this._producers.get(producerId);
101
+ if (!prod || prod.closed)
102
+ {
103
+ throw new WebRTCError('consume: unknown producer', { code: 'WEBRTC_SFU_NO_PRODUCER' });
104
+ }
105
+ const id = this._nextId('consumer');
106
+ const c = {
107
+ id,
108
+ consumerId: id,
109
+ transportId: t.id,
110
+ producerId,
111
+ kind: prod.kind,
112
+ rtpParams: prod.rtpParams,
113
+ rtpCaps: rtpCaps || {},
114
+ closed: false,
115
+ };
116
+ this._consumers.set(id, c);
117
+ t.consumers.add(id);
118
+ this._emit('consumer-new', { consumerId: id, transportId: t.id, producerId });
119
+ return c;
120
+ }
121
+
122
+ async pauseProducer(producerId)
123
+ {
124
+ const p = this._producers.get(producerId);
125
+ if (!p || p.closed)
126
+ {
127
+ throw new WebRTCError('pauseProducer: unknown producer', { code: 'WEBRTC_SFU_NO_PRODUCER' });
128
+ }
129
+ if (!p.paused)
130
+ {
131
+ p.paused = true;
132
+ this._emit('producer-pause', { producerId });
133
+ }
134
+ }
135
+
136
+ async resumeProducer(producerId)
137
+ {
138
+ const p = this._producers.get(producerId);
139
+ if (!p || p.closed)
140
+ {
141
+ throw new WebRTCError('resumeProducer: unknown producer', { code: 'WEBRTC_SFU_NO_PRODUCER' });
142
+ }
143
+ if (p.paused)
144
+ {
145
+ p.paused = false;
146
+ this._emit('producer-resume', { producerId });
147
+ }
148
+ }
149
+
150
+ async closeRouter(routerId)
151
+ {
152
+ const r = this._routers.get(routerId);
153
+ if (!r) return;
154
+ for (const tid of r.transports)
155
+ {
156
+ const t = this._transports.get(tid);
157
+ if (!t) continue;
158
+ for (const pid of t.producers)
159
+ {
160
+ const p = this._producers.get(pid);
161
+ if (p) { p.closed = true; this._emit('producer-close', { producerId: pid }); }
162
+ this._producers.delete(pid);
163
+ }
164
+ for (const cid of t.consumers)
165
+ {
166
+ const c = this._consumers.get(cid);
167
+ if (c) { c.closed = true; this._emit('consumer-close', { consumerId: cid }); }
168
+ this._consumers.delete(cid);
169
+ }
170
+ t.closed = true;
171
+ this._emit('transport-close', { transportId: tid });
172
+ this._transports.delete(tid);
173
+ }
174
+ r.closed = true;
175
+ this._emit('router-close', { routerId });
176
+ this._routers.delete(routerId);
177
+ }
178
+
179
+ async stats(scope)
180
+ {
181
+ if (scope && this._routers.has(scope))
182
+ {
183
+ const r = this._routers.get(scope);
184
+ return { kind: 'router', routerId: scope, transports: r.transports.size };
185
+ }
186
+ if (scope && this._transports.has(scope))
187
+ {
188
+ const t = this._transports.get(scope);
189
+ return {
190
+ kind: 'transport', transportId: scope, routerId: t.routerId,
191
+ producers: t.producers.size, consumers: t.consumers.size,
192
+ };
193
+ }
194
+ return {
195
+ kind: 'global',
196
+ routers: this._routers.size,
197
+ transports: this._transports.size,
198
+ producers: this._producers.size,
199
+ consumers: this._consumers.size,
200
+ };
201
+ }
202
+ }
203
+
204
+ module.exports = { MemorySfuAdapter };