@phystack/hub-client 4.5.19-dev → 4.5.20-dev
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.
- package/dist/index.d.ts +22 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +252 -378
- package/dist/index.js.map +1 -1
- package/dist/peripheral-twin.d.ts +34 -0
- package/dist/peripheral-twin.d.ts.map +1 -0
- package/dist/peripheral-twin.js +234 -0
- package/dist/peripheral-twin.js.map +1 -0
- package/dist/services/phyhub-connection.service.d.ts +1 -0
- package/dist/services/phyhub-connection.service.d.ts.map +1 -1
- package/dist/services/phyhub-connection.service.js +17 -0
- package/dist/services/phyhub-connection.service.js.map +1 -1
- package/dist/services/phyhub-direct-connection.service.d.ts +21 -0
- package/dist/services/phyhub-direct-connection.service.d.ts.map +1 -0
- package/dist/services/phyhub-direct-connection.service.js +101 -0
- package/dist/services/phyhub-direct-connection.service.js.map +1 -0
- package/dist/services/webrtc/data-channel-handler.d.ts +45 -0
- package/dist/services/webrtc/data-channel-handler.d.ts.map +1 -0
- package/dist/services/webrtc/data-channel-handler.js +260 -0
- package/dist/services/webrtc/data-channel-handler.js.map +1 -0
- package/dist/services/webrtc/index.d.ts +8 -0
- package/dist/services/webrtc/index.d.ts.map +1 -0
- package/dist/services/webrtc/index.js +18 -0
- package/dist/services/webrtc/index.js.map +1 -0
- package/dist/services/webrtc/media-stream-handler.d.ts +57 -0
- package/dist/services/webrtc/media-stream-handler.d.ts.map +1 -0
- package/dist/services/webrtc/media-stream-handler.js +383 -0
- package/dist/services/webrtc/media-stream-handler.js.map +1 -0
- package/dist/services/webrtc/peer-connection-manager.d.ts +40 -0
- package/dist/services/webrtc/peer-connection-manager.d.ts.map +1 -0
- package/dist/services/webrtc/peer-connection-manager.js +336 -0
- package/dist/services/webrtc/peer-connection-manager.js.map +1 -0
- package/dist/services/webrtc/types.d.ts +134 -0
- package/dist/services/webrtc/types.d.ts.map +1 -0
- package/dist/services/webrtc/types.js +12 -0
- package/dist/services/webrtc/types.js.map +1 -0
- package/dist/services/webrtc/webrtc-globals.d.ts +4 -0
- package/dist/services/webrtc/webrtc-globals.d.ts.map +1 -0
- package/dist/services/webrtc/webrtc-globals.js +72 -0
- package/dist/services/webrtc/webrtc-globals.js.map +1 -0
- package/dist/services/webrtc/webrtc-manager.d.ts +35 -0
- package/dist/services/webrtc/webrtc-manager.d.ts.map +1 -0
- package/dist/services/webrtc/webrtc-manager.js +274 -0
- package/dist/services/webrtc/webrtc-manager.js.map +1 -0
- package/dist/test/communication-comprehensive-test.d.ts +8 -0
- package/dist/test/communication-comprehensive-test.d.ts.map +1 -0
- package/dist/test/communication-comprehensive-test.js +356 -0
- package/dist/test/communication-comprehensive-test.js.map +1 -0
- package/dist/test/webrtc-channel-names-test.d.ts +2 -0
- package/dist/test/webrtc-channel-names-test.d.ts.map +1 -0
- package/dist/test/webrtc-channel-names-test.js +177 -0
- package/dist/test/webrtc-channel-names-test.js.map +1 -0
- package/dist/test/webrtc-comprehensive-test.d.ts +2 -0
- package/dist/test/webrtc-comprehensive-test.d.ts.map +1 -0
- package/dist/test/webrtc-comprehensive-test.js +328 -0
- package/dist/test/webrtc-comprehensive-test.js.map +1 -0
- package/dist/test/webrtc-reconnect-test.d.ts +4 -0
- package/dist/test/webrtc-reconnect-test.d.ts.map +1 -0
- package/dist/test/webrtc-reconnect-test.js +244 -0
- package/dist/test/webrtc-reconnect-test.js.map +1 -0
- package/dist/test/webrtc-test-harness.d.ts +4 -0
- package/dist/test/webrtc-test-harness.d.ts.map +1 -0
- package/dist/test/webrtc-test-harness.js +169 -0
- package/dist/test/webrtc-test-harness.js.map +1 -0
- package/dist/twin-messaging.d.ts +20 -0
- package/dist/twin-messaging.d.ts.map +1 -0
- package/dist/twin-messaging.js +94 -0
- package/dist/twin-messaging.js.map +1 -0
- package/dist/twin-registry.d.ts +9 -0
- package/dist/twin-registry.d.ts.map +1 -0
- package/dist/twin-registry.js +26 -0
- package/dist/twin-registry.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +20 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/twin.types.d.ts +62 -14
- package/dist/types/twin.types.d.ts.map +1 -1
- package/dist/types/twin.types.js +8 -1
- package/dist/types/twin.types.js.map +1 -1
- package/docs/webrtc-howto.md +398 -0
- package/docs/webrtc-test.md +330 -0
- package/package.json +3 -3
- package/scripts/webrtc-test.sh +401 -0
- package/src/index.ts +378 -568
- package/src/peripheral-twin.ts +337 -0
- package/src/services/phyhub-connection.service.ts +24 -0
- package/src/services/phyhub-direct-connection.service.ts +159 -0
- package/src/services/webrtc/data-channel-handler.ts +362 -0
- package/src/services/webrtc/index.ts +36 -0
- package/src/services/webrtc/media-stream-handler.ts +536 -0
- package/src/services/webrtc/peer-connection-manager.ts +467 -0
- package/src/services/webrtc/types.ts +273 -0
- package/src/services/webrtc/webrtc-globals.ts +108 -0
- package/src/services/webrtc/webrtc-manager.ts +490 -0
- package/src/test/communication-comprehensive-test.ts +533 -0
- package/src/test/webrtc-channel-names-test.ts +266 -0
- package/src/test/webrtc-comprehensive-test.ts +494 -0
- package/src/test/webrtc-reconnect-test.ts +345 -0
- package/src/test/webrtc-test-harness.ts +254 -0
- package/src/twin-messaging.ts +184 -0
- package/src/twin-registry.ts +39 -0
- package/src/types/index.ts +3 -0
- package/src/types/twin.types.ts +80 -14
- package/dist/services/webrtc/datachannel.d.ts +0 -10
- package/dist/services/webrtc/datachannel.d.ts.map +0 -1
- package/dist/services/webrtc/datachannel.js +0 -290
- package/dist/services/webrtc/datachannel.js.map +0 -1
- package/dist/services/webrtc/mediastream.d.ts +0 -10
- package/dist/services/webrtc/mediastream.d.ts.map +0 -1
- package/dist/services/webrtc/mediastream.js +0 -396
- package/dist/services/webrtc/mediastream.js.map +0 -1
- package/dist/services/webrtc/peer-connection-ice.d.ts +0 -32
- package/dist/services/webrtc/peer-connection-ice.d.ts.map +0 -1
- package/dist/services/webrtc/peer-connection-ice.js +0 -483
- package/dist/services/webrtc/peer-connection-ice.js.map +0 -1
- package/src/services/webrtc/datachannel.ts +0 -421
- package/src/services/webrtc/mediastream.ts +0 -602
- package/src/services/webrtc/peer-connection-ice.ts +0 -689
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataChannelHandler
|
|
3
|
+
*
|
|
4
|
+
* Manages RTCDataChannel lifecycle including:
|
|
5
|
+
* - Channel creation (initiator) or reception (responder)
|
|
6
|
+
* - Message serialization/deserialization
|
|
7
|
+
* - Persistent channel abstraction across reconnections
|
|
8
|
+
* - Message buffering during reconnection
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { PeerConnectionManager, PeerConnectionManagerOptions } from './peer-connection-manager';
|
|
12
|
+
import {
|
|
13
|
+
TwinMessagingInterface,
|
|
14
|
+
PhygridDataChannel,
|
|
15
|
+
PeerConnectionConfig,
|
|
16
|
+
DEFAULT_WEBRTC_OPTIONS,
|
|
17
|
+
} from './types';
|
|
18
|
+
|
|
19
|
+
export interface DataChannelHandlerOptions extends Partial<PeerConnectionManagerOptions> {
|
|
20
|
+
/** Use STUN servers. Default: true */
|
|
21
|
+
useStun?: boolean;
|
|
22
|
+
|
|
23
|
+
/** STUN server URLs */
|
|
24
|
+
stunServers?: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class DataChannelHandler {
|
|
28
|
+
private targetTwinId: string;
|
|
29
|
+
private channelName: string;
|
|
30
|
+
private isInitiator: boolean;
|
|
31
|
+
private twinMessaging: TwinMessagingInterface;
|
|
32
|
+
private options: Required<DataChannelHandlerOptions>;
|
|
33
|
+
|
|
34
|
+
private pcManager: PeerConnectionManager | null = null;
|
|
35
|
+
private dataChannel: RTCDataChannel | null = null;
|
|
36
|
+
private isOpen = false;
|
|
37
|
+
private isClosed = false;
|
|
38
|
+
|
|
39
|
+
// Connection status
|
|
40
|
+
private isConnecting = false;
|
|
41
|
+
|
|
42
|
+
// Event listeners
|
|
43
|
+
private messageListeners: Set<(data: any) => void> = new Set();
|
|
44
|
+
private closeListeners: Set<() => void> = new Set();
|
|
45
|
+
|
|
46
|
+
// Callbacks for WebRTCManager
|
|
47
|
+
private onConnectedCallback?: () => void;
|
|
48
|
+
private onDisconnectedCallback?: () => void;
|
|
49
|
+
private onErrorCallback?: (error: Error) => void;
|
|
50
|
+
private onReconnectingCallback?: (attempt: number) => void;
|
|
51
|
+
private onReconnectedCallback?: (attempt: number) => void;
|
|
52
|
+
|
|
53
|
+
constructor(
|
|
54
|
+
targetTwinId: string,
|
|
55
|
+
isInitiator: boolean,
|
|
56
|
+
twinMessaging: TwinMessagingInterface,
|
|
57
|
+
options: DataChannelHandlerOptions = {},
|
|
58
|
+
channelName: string = 'default'
|
|
59
|
+
) {
|
|
60
|
+
this.targetTwinId = targetTwinId;
|
|
61
|
+
this.channelName = channelName;
|
|
62
|
+
this.isInitiator = isInitiator;
|
|
63
|
+
this.twinMessaging = twinMessaging;
|
|
64
|
+
this.options = {
|
|
65
|
+
useStun: options.useStun ?? DEFAULT_WEBRTC_OPTIONS.useStun,
|
|
66
|
+
stunServers: options.stunServers ?? DEFAULT_WEBRTC_OPTIONS.stunServers,
|
|
67
|
+
connectionTimeout: options.connectionTimeout ?? DEFAULT_WEBRTC_OPTIONS.connectionTimeout,
|
|
68
|
+
initialRetryDelay: options.initialRetryDelay ?? DEFAULT_WEBRTC_OPTIONS.initialRetryDelay,
|
|
69
|
+
maxRetryDelay: options.maxRetryDelay ?? DEFAULT_WEBRTC_OPTIONS.maxRetryDelay,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Set callbacks for connection events
|
|
75
|
+
*/
|
|
76
|
+
setCallbacks(callbacks: {
|
|
77
|
+
onConnected?: () => void;
|
|
78
|
+
onDisconnected?: () => void;
|
|
79
|
+
onError?: (error: Error) => void;
|
|
80
|
+
onReconnecting?: (attempt: number) => void;
|
|
81
|
+
onReconnected?: (attempt: number) => void;
|
|
82
|
+
}): void {
|
|
83
|
+
this.onConnectedCallback = callbacks.onConnected;
|
|
84
|
+
this.onDisconnectedCallback = callbacks.onDisconnected;
|
|
85
|
+
this.onErrorCallback = callbacks.onError;
|
|
86
|
+
this.onReconnectingCallback = callbacks.onReconnecting;
|
|
87
|
+
this.onReconnectedCallback = callbacks.onReconnected;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Connect and return a PhygridDataChannel
|
|
92
|
+
*/
|
|
93
|
+
async connect(): Promise<PhygridDataChannel> {
|
|
94
|
+
if (this.isClosed) {
|
|
95
|
+
throw new Error('DataChannelHandler has been closed');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.isConnecting = true;
|
|
99
|
+
// Channel ID includes the name to support multiple channels to same peer
|
|
100
|
+
const channelId = `dc-${this.channelName}-${this.targetTwinId}`;
|
|
101
|
+
// Prefix for signaling messages - unique per channel name
|
|
102
|
+
const channelPrefix = `dc-${this.channelName}`;
|
|
103
|
+
|
|
104
|
+
const pcConfig: PeerConnectionConfig = {
|
|
105
|
+
targetTwinId: this.targetTwinId,
|
|
106
|
+
isInitiator: this.isInitiator,
|
|
107
|
+
connectionType: 'datachannel',
|
|
108
|
+
channelPrefix,
|
|
109
|
+
useStun: this.options.useStun,
|
|
110
|
+
stunServers: this.options.stunServers,
|
|
111
|
+
onConnected: () => this.handlePeerConnected(),
|
|
112
|
+
onDisconnected: () => this.handlePeerDisconnected(),
|
|
113
|
+
onError: (err) => this.handleError(err),
|
|
114
|
+
onReconnecting: (attempt) => {
|
|
115
|
+
this.isConnecting = true;
|
|
116
|
+
this.isOpen = false;
|
|
117
|
+
// Clear old data channel reference - new one will be created/received
|
|
118
|
+
this.dataChannel = null;
|
|
119
|
+
this.onReconnectingCallback?.(attempt);
|
|
120
|
+
},
|
|
121
|
+
onReconnected: (attempt) => this.handleReconnected(attempt),
|
|
122
|
+
// Setup data channel/handler before signaling begins
|
|
123
|
+
onPeerConnectionCreated: (pc) => {
|
|
124
|
+
if (this.isInitiator) {
|
|
125
|
+
// Initiator: Create data channel before offer is sent
|
|
126
|
+
console.log('[DataChannelHandler] Creating data channel before offer');
|
|
127
|
+
this.dataChannel = pc.createDataChannel(channelId);
|
|
128
|
+
this.dataChannel.binaryType = 'arraybuffer';
|
|
129
|
+
} else {
|
|
130
|
+
// Responder: Set up ondatachannel handler BEFORE receiving offer
|
|
131
|
+
// This ensures we don't miss the datachannel event
|
|
132
|
+
console.log('[DataChannelHandler] Setting up ondatachannel handler');
|
|
133
|
+
pc.ondatachannel = (event) => {
|
|
134
|
+
console.log('[DataChannelHandler] Received data channel from initiator');
|
|
135
|
+
this.dataChannel = event.channel;
|
|
136
|
+
this.dataChannel.binaryType = 'arraybuffer';
|
|
137
|
+
this.attachDataChannelHandlers(this.dataChannel, () => {
|
|
138
|
+
// No-op: Channel setup is complete. Handler registration and callbacks
|
|
139
|
+
// are managed inside attachDataChannelHandlers.
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
this.pcManager = new PeerConnectionManager(pcConfig, this.twinMessaging, {
|
|
147
|
+
connectionTimeout: this.options.connectionTimeout,
|
|
148
|
+
initialRetryDelay: this.options.initialRetryDelay,
|
|
149
|
+
maxRetryDelay: this.options.maxRetryDelay,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const pc = await this.pcManager.connect();
|
|
153
|
+
await this.setupDataChannel(pc);
|
|
154
|
+
|
|
155
|
+
return this.createPhygridDataChannel();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Close the data channel and clean up
|
|
160
|
+
*/
|
|
161
|
+
close(): void {
|
|
162
|
+
if (this.isClosed) return;
|
|
163
|
+
|
|
164
|
+
this.isClosed = true;
|
|
165
|
+
this.isOpen = false;
|
|
166
|
+
|
|
167
|
+
if (this.dataChannel) {
|
|
168
|
+
try {
|
|
169
|
+
this.dataChannel.close();
|
|
170
|
+
} catch (err) {
|
|
171
|
+
console.error('[DataChannelHandler] Error closing data channel:', err);
|
|
172
|
+
}
|
|
173
|
+
this.dataChannel = null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (this.pcManager) {
|
|
177
|
+
this.pcManager.close();
|
|
178
|
+
this.pcManager = null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.notifyCloseListeners();
|
|
182
|
+
this.messageListeners.clear();
|
|
183
|
+
this.closeListeners.clear();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ===========================================================================
|
|
187
|
+
// Private Methods
|
|
188
|
+
// ===========================================================================
|
|
189
|
+
|
|
190
|
+
private async setupDataChannel(pc: RTCPeerConnection): Promise<void> {
|
|
191
|
+
return new Promise((resolve) => {
|
|
192
|
+
// Data channel was already created/received in onPeerConnectionCreated
|
|
193
|
+
// Just need to attach handlers if not already done
|
|
194
|
+
if (this.dataChannel) {
|
|
195
|
+
this.attachDataChannelHandlers(this.dataChannel, resolve);
|
|
196
|
+
} else if (this.isInitiator) {
|
|
197
|
+
// Fallback: create data channel now (shouldn't happen normally)
|
|
198
|
+
const channelId = `channel-${this.targetTwinId}`;
|
|
199
|
+
this.dataChannel = pc.createDataChannel(channelId);
|
|
200
|
+
this.dataChannel.binaryType = 'arraybuffer';
|
|
201
|
+
this.attachDataChannelHandlers(this.dataChannel, resolve);
|
|
202
|
+
} else {
|
|
203
|
+
// Responder: ondatachannel handler should already be set,
|
|
204
|
+
// but it may not have fired yet - we'll resolve when it does
|
|
205
|
+
const existingHandler = pc.ondatachannel;
|
|
206
|
+
pc.ondatachannel = (event) => {
|
|
207
|
+
existingHandler?.call(pc, event);
|
|
208
|
+
resolve();
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private attachDataChannelHandlers(dc: RTCDataChannel, onReady: () => void): void {
|
|
215
|
+
dc.onopen = () => {
|
|
216
|
+
this.isOpen = true;
|
|
217
|
+
this.isConnecting = false;
|
|
218
|
+
this.onConnectedCallback?.();
|
|
219
|
+
onReady();
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
dc.onmessage = (event) => {
|
|
223
|
+
this.handleMessage(event.data);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
dc.onclose = () => {
|
|
227
|
+
this.isOpen = false;
|
|
228
|
+
if (!this.isClosed) {
|
|
229
|
+
this.onDisconnectedCallback?.();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
dc.onerror = (event) => {
|
|
234
|
+
const error = new Error(`DataChannel error: ${(event as any).error?.message || 'Unknown error'}`);
|
|
235
|
+
this.handleError(error);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// If already open (can happen on reconnect), resolve immediately
|
|
239
|
+
if (dc.readyState === 'open') {
|
|
240
|
+
this.isOpen = true;
|
|
241
|
+
this.isConnecting = false;
|
|
242
|
+
onReady();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private handleMessage(data: string | ArrayBuffer): void {
|
|
247
|
+
let parsedData = data;
|
|
248
|
+
|
|
249
|
+
// Try to parse JSON strings
|
|
250
|
+
if (typeof data === 'string') {
|
|
251
|
+
try {
|
|
252
|
+
parsedData = JSON.parse(data);
|
|
253
|
+
} catch {
|
|
254
|
+
// Not JSON, use as-is
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.messageListeners.forEach((listener) => {
|
|
259
|
+
try {
|
|
260
|
+
listener(parsedData);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.error('[DataChannelHandler] Error in message listener:', err);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private handlePeerConnected(): void {
|
|
268
|
+
// No-op: Peer connection is established but we don't need to do anything here.
|
|
269
|
+
// DataChannel setup is handled by onPeerConnectionCreated callback.
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private handlePeerDisconnected(): void {
|
|
273
|
+
this.isOpen = false;
|
|
274
|
+
this.onDisconnectedCallback?.();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private handleReconnected(attempt: number): void {
|
|
278
|
+
// Re-setup data channel after reconnection
|
|
279
|
+
const pc = this.pcManager?.getPeerConnection();
|
|
280
|
+
if (pc) {
|
|
281
|
+
this.setupDataChannel(pc).catch((err) => {
|
|
282
|
+
console.error('[DataChannelHandler] Error re-setting up data channel:', err);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
this.onReconnectedCallback?.(attempt);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private handleError(error: Error): void {
|
|
289
|
+
console.error('[DataChannelHandler] DataChannel error:', error);
|
|
290
|
+
this.onErrorCallback?.(error);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
private notifyCloseListeners(): void {
|
|
295
|
+
this.closeListeners.forEach((listener) => {
|
|
296
|
+
try {
|
|
297
|
+
listener();
|
|
298
|
+
} catch (err) {
|
|
299
|
+
console.error('[DataChannelHandler] Error in close listener:', err);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private createPhygridDataChannel(): PhygridDataChannel {
|
|
305
|
+
return {
|
|
306
|
+
send: (data: string | ArrayBuffer | object) => {
|
|
307
|
+
let messageToSend: string | ArrayBuffer;
|
|
308
|
+
|
|
309
|
+
if (typeof data === 'object' && !(data instanceof ArrayBuffer)) {
|
|
310
|
+
messageToSend = JSON.stringify(data);
|
|
311
|
+
} else {
|
|
312
|
+
messageToSend = data as string | ArrayBuffer;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (this.dataChannel?.readyState === 'open') {
|
|
316
|
+
try {
|
|
317
|
+
this.dataChannel.send(messageToSend as any);
|
|
318
|
+
} catch (err) {
|
|
319
|
+
console.error('[DataChannelHandler] Error sending message:', err);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// If not open, silently drop the message - no buffering
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
onMessage: (callback: (data: any) => void) => {
|
|
326
|
+
this.messageListeners.add(callback);
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
offMessage: (callback: (data: any) => void) => {
|
|
330
|
+
this.messageListeners.delete(callback);
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
onClose: (callback: () => void) => {
|
|
334
|
+
this.closeListeners.add(callback);
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
offClose: (callback: () => void) => {
|
|
338
|
+
this.closeListeners.delete(callback);
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
close: () => {
|
|
342
|
+
this.close();
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
isOpen: () => {
|
|
346
|
+
return this.isOpen && this.dataChannel?.readyState === 'open';
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
isConnecting: () => {
|
|
350
|
+
return this.isConnecting;
|
|
351
|
+
},
|
|
352
|
+
|
|
353
|
+
getTargetTwinId: () => {
|
|
354
|
+
return this.targetTwinId;
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
getChannelName: () => {
|
|
358
|
+
return this.channelName;
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebRTC Module Exports
|
|
3
|
+
*
|
|
4
|
+
* This module provides WebRTC functionality for peer-to-peer
|
|
5
|
+
* DataChannel and MediaStream connections between twins.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Main manager class
|
|
9
|
+
export { WebRTCManager } from './webrtc-manager';
|
|
10
|
+
|
|
11
|
+
// Handler classes (for advanced usage)
|
|
12
|
+
export { DataChannelHandler } from './data-channel-handler';
|
|
13
|
+
export { MediaStreamHandler } from './media-stream-handler';
|
|
14
|
+
export { PeerConnectionManager } from './peer-connection-manager';
|
|
15
|
+
|
|
16
|
+
// Globals utilities
|
|
17
|
+
export { ensureWebRTCGlobals, isWebRTCAvailable, isWebRTCInitialized } from './webrtc-globals';
|
|
18
|
+
|
|
19
|
+
// Types
|
|
20
|
+
export type {
|
|
21
|
+
TwinMessagingInterface,
|
|
22
|
+
WebRTCManagerOptions,
|
|
23
|
+
WebRTCEvent,
|
|
24
|
+
WebRTCStandardEvent,
|
|
25
|
+
WebRTCVerboseEvent,
|
|
26
|
+
WebRTCEventData,
|
|
27
|
+
WebRTCEventCallback,
|
|
28
|
+
PhygridDataChannel,
|
|
29
|
+
PhygridMediaStream,
|
|
30
|
+
MediaStreamOptions,
|
|
31
|
+
ExtendedMediaStreamTrack,
|
|
32
|
+
ConnectionType,
|
|
33
|
+
ConnectionState,
|
|
34
|
+
} from './types';
|
|
35
|
+
|
|
36
|
+
export { DEFAULT_WEBRTC_OPTIONS } from './types';
|