@xtr-dev/rondevu-client 0.12.4 → 0.17.0

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 (46) hide show
  1. package/README.md +100 -381
  2. package/dist/api.d.ts +75 -96
  3. package/dist/api.js +202 -243
  4. package/dist/crypto-adapter.d.ts +37 -0
  5. package/dist/crypto-adapter.js +4 -0
  6. package/dist/index.d.ts +8 -15
  7. package/dist/index.js +5 -8
  8. package/dist/node-crypto-adapter.d.ts +35 -0
  9. package/dist/node-crypto-adapter.js +80 -0
  10. package/dist/rondevu-signaler.d.ts +14 -12
  11. package/dist/rondevu-signaler.js +111 -95
  12. package/dist/rondevu.d.ts +329 -0
  13. package/dist/rondevu.js +648 -0
  14. package/dist/rpc-batcher.d.ts +61 -0
  15. package/dist/rpc-batcher.js +111 -0
  16. package/dist/types.d.ts +8 -21
  17. package/dist/types.js +4 -6
  18. package/dist/web-crypto-adapter.d.ts +16 -0
  19. package/dist/web-crypto-adapter.js +52 -0
  20. package/package.json +1 -1
  21. package/dist/bin.d.ts +0 -35
  22. package/dist/bin.js +0 -35
  23. package/dist/connection-manager.d.ts +0 -104
  24. package/dist/connection-manager.js +0 -324
  25. package/dist/connection.d.ts +0 -112
  26. package/dist/connection.js +0 -194
  27. package/dist/durable-connection.d.ts +0 -120
  28. package/dist/durable-connection.js +0 -244
  29. package/dist/event-bus.d.ts +0 -52
  30. package/dist/event-bus.js +0 -84
  31. package/dist/noop-signaler.d.ts +0 -14
  32. package/dist/noop-signaler.js +0 -27
  33. package/dist/quick-start.d.ts +0 -29
  34. package/dist/quick-start.js +0 -44
  35. package/dist/rondevu-context.d.ts +0 -10
  36. package/dist/rondevu-context.js +0 -20
  37. package/dist/rondevu-service.d.ts +0 -87
  38. package/dist/rondevu-service.js +0 -170
  39. package/dist/service-client.d.ts +0 -77
  40. package/dist/service-client.js +0 -158
  41. package/dist/service-host.d.ts +0 -67
  42. package/dist/service-host.js +0 -120
  43. package/dist/signaler.d.ts +0 -25
  44. package/dist/signaler.js +0 -89
  45. package/dist/webrtc-context.d.ts +0 -5
  46. package/dist/webrtc-context.js +0 -35
@@ -1,87 +0,0 @@
1
- import { RondevuAPI, Credentials, Keypair, Service } from './api.js';
2
- export interface RondevuServiceOptions {
3
- apiUrl: string;
4
- username: string;
5
- keypair?: Keypair;
6
- credentials?: Credentials;
7
- }
8
- export interface PublishServiceOptions {
9
- serviceFqn: string;
10
- offers: Array<{
11
- sdp: string;
12
- }>;
13
- ttl?: number;
14
- isPublic?: boolean;
15
- metadata?: Record<string, any>;
16
- }
17
- /**
18
- * RondevuService - High-level service management with automatic signature handling
19
- *
20
- * Provides a simplified API for:
21
- * - Username claiming with Ed25519 signatures
22
- * - Service publishing with automatic signature generation
23
- * - Keypair management
24
- *
25
- * @example
26
- * ```typescript
27
- * // Initialize service (generates keypair automatically)
28
- * const service = new RondevuService({
29
- * apiUrl: 'https://signal.example.com',
30
- * username: 'myusername',
31
- * })
32
- *
33
- * await service.initialize()
34
- *
35
- * // Claim username (one time)
36
- * await service.claimUsername()
37
- *
38
- * // Publish a service
39
- * const publishedService = await service.publishService({
40
- * serviceFqn: 'chat.app@1.0.0',
41
- * offers: [{ sdp: offerSdp }],
42
- * ttl: 300000,
43
- * isPublic: true,
44
- * })
45
- * ```
46
- */
47
- export declare class RondevuService {
48
- private readonly api;
49
- private readonly username;
50
- private keypair;
51
- private usernameClaimed;
52
- constructor(options: RondevuServiceOptions);
53
- /**
54
- * Initialize the service - generates keypair if not provided
55
- * Call this before using other methods
56
- */
57
- initialize(): Promise<void>;
58
- /**
59
- * Claim the username with Ed25519 signature
60
- * Should be called once before publishing services
61
- */
62
- claimUsername(): Promise<void>;
63
- /**
64
- * Publish a service with automatic signature generation
65
- */
66
- publishService(options: PublishServiceOptions): Promise<Service>;
67
- /**
68
- * Get the current keypair (for backup/storage)
69
- */
70
- getKeypair(): Keypair | null;
71
- /**
72
- * Get the username
73
- */
74
- getUsername(): string;
75
- /**
76
- * Get the public key
77
- */
78
- getPublicKey(): string | null;
79
- /**
80
- * Check if username has been claimed (checks with server)
81
- */
82
- isUsernameClaimed(): Promise<boolean>;
83
- /**
84
- * Access to underlying API for advanced operations
85
- */
86
- getAPI(): RondevuAPI;
87
- }
@@ -1,170 +0,0 @@
1
- import { RondevuAPI } from './api.js';
2
- /**
3
- * RondevuService - High-level service management with automatic signature handling
4
- *
5
- * Provides a simplified API for:
6
- * - Username claiming with Ed25519 signatures
7
- * - Service publishing with automatic signature generation
8
- * - Keypair management
9
- *
10
- * @example
11
- * ```typescript
12
- * // Initialize service (generates keypair automatically)
13
- * const service = new RondevuService({
14
- * apiUrl: 'https://signal.example.com',
15
- * username: 'myusername',
16
- * })
17
- *
18
- * await service.initialize()
19
- *
20
- * // Claim username (one time)
21
- * await service.claimUsername()
22
- *
23
- * // Publish a service
24
- * const publishedService = await service.publishService({
25
- * serviceFqn: 'chat.app@1.0.0',
26
- * offers: [{ sdp: offerSdp }],
27
- * ttl: 300000,
28
- * isPublic: true,
29
- * })
30
- * ```
31
- */
32
- export class RondevuService {
33
- constructor(options) {
34
- this.keypair = null;
35
- this.usernameClaimed = false;
36
- this.username = options.username;
37
- this.keypair = options.keypair || null;
38
- this.api = new RondevuAPI(options.apiUrl, options.credentials);
39
- console.log('[RondevuService] Constructor called:', {
40
- username: this.username,
41
- hasKeypair: !!this.keypair,
42
- publicKey: this.keypair?.publicKey
43
- });
44
- }
45
- /**
46
- * Initialize the service - generates keypair if not provided
47
- * Call this before using other methods
48
- */
49
- async initialize() {
50
- console.log('[RondevuService] Initialize called, hasKeypair:', !!this.keypair);
51
- if (!this.keypair) {
52
- console.log('[RondevuService] Generating new keypair...');
53
- this.keypair = await RondevuAPI.generateKeypair();
54
- console.log('[RondevuService] Generated keypair, publicKey:', this.keypair.publicKey);
55
- }
56
- else {
57
- console.log('[RondevuService] Using existing keypair, publicKey:', this.keypair.publicKey);
58
- }
59
- // Register with API if no credentials provided
60
- if (!this.api['credentials']) {
61
- const credentials = await this.api.register();
62
- this.api.setCredentials(credentials);
63
- }
64
- }
65
- /**
66
- * Claim the username with Ed25519 signature
67
- * Should be called once before publishing services
68
- */
69
- async claimUsername() {
70
- if (!this.keypair) {
71
- throw new Error('Service not initialized. Call initialize() first.');
72
- }
73
- // Check if username is already claimed
74
- const check = await this.api.checkUsername(this.username);
75
- if (!check.available) {
76
- // Verify it's claimed by us
77
- if (check.publicKey === this.keypair.publicKey) {
78
- this.usernameClaimed = true;
79
- return;
80
- }
81
- throw new Error(`Username "${this.username}" is already claimed by another user`);
82
- }
83
- // Generate signature for username claim
84
- const message = `claim:${this.username}:${Date.now()}`;
85
- const signature = await RondevuAPI.signMessage(message, this.keypair.privateKey);
86
- // Claim the username
87
- await this.api.claimUsername(this.username, this.keypair.publicKey, signature, message);
88
- this.usernameClaimed = true;
89
- }
90
- /**
91
- * Publish a service with automatic signature generation
92
- */
93
- async publishService(options) {
94
- if (!this.keypair) {
95
- throw new Error('Service not initialized. Call initialize() first.');
96
- }
97
- if (!this.usernameClaimed) {
98
- throw new Error('Username not claimed. Call claimUsername() first or the server will reject the service.');
99
- }
100
- const { serviceFqn, offers, ttl, isPublic, metadata } = options;
101
- // Generate signature for service publication
102
- const message = `publish:${this.username}:${serviceFqn}:${Date.now()}`;
103
- const signature = await RondevuAPI.signMessage(message, this.keypair.privateKey);
104
- // Create service request
105
- const serviceRequest = {
106
- username: this.username,
107
- serviceFqn,
108
- offers,
109
- signature,
110
- message,
111
- ttl,
112
- isPublic,
113
- metadata,
114
- };
115
- // Publish to server
116
- return await this.api.publishService(serviceRequest);
117
- }
118
- /**
119
- * Get the current keypair (for backup/storage)
120
- */
121
- getKeypair() {
122
- return this.keypair;
123
- }
124
- /**
125
- * Get the username
126
- */
127
- getUsername() {
128
- return this.username;
129
- }
130
- /**
131
- * Get the public key
132
- */
133
- getPublicKey() {
134
- return this.keypair?.publicKey || null;
135
- }
136
- /**
137
- * Check if username has been claimed (checks with server)
138
- */
139
- async isUsernameClaimed() {
140
- if (!this.keypair) {
141
- return false;
142
- }
143
- try {
144
- const check = await this.api.checkUsername(this.username);
145
- // Debug logging
146
- console.log('[RondevuService] Username check:', {
147
- username: this.username,
148
- available: check.available,
149
- serverPublicKey: check.publicKey,
150
- localPublicKey: this.keypair.publicKey,
151
- match: check.publicKey === this.keypair.publicKey
152
- });
153
- // Username is claimed if it's not available and owned by our public key
154
- const claimed = !check.available && check.publicKey === this.keypair.publicKey;
155
- // Update internal flag to match server state
156
- this.usernameClaimed = claimed;
157
- return claimed;
158
- }
159
- catch (err) {
160
- console.error('Failed to check username claim status:', err);
161
- return false;
162
- }
163
- }
164
- /**
165
- * Access to underlying API for advanced operations
166
- */
167
- getAPI() {
168
- return this.api;
169
- }
170
- }
@@ -1,77 +0,0 @@
1
- import { RondevuService } from './rondevu-service.js';
2
- import { RTCDurableConnection } from './durable-connection.js';
3
- import { EventBus } from './event-bus.js';
4
- export interface ServiceClientOptions {
5
- username: string;
6
- serviceFqn: string;
7
- rondevuService: RondevuService;
8
- autoReconnect?: boolean;
9
- maxReconnectAttempts?: number;
10
- rtcConfiguration?: RTCConfiguration;
11
- }
12
- export interface ServiceClientEvents {
13
- connected: RTCDurableConnection;
14
- disconnected: void;
15
- reconnecting: {
16
- attempt: number;
17
- maxAttempts: number;
18
- };
19
- error: Error;
20
- }
21
- /**
22
- * ServiceClient - High-level wrapper for connecting to a WebRTC service
23
- *
24
- * Simplifies client connection by handling:
25
- * - Service discovery
26
- * - Offer/answer exchange
27
- * - ICE candidate polling
28
- * - Automatic reconnection
29
- *
30
- * @example
31
- * ```typescript
32
- * const client = new ServiceClient({
33
- * username: 'host-user',
34
- * serviceFqn: 'chat.app@1.0.0',
35
- * rondevuService: myService
36
- * })
37
- *
38
- * client.events.on('connected', conn => {
39
- * conn.events.on('message', msg => console.log('Received:', msg))
40
- * conn.sendMessage('Hello from client!')
41
- * })
42
- *
43
- * await client.connect()
44
- * ```
45
- */
46
- export declare class ServiceClient {
47
- private options;
48
- events: EventBus<ServiceClientEvents>;
49
- private signaler;
50
- private webrtcContext;
51
- private connection;
52
- private autoReconnect;
53
- private maxReconnectAttempts;
54
- private reconnectAttempts;
55
- private isConnecting;
56
- constructor(options: ServiceClientOptions);
57
- /**
58
- * Connect to the service
59
- */
60
- connect(): Promise<RTCDurableConnection>;
61
- /**
62
- * Disconnect from the service
63
- */
64
- dispose(): void;
65
- /**
66
- * @deprecated Use dispose() instead
67
- */
68
- disconnect(): void;
69
- /**
70
- * Attempt to reconnect
71
- */
72
- private attemptReconnect;
73
- /**
74
- * Get the current connection
75
- */
76
- getConnection(): RTCDurableConnection | null;
77
- }
@@ -1,158 +0,0 @@
1
- import { RondevuSignaler } from './rondevu-signaler.js';
2
- import { WebRTCContext } from './webrtc-context.js';
3
- import { RTCDurableConnection } from './durable-connection.js';
4
- import { EventBus } from './event-bus.js';
5
- /**
6
- * ServiceClient - High-level wrapper for connecting to a WebRTC service
7
- *
8
- * Simplifies client connection by handling:
9
- * - Service discovery
10
- * - Offer/answer exchange
11
- * - ICE candidate polling
12
- * - Automatic reconnection
13
- *
14
- * @example
15
- * ```typescript
16
- * const client = new ServiceClient({
17
- * username: 'host-user',
18
- * serviceFqn: 'chat.app@1.0.0',
19
- * rondevuService: myService
20
- * })
21
- *
22
- * client.events.on('connected', conn => {
23
- * conn.events.on('message', msg => console.log('Received:', msg))
24
- * conn.sendMessage('Hello from client!')
25
- * })
26
- *
27
- * await client.connect()
28
- * ```
29
- */
30
- export class ServiceClient {
31
- constructor(options) {
32
- this.options = options;
33
- this.signaler = null;
34
- this.connection = null;
35
- this.reconnectAttempts = 0;
36
- this.isConnecting = false;
37
- this.events = new EventBus();
38
- this.webrtcContext = new WebRTCContext(options.rtcConfiguration);
39
- this.autoReconnect = options.autoReconnect !== undefined ? options.autoReconnect : true;
40
- this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
41
- }
42
- /**
43
- * Connect to the service
44
- */
45
- async connect() {
46
- if (this.isConnecting) {
47
- throw new Error('Connection already in progress');
48
- }
49
- if (this.connection) {
50
- throw new Error('Already connected. Disconnect first.');
51
- }
52
- this.isConnecting = true;
53
- try {
54
- // Create signaler
55
- this.signaler = new RondevuSignaler(this.options.rondevuService, this.options.serviceFqn, this.options.username);
56
- // Wait for remote offer from signaler
57
- const remoteOffer = await new Promise((resolve, reject) => {
58
- const timeout = setTimeout(() => {
59
- reject(new Error('Service discovery timeout'));
60
- }, 30000);
61
- this.signaler.addOfferListener((offer) => {
62
- clearTimeout(timeout);
63
- resolve(offer);
64
- });
65
- });
66
- // Create connection with remote offer (makes us the answerer)
67
- const connection = new RTCDurableConnection({
68
- context: this.webrtcContext,
69
- signaler: this.signaler,
70
- offer: remoteOffer
71
- });
72
- // Wait for connection to be ready
73
- await connection.ready;
74
- // Set up connection event listeners
75
- connection.events.on('state-change', (state) => {
76
- if (state === 'connected') {
77
- this.reconnectAttempts = 0;
78
- this.events.emit('connected', connection);
79
- }
80
- else if (state === 'disconnected') {
81
- this.events.emit('disconnected', undefined);
82
- if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
83
- this.attemptReconnect();
84
- }
85
- }
86
- });
87
- this.connection = connection;
88
- this.isConnecting = false;
89
- return connection;
90
- }
91
- catch (err) {
92
- this.isConnecting = false;
93
- const error = err instanceof Error ? err : new Error(String(err));
94
- this.events.emit('error', error);
95
- throw error;
96
- }
97
- }
98
- /**
99
- * Disconnect from the service
100
- */
101
- dispose() {
102
- if (this.signaler) {
103
- this.signaler.dispose();
104
- this.signaler = null;
105
- }
106
- if (this.connection) {
107
- this.connection.disconnect();
108
- this.connection = null;
109
- }
110
- this.isConnecting = false;
111
- this.reconnectAttempts = 0;
112
- }
113
- /**
114
- * @deprecated Use dispose() instead
115
- */
116
- disconnect() {
117
- this.dispose();
118
- }
119
- /**
120
- * Attempt to reconnect
121
- */
122
- async attemptReconnect() {
123
- this.reconnectAttempts++;
124
- this.events.emit('reconnecting', {
125
- attempt: this.reconnectAttempts,
126
- maxAttempts: this.maxReconnectAttempts
127
- });
128
- // Cleanup old connection
129
- if (this.signaler) {
130
- this.signaler.dispose();
131
- this.signaler = null;
132
- }
133
- if (this.connection) {
134
- this.connection = null;
135
- }
136
- // Wait a bit before reconnecting
137
- await new Promise(resolve => setTimeout(resolve, 1000 * this.reconnectAttempts));
138
- try {
139
- await this.connect();
140
- }
141
- catch (err) {
142
- console.error('Reconnection attempt failed:', err);
143
- if (this.reconnectAttempts < this.maxReconnectAttempts) {
144
- this.attemptReconnect();
145
- }
146
- else {
147
- const error = new Error('Max reconnection attempts reached');
148
- this.events.emit('error', error);
149
- }
150
- }
151
- }
152
- /**
153
- * Get the current connection
154
- */
155
- getConnection() {
156
- return this.connection;
157
- }
158
- }
@@ -1,67 +0,0 @@
1
- import { RondevuService } from './rondevu-service.js';
2
- import { RTCDurableConnection } from './durable-connection.js';
3
- import { EventBus } from './event-bus.js';
4
- export interface ServiceHostOptions {
5
- service: string;
6
- rondevuService: RondevuService;
7
- maxPeers?: number;
8
- ttl?: number;
9
- isPublic?: boolean;
10
- rtcConfiguration?: RTCConfiguration;
11
- metadata?: Record<string, any>;
12
- }
13
- export interface ServiceHostEvents {
14
- connection: RTCDurableConnection;
15
- error: Error;
16
- }
17
- /**
18
- * ServiceHost - High-level wrapper for hosting a WebRTC service
19
- *
20
- * Simplifies hosting by handling:
21
- * - Offer/answer exchange
22
- * - ICE candidate polling
23
- * - Connection pool management
24
- * - Automatic reconnection
25
- *
26
- * @example
27
- * ```typescript
28
- * const host = new ServiceHost({
29
- * service: 'chat.app@1.0.0',
30
- * rondevuService: myService,
31
- * maxPeers: 5
32
- * })
33
- *
34
- * host.events.on('connection', conn => {
35
- * conn.events.on('message', msg => console.log('Received:', msg))
36
- * conn.sendMessage('Hello!')
37
- * })
38
- *
39
- * await host.start()
40
- * ```
41
- */
42
- export declare class ServiceHost {
43
- private options;
44
- events: EventBus<ServiceHostEvents>;
45
- private signaler;
46
- private webrtcContext;
47
- private connections;
48
- private maxPeers;
49
- private running;
50
- constructor(options: ServiceHostOptions);
51
- /**
52
- * Start hosting the service
53
- */
54
- start(): Promise<void>;
55
- /**
56
- * Create the next connection for incoming peers
57
- */
58
- private createNextConnection;
59
- /**
60
- * Stop hosting the service
61
- */
62
- dispose(): void;
63
- /**
64
- * Get all active connections
65
- */
66
- getConnections(): RTCDurableConnection[];
67
- }
@@ -1,120 +0,0 @@
1
- import { RondevuSignaler } from './rondevu-signaler.js';
2
- import { WebRTCContext } from './webrtc-context.js';
3
- import { RTCDurableConnection } from './durable-connection.js';
4
- import { EventBus } from './event-bus.js';
5
- /**
6
- * ServiceHost - High-level wrapper for hosting a WebRTC service
7
- *
8
- * Simplifies hosting by handling:
9
- * - Offer/answer exchange
10
- * - ICE candidate polling
11
- * - Connection pool management
12
- * - Automatic reconnection
13
- *
14
- * @example
15
- * ```typescript
16
- * const host = new ServiceHost({
17
- * service: 'chat.app@1.0.0',
18
- * rondevuService: myService,
19
- * maxPeers: 5
20
- * })
21
- *
22
- * host.events.on('connection', conn => {
23
- * conn.events.on('message', msg => console.log('Received:', msg))
24
- * conn.sendMessage('Hello!')
25
- * })
26
- *
27
- * await host.start()
28
- * ```
29
- */
30
- export class ServiceHost {
31
- constructor(options) {
32
- this.options = options;
33
- this.signaler = null;
34
- this.connections = [];
35
- this.running = false;
36
- this.events = new EventBus();
37
- this.webrtcContext = new WebRTCContext(options.rtcConfiguration);
38
- this.maxPeers = options.maxPeers || 5;
39
- }
40
- /**
41
- * Start hosting the service
42
- */
43
- async start() {
44
- if (this.running) {
45
- throw new Error('ServiceHost already running');
46
- }
47
- this.running = true;
48
- // Create signaler
49
- this.signaler = new RondevuSignaler(this.options.rondevuService, this.options.service);
50
- // Create first connection (offerer)
51
- const connection = new RTCDurableConnection({
52
- context: this.webrtcContext,
53
- signaler: this.signaler,
54
- offer: null // null means we're the offerer
55
- });
56
- // Wait for connection to be ready
57
- await connection.ready;
58
- // Set up connection event listeners
59
- connection.events.on('state-change', (state) => {
60
- if (state === 'connected') {
61
- this.connections.push(connection);
62
- this.events.emit('connection', connection);
63
- // Create next connection if under maxPeers
64
- if (this.connections.length < this.maxPeers) {
65
- this.createNextConnection().catch(err => {
66
- console.error('Failed to create next connection:', err);
67
- this.events.emit('error', err);
68
- });
69
- }
70
- }
71
- else if (state === 'disconnected') {
72
- // Remove from connections list
73
- const index = this.connections.indexOf(connection);
74
- if (index > -1) {
75
- this.connections.splice(index, 1);
76
- }
77
- }
78
- });
79
- // Publish service with the offer
80
- const offer = connection.connection?.localDescription;
81
- if (!offer?.sdp) {
82
- throw new Error('Offer SDP is empty');
83
- }
84
- await this.signaler.setOffer(offer);
85
- }
86
- /**
87
- * Create the next connection for incoming peers
88
- */
89
- async createNextConnection() {
90
- if (!this.signaler || !this.running) {
91
- return;
92
- }
93
- // For now, we'll use the same offer for all connections
94
- // In a production scenario, you'd create multiple offers
95
- // This is a limitation of the current service model
96
- // which publishes one offer per service
97
- }
98
- /**
99
- * Stop hosting the service
100
- */
101
- dispose() {
102
- this.running = false;
103
- // Cleanup signaler
104
- if (this.signaler) {
105
- this.signaler.dispose();
106
- this.signaler = null;
107
- }
108
- // Disconnect all connections
109
- for (const conn of this.connections) {
110
- conn.disconnect();
111
- }
112
- this.connections = [];
113
- }
114
- /**
115
- * Get all active connections
116
- */
117
- getConnections() {
118
- return [...this.connections];
119
- }
120
- }
@@ -1,25 +0,0 @@
1
- import { Signaler } from './types.js';
2
- import { Binnable } from './bin.js';
3
- import { RondevuAPI } from './api.js';
4
- /**
5
- * RondevuSignaler - Handles ICE candidate exchange via Rondevu API
6
- * Uses polling to retrieve remote candidates
7
- */
8
- export declare class RondevuSignaler implements Signaler {
9
- private api;
10
- private offerId;
11
- constructor(api: RondevuAPI, offerId: string);
12
- addOfferListener(callback: (offer: RTCSessionDescriptionInit) => void): Binnable;
13
- addAnswerListener(callback: (answer: RTCSessionDescriptionInit) => void): Binnable;
14
- setOffer(offer: RTCSessionDescriptionInit): Promise<void>;
15
- setAnswer(answer: RTCSessionDescriptionInit): Promise<void>;
16
- /**
17
- * Send a local ICE candidate to signaling server
18
- */
19
- addIceCandidate(candidate: RTCIceCandidate): Promise<void>;
20
- /**
21
- * Poll for remote ICE candidates and call callback for each one
22
- * Returns cleanup function to stop polling
23
- */
24
- addListener(callback: (candidate: RTCIceCandidate) => void): Binnable;
25
- }