@xtr-dev/rondevu-client 0.18.7 → 0.18.8
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/answerer-connection.d.ts +44 -0
- package/dist/answerer-connection.js +145 -0
- package/dist/connection-config.d.ts +21 -0
- package/dist/connection-config.js +30 -0
- package/dist/connection-events.d.ts +78 -0
- package/dist/connection-events.js +16 -0
- package/dist/connection.d.ts +148 -0
- package/dist/connection.js +481 -0
- package/dist/exponential-backoff.d.ts +30 -0
- package/dist/exponential-backoff.js +46 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +7 -0
- package/dist/message-buffer.d.ts +55 -0
- package/dist/message-buffer.js +106 -0
- package/dist/offerer-connection.d.ts +50 -0
- package/dist/offerer-connection.js +193 -0
- package/dist/rondevu.d.ts +77 -64
- package/dist/rondevu.js +185 -290
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Answerer-side WebRTC connection with answer creation and offer processing
|
|
3
|
+
*/
|
|
4
|
+
import { RondevuConnection } from './connection.js';
|
|
5
|
+
import { RondevuAPI } from './api.js';
|
|
6
|
+
import { ConnectionConfig } from './connection-config.js';
|
|
7
|
+
export interface AnswererOptions {
|
|
8
|
+
api: RondevuAPI;
|
|
9
|
+
serviceFqn: string;
|
|
10
|
+
offerId: string;
|
|
11
|
+
offerSdp: string;
|
|
12
|
+
rtcConfig?: RTCConfiguration;
|
|
13
|
+
config?: Partial<ConnectionConfig>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Answerer connection - processes offers and creates answers
|
|
17
|
+
*/
|
|
18
|
+
export declare class AnswererConnection extends RondevuConnection {
|
|
19
|
+
private api;
|
|
20
|
+
private serviceFqn;
|
|
21
|
+
private offerId;
|
|
22
|
+
private offerSdp;
|
|
23
|
+
constructor(options: AnswererOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Initialize the connection by processing offer and creating answer
|
|
26
|
+
*/
|
|
27
|
+
initialize(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Handle local ICE candidate generation
|
|
30
|
+
*/
|
|
31
|
+
protected onLocalIceCandidate(candidate: RTCIceCandidate): void;
|
|
32
|
+
/**
|
|
33
|
+
* Poll for remote ICE candidates (from offerer)
|
|
34
|
+
*/
|
|
35
|
+
protected pollIceCandidates(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Attempt to reconnect
|
|
38
|
+
*/
|
|
39
|
+
protected attemptReconnect(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Get the offer ID we're answering
|
|
42
|
+
*/
|
|
43
|
+
getOfferId(): string;
|
|
44
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Answerer-side WebRTC connection with answer creation and offer processing
|
|
3
|
+
*/
|
|
4
|
+
import { RondevuConnection } from './connection.js';
|
|
5
|
+
import { ConnectionState } from './connection-events.js';
|
|
6
|
+
/**
|
|
7
|
+
* Answerer connection - processes offers and creates answers
|
|
8
|
+
*/
|
|
9
|
+
export class AnswererConnection extends RondevuConnection {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super(options.rtcConfig, options.config);
|
|
12
|
+
this.api = options.api;
|
|
13
|
+
this.serviceFqn = options.serviceFqn;
|
|
14
|
+
this.offerId = options.offerId;
|
|
15
|
+
this.offerSdp = options.offerSdp;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Initialize the connection by processing offer and creating answer
|
|
19
|
+
*/
|
|
20
|
+
async initialize() {
|
|
21
|
+
this.debug('Initializing answerer connection');
|
|
22
|
+
// Create peer connection
|
|
23
|
+
this.createPeerConnection();
|
|
24
|
+
if (!this.pc)
|
|
25
|
+
throw new Error('Peer connection not created');
|
|
26
|
+
// Setup ondatachannel handler BEFORE setting remote description
|
|
27
|
+
// This is critical to avoid race conditions
|
|
28
|
+
this.pc.ondatachannel = (event) => {
|
|
29
|
+
this.debug('Received data channel');
|
|
30
|
+
this.dc = event.channel;
|
|
31
|
+
this.setupDataChannelHandlers(this.dc);
|
|
32
|
+
};
|
|
33
|
+
// Start connection timeout
|
|
34
|
+
this.startConnectionTimeout();
|
|
35
|
+
// Set remote description (offer)
|
|
36
|
+
await this.pc.setRemoteDescription({
|
|
37
|
+
type: 'offer',
|
|
38
|
+
sdp: this.offerSdp,
|
|
39
|
+
});
|
|
40
|
+
this.transitionTo(ConnectionState.SIGNALING, 'Offer received, creating answer');
|
|
41
|
+
// Create and set local description (answer)
|
|
42
|
+
const answer = await this.pc.createAnswer();
|
|
43
|
+
await this.pc.setLocalDescription(answer);
|
|
44
|
+
this.debug('Answer created, sending to server');
|
|
45
|
+
// Send answer to server
|
|
46
|
+
await this.api.answerOffer(this.serviceFqn, this.offerId, answer.sdp);
|
|
47
|
+
this.debug('Answer sent successfully');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Handle local ICE candidate generation
|
|
51
|
+
*/
|
|
52
|
+
onLocalIceCandidate(candidate) {
|
|
53
|
+
this.debug('Generated local ICE candidate');
|
|
54
|
+
// For answerer, we add ICE candidates to the offer
|
|
55
|
+
// The server will make them available for the offerer to poll
|
|
56
|
+
this.api
|
|
57
|
+
.addOfferIceCandidates(this.serviceFqn, this.offerId, [
|
|
58
|
+
{
|
|
59
|
+
candidate: candidate.candidate,
|
|
60
|
+
sdpMLineIndex: candidate.sdpMLineIndex,
|
|
61
|
+
sdpMid: candidate.sdpMid,
|
|
62
|
+
},
|
|
63
|
+
])
|
|
64
|
+
.catch((error) => {
|
|
65
|
+
this.debug('Failed to send ICE candidate:', error);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Poll for remote ICE candidates (from offerer)
|
|
70
|
+
*/
|
|
71
|
+
pollIceCandidates() {
|
|
72
|
+
this.api
|
|
73
|
+
.getOfferIceCandidates(this.serviceFqn, this.offerId, this.lastIcePollTime)
|
|
74
|
+
.then((result) => {
|
|
75
|
+
if (result.candidates.length > 0) {
|
|
76
|
+
this.debug(`Received ${result.candidates.length} remote ICE candidates`);
|
|
77
|
+
for (const iceCandidate of result.candidates) {
|
|
78
|
+
// Only process ICE candidates from the offerer
|
|
79
|
+
if (iceCandidate.role === 'offerer' && iceCandidate.candidate && this.pc) {
|
|
80
|
+
const candidate = iceCandidate.candidate;
|
|
81
|
+
this.pc
|
|
82
|
+
.addIceCandidate(new RTCIceCandidate(candidate))
|
|
83
|
+
.then(() => {
|
|
84
|
+
this.emit('ice:candidate:remote', new RTCIceCandidate(candidate));
|
|
85
|
+
})
|
|
86
|
+
.catch((error) => {
|
|
87
|
+
this.debug('Failed to add ICE candidate:', error);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// Update last poll time
|
|
91
|
+
if (iceCandidate.createdAt > this.lastIcePollTime) {
|
|
92
|
+
this.lastIcePollTime = iceCandidate.createdAt;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
.catch((error) => {
|
|
98
|
+
this.debug('Failed to poll ICE candidates:', error);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Attempt to reconnect
|
|
103
|
+
*/
|
|
104
|
+
attemptReconnect() {
|
|
105
|
+
this.debug('Attempting to reconnect');
|
|
106
|
+
// For answerer, we need to fetch a new offer and create a new answer
|
|
107
|
+
// Clean up old connection
|
|
108
|
+
if (this.pc) {
|
|
109
|
+
this.pc.close();
|
|
110
|
+
this.pc = null;
|
|
111
|
+
}
|
|
112
|
+
if (this.dc) {
|
|
113
|
+
this.dc.close();
|
|
114
|
+
this.dc = null;
|
|
115
|
+
}
|
|
116
|
+
// Fetch new offer from service
|
|
117
|
+
this.api
|
|
118
|
+
.getService(this.serviceFqn)
|
|
119
|
+
.then((service) => {
|
|
120
|
+
if (!service || !service.offers || service.offers.length === 0) {
|
|
121
|
+
throw new Error('No offers available for reconnection');
|
|
122
|
+
}
|
|
123
|
+
// Pick a random offer
|
|
124
|
+
const offer = service.offers[Math.floor(Math.random() * service.offers.length)];
|
|
125
|
+
this.offerId = offer.offerId;
|
|
126
|
+
this.offerSdp = offer.sdp;
|
|
127
|
+
// Reinitialize with new offer
|
|
128
|
+
return this.initialize();
|
|
129
|
+
})
|
|
130
|
+
.then(() => {
|
|
131
|
+
this.emit('reconnect:success');
|
|
132
|
+
})
|
|
133
|
+
.catch((error) => {
|
|
134
|
+
this.debug('Reconnection failed:', error);
|
|
135
|
+
this.emit('reconnect:failed', error);
|
|
136
|
+
this.scheduleReconnect();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the offer ID we're answering
|
|
141
|
+
*/
|
|
142
|
+
getOfferId() {
|
|
143
|
+
return this.offerId;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection configuration interfaces and defaults
|
|
3
|
+
*/
|
|
4
|
+
export interface ConnectionConfig {
|
|
5
|
+
connectionTimeout: number;
|
|
6
|
+
iceGatheringTimeout: number;
|
|
7
|
+
reconnectEnabled: boolean;
|
|
8
|
+
maxReconnectAttempts: number;
|
|
9
|
+
reconnectBackoffBase: number;
|
|
10
|
+
reconnectBackoffMax: number;
|
|
11
|
+
reconnectJitter: number;
|
|
12
|
+
bufferEnabled: boolean;
|
|
13
|
+
maxBufferSize: number;
|
|
14
|
+
maxBufferAge: number;
|
|
15
|
+
preserveBufferOnClose: boolean;
|
|
16
|
+
icePollingInterval: number;
|
|
17
|
+
icePollingTimeout: number;
|
|
18
|
+
debug: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_CONNECTION_CONFIG: ConnectionConfig;
|
|
21
|
+
export declare function mergeConnectionConfig(userConfig?: Partial<ConnectionConfig>): ConnectionConfig;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection configuration interfaces and defaults
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_CONNECTION_CONFIG = {
|
|
5
|
+
// Timeouts
|
|
6
|
+
connectionTimeout: 30000, // 30 seconds
|
|
7
|
+
iceGatheringTimeout: 10000, // 10 seconds
|
|
8
|
+
// Reconnection
|
|
9
|
+
reconnectEnabled: true,
|
|
10
|
+
maxReconnectAttempts: 5, // 5 attempts before giving up
|
|
11
|
+
reconnectBackoffBase: 1000, // Start with 1 second
|
|
12
|
+
reconnectBackoffMax: 30000, // Cap at 30 seconds
|
|
13
|
+
reconnectJitter: 0.1, // 10% jitter
|
|
14
|
+
// Message buffering
|
|
15
|
+
bufferEnabled: true,
|
|
16
|
+
maxBufferSize: 100, // 100 messages
|
|
17
|
+
maxBufferAge: 60000, // 1 minute
|
|
18
|
+
preserveBufferOnClose: false, // Clear buffer on close
|
|
19
|
+
// ICE polling
|
|
20
|
+
icePollingInterval: 500, // Poll every 500ms
|
|
21
|
+
icePollingTimeout: 30000, // Stop polling after 30s
|
|
22
|
+
// Debug
|
|
23
|
+
debug: false,
|
|
24
|
+
};
|
|
25
|
+
export function mergeConnectionConfig(userConfig) {
|
|
26
|
+
return {
|
|
27
|
+
...DEFAULT_CONNECTION_CONFIG,
|
|
28
|
+
...userConfig,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript event type definitions for RondevuConnection
|
|
3
|
+
*/
|
|
4
|
+
export declare enum ConnectionState {
|
|
5
|
+
INITIALIZING = "initializing",// Creating peer connection
|
|
6
|
+
GATHERING = "gathering",// ICE gathering in progress
|
|
7
|
+
SIGNALING = "signaling",// Exchanging offer/answer
|
|
8
|
+
CHECKING = "checking",// ICE connectivity checks
|
|
9
|
+
CONNECTING = "connecting",// ICE connection attempts
|
|
10
|
+
CONNECTED = "connected",// Data channel open, working
|
|
11
|
+
DISCONNECTED = "disconnected",// Temporarily disconnected
|
|
12
|
+
RECONNECTING = "reconnecting",// Attempting reconnection
|
|
13
|
+
FAILED = "failed",// Connection failed
|
|
14
|
+
CLOSED = "closed"
|
|
15
|
+
}
|
|
16
|
+
export interface BufferedMessage {
|
|
17
|
+
id: string;
|
|
18
|
+
data: string | ArrayBuffer | Blob;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
attempts: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ReconnectInfo {
|
|
23
|
+
attempt: number;
|
|
24
|
+
delay: number;
|
|
25
|
+
maxAttempts: number;
|
|
26
|
+
}
|
|
27
|
+
export interface StateChangeInfo {
|
|
28
|
+
oldState: ConnectionState;
|
|
29
|
+
newState: ConnectionState;
|
|
30
|
+
reason?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Event map for RondevuConnection
|
|
34
|
+
* Maps event names to their payload types
|
|
35
|
+
*/
|
|
36
|
+
export interface ConnectionEventMap {
|
|
37
|
+
'state:changed': [StateChangeInfo];
|
|
38
|
+
'connecting': [];
|
|
39
|
+
'connected': [];
|
|
40
|
+
'disconnected': [reason?: string];
|
|
41
|
+
'failed': [error: Error];
|
|
42
|
+
'closed': [reason?: string];
|
|
43
|
+
'reconnect:scheduled': [ReconnectInfo];
|
|
44
|
+
'reconnect:attempting': [attempt: number];
|
|
45
|
+
'reconnect:success': [];
|
|
46
|
+
'reconnect:failed': [error: Error];
|
|
47
|
+
'reconnect:exhausted': [attempts: number];
|
|
48
|
+
'message': [data: string | ArrayBuffer | Blob];
|
|
49
|
+
'message:sent': [data: string | ArrayBuffer | Blob, buffered: boolean];
|
|
50
|
+
'message:buffered': [data: string | ArrayBuffer | Blob];
|
|
51
|
+
'message:replayed': [message: BufferedMessage];
|
|
52
|
+
'message:buffer:overflow': [discardedMessage: BufferedMessage];
|
|
53
|
+
'message:buffer:expired': [message: BufferedMessage];
|
|
54
|
+
'ice:candidate:local': [candidate: RTCIceCandidate | null];
|
|
55
|
+
'ice:candidate:remote': [candidate: RTCIceCandidate | null];
|
|
56
|
+
'ice:connection:state': [state: RTCIceConnectionState];
|
|
57
|
+
'ice:gathering:state': [state: RTCIceGatheringState];
|
|
58
|
+
'ice:polling:started': [];
|
|
59
|
+
'ice:polling:stopped': [];
|
|
60
|
+
'answer:processed': [offerId: string, answererId: string];
|
|
61
|
+
'answer:duplicate': [offerId: string];
|
|
62
|
+
'datachannel:open': [];
|
|
63
|
+
'datachannel:close': [];
|
|
64
|
+
'datachannel:error': [error: Event];
|
|
65
|
+
'cleanup:started': [];
|
|
66
|
+
'cleanup:complete': [];
|
|
67
|
+
'connection:state': [state: RTCPeerConnectionState];
|
|
68
|
+
'connection:timeout': [];
|
|
69
|
+
'ice:gathering:timeout': [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Helper type to extract event names from the event map
|
|
73
|
+
*/
|
|
74
|
+
export type ConnectionEventName = keyof ConnectionEventMap;
|
|
75
|
+
/**
|
|
76
|
+
* Helper type to extract event arguments for a specific event
|
|
77
|
+
*/
|
|
78
|
+
export type ConnectionEventArgs<T extends ConnectionEventName> = ConnectionEventMap[T];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript event type definitions for RondevuConnection
|
|
3
|
+
*/
|
|
4
|
+
export var ConnectionState;
|
|
5
|
+
(function (ConnectionState) {
|
|
6
|
+
ConnectionState["INITIALIZING"] = "initializing";
|
|
7
|
+
ConnectionState["GATHERING"] = "gathering";
|
|
8
|
+
ConnectionState["SIGNALING"] = "signaling";
|
|
9
|
+
ConnectionState["CHECKING"] = "checking";
|
|
10
|
+
ConnectionState["CONNECTING"] = "connecting";
|
|
11
|
+
ConnectionState["CONNECTED"] = "connected";
|
|
12
|
+
ConnectionState["DISCONNECTED"] = "disconnected";
|
|
13
|
+
ConnectionState["RECONNECTING"] = "reconnecting";
|
|
14
|
+
ConnectionState["FAILED"] = "failed";
|
|
15
|
+
ConnectionState["CLOSED"] = "closed";
|
|
16
|
+
})(ConnectionState || (ConnectionState = {}));
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base connection class with state machine, reconnection, and message buffering
|
|
3
|
+
*/
|
|
4
|
+
import { EventEmitter } from 'eventemitter3';
|
|
5
|
+
import { ConnectionConfig } from './connection-config.js';
|
|
6
|
+
import { ConnectionState, ConnectionEventMap } from './connection-events.js';
|
|
7
|
+
import { ExponentialBackoff } from './exponential-backoff.js';
|
|
8
|
+
import { MessageBuffer } from './message-buffer.js';
|
|
9
|
+
/**
|
|
10
|
+
* Abstract base class for WebRTC connections with durability features
|
|
11
|
+
*/
|
|
12
|
+
export declare abstract class RondevuConnection extends EventEmitter<ConnectionEventMap> {
|
|
13
|
+
protected rtcConfig?: RTCConfiguration | undefined;
|
|
14
|
+
protected pc: RTCPeerConnection | null;
|
|
15
|
+
protected dc: RTCDataChannel | null;
|
|
16
|
+
protected state: ConnectionState;
|
|
17
|
+
protected config: ConnectionConfig;
|
|
18
|
+
protected messageBuffer: MessageBuffer | null;
|
|
19
|
+
protected backoff: ExponentialBackoff | null;
|
|
20
|
+
protected reconnectTimeout: ReturnType<typeof setTimeout> | null;
|
|
21
|
+
protected reconnectAttempts: number;
|
|
22
|
+
protected connectionTimeout: ReturnType<typeof setTimeout> | null;
|
|
23
|
+
protected iceGatheringTimeout: ReturnType<typeof setTimeout> | null;
|
|
24
|
+
protected icePollingInterval: ReturnType<typeof setInterval> | null;
|
|
25
|
+
protected lastIcePollTime: number;
|
|
26
|
+
protected answerProcessed: boolean;
|
|
27
|
+
protected answerSdpFingerprint: string | null;
|
|
28
|
+
constructor(rtcConfig?: RTCConfiguration | undefined, userConfig?: Partial<ConnectionConfig>);
|
|
29
|
+
/**
|
|
30
|
+
* Transition to a new state and emit events
|
|
31
|
+
*/
|
|
32
|
+
protected transitionTo(newState: ConnectionState, reason?: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Create and configure RTCPeerConnection
|
|
35
|
+
*/
|
|
36
|
+
protected createPeerConnection(): RTCPeerConnection;
|
|
37
|
+
/**
|
|
38
|
+
* Setup data channel event handlers
|
|
39
|
+
*/
|
|
40
|
+
protected setupDataChannelHandlers(dc: RTCDataChannel): void;
|
|
41
|
+
/**
|
|
42
|
+
* Handle local ICE candidate generation
|
|
43
|
+
*/
|
|
44
|
+
protected handleIceCandidate(event: RTCPeerConnectionIceEvent): void;
|
|
45
|
+
/**
|
|
46
|
+
* Handle ICE connection state changes (primary state driver)
|
|
47
|
+
*/
|
|
48
|
+
protected handleIceConnectionStateChange(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Handle connection state changes (backup validation)
|
|
51
|
+
*/
|
|
52
|
+
protected handleConnectionStateChange(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Handle ICE gathering state changes
|
|
55
|
+
*/
|
|
56
|
+
protected handleIceGatheringStateChange(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Handle data channel open event
|
|
59
|
+
*/
|
|
60
|
+
protected handleDataChannelOpen(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Handle data channel close event
|
|
63
|
+
*/
|
|
64
|
+
protected handleDataChannelClose(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Handle data channel error event
|
|
67
|
+
*/
|
|
68
|
+
protected handleDataChannelError(error: Event): void;
|
|
69
|
+
/**
|
|
70
|
+
* Handle incoming message
|
|
71
|
+
*/
|
|
72
|
+
protected handleMessage(event: MessageEvent): void;
|
|
73
|
+
/**
|
|
74
|
+
* Called when connection is successfully established
|
|
75
|
+
*/
|
|
76
|
+
protected onConnected(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Start ICE candidate polling
|
|
79
|
+
*/
|
|
80
|
+
protected startIcePolling(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Stop ICE candidate polling
|
|
83
|
+
*/
|
|
84
|
+
protected stopIcePolling(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Start connection timeout
|
|
87
|
+
*/
|
|
88
|
+
protected startConnectionTimeout(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Clear connection timeout
|
|
91
|
+
*/
|
|
92
|
+
protected clearConnectionTimeout(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Start ICE gathering timeout
|
|
95
|
+
*/
|
|
96
|
+
protected startIceGatheringTimeout(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Clear ICE gathering timeout
|
|
99
|
+
*/
|
|
100
|
+
protected clearIceGatheringTimeout(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Schedule reconnection attempt
|
|
103
|
+
*/
|
|
104
|
+
protected scheduleReconnect(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Cancel scheduled reconnection
|
|
107
|
+
*/
|
|
108
|
+
protected cancelReconnect(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Send a message directly (bypasses buffer)
|
|
111
|
+
*/
|
|
112
|
+
protected sendDirect(data: string | ArrayBuffer | Blob): void;
|
|
113
|
+
/**
|
|
114
|
+
* Send a message with automatic buffering
|
|
115
|
+
*/
|
|
116
|
+
send(data: string | ArrayBuffer | Blob): void;
|
|
117
|
+
/**
|
|
118
|
+
* Buffer a message for later delivery
|
|
119
|
+
*/
|
|
120
|
+
protected bufferMessage(data: string | ArrayBuffer | Blob): void;
|
|
121
|
+
/**
|
|
122
|
+
* Get current connection state
|
|
123
|
+
*/
|
|
124
|
+
getState(): ConnectionState;
|
|
125
|
+
/**
|
|
126
|
+
* Get the data channel
|
|
127
|
+
*/
|
|
128
|
+
getDataChannel(): RTCDataChannel | null;
|
|
129
|
+
/**
|
|
130
|
+
* Get the peer connection
|
|
131
|
+
*/
|
|
132
|
+
getPeerConnection(): RTCPeerConnection | null;
|
|
133
|
+
/**
|
|
134
|
+
* Close the connection
|
|
135
|
+
*/
|
|
136
|
+
close(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Complete cleanup of all resources
|
|
139
|
+
*/
|
|
140
|
+
protected cleanup(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Debug logging helper
|
|
143
|
+
*/
|
|
144
|
+
protected debug(...args: any[]): void;
|
|
145
|
+
protected abstract onLocalIceCandidate(candidate: RTCIceCandidate): void;
|
|
146
|
+
protected abstract pollIceCandidates(): void;
|
|
147
|
+
protected abstract attemptReconnect(): void;
|
|
148
|
+
}
|