@xtr-dev/rondevu-client 0.18.9 → 0.20.1

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 (40) hide show
  1. package/README.md +324 -47
  2. package/dist/{api.d.ts → api/client.d.ts} +17 -8
  3. package/dist/{api.js → api/client.js} +114 -81
  4. package/dist/{answerer-connection.d.ts → connections/answerer.d.ts} +13 -5
  5. package/dist/{answerer-connection.js → connections/answerer.js} +17 -32
  6. package/dist/{connection.d.ts → connections/base.d.ts} +26 -5
  7. package/dist/{connection.js → connections/base.js} +45 -4
  8. package/dist/{offerer-connection.d.ts → connections/offerer.d.ts} +30 -5
  9. package/dist/{offerer-connection.js → connections/offerer.js} +93 -32
  10. package/dist/core/index.d.ts +22 -0
  11. package/dist/core/index.js +17 -0
  12. package/dist/core/offer-pool.d.ts +94 -0
  13. package/dist/core/offer-pool.js +267 -0
  14. package/dist/{rondevu.d.ts → core/rondevu.d.ts} +7 -28
  15. package/dist/{rondevu.js → core/rondevu.js} +32 -175
  16. package/dist/{node-crypto-adapter.d.ts → crypto/node.d.ts} +1 -1
  17. package/dist/{web-crypto-adapter.d.ts → crypto/web.d.ts} +1 -1
  18. package/dist/utils/async-lock.d.ts +42 -0
  19. package/dist/utils/async-lock.js +75 -0
  20. package/dist/{message-buffer.d.ts → utils/message-buffer.d.ts} +1 -1
  21. package/package.json +3 -3
  22. package/dist/index.d.ts +0 -22
  23. package/dist/index.js +0 -17
  24. package/dist/rondevu-signaler.d.ts +0 -112
  25. package/dist/rondevu-signaler.js +0 -401
  26. /package/dist/{rpc-batcher.d.ts → api/batcher.d.ts} +0 -0
  27. /package/dist/{rpc-batcher.js → api/batcher.js} +0 -0
  28. /package/dist/{connection-config.d.ts → connections/config.d.ts} +0 -0
  29. /package/dist/{connection-config.js → connections/config.js} +0 -0
  30. /package/dist/{connection-events.d.ts → connections/events.d.ts} +0 -0
  31. /package/dist/{connection-events.js → connections/events.js} +0 -0
  32. /package/dist/{types.d.ts → core/types.d.ts} +0 -0
  33. /package/dist/{types.js → core/types.js} +0 -0
  34. /package/dist/{crypto-adapter.d.ts → crypto/adapter.d.ts} +0 -0
  35. /package/dist/{crypto-adapter.js → crypto/adapter.js} +0 -0
  36. /package/dist/{node-crypto-adapter.js → crypto/node.js} +0 -0
  37. /package/dist/{web-crypto-adapter.js → crypto/web.js} +0 -0
  38. /package/dist/{exponential-backoff.d.ts → utils/exponential-backoff.d.ts} +0 -0
  39. /package/dist/{exponential-backoff.js → utils/exponential-backoff.js} +0 -0
  40. /package/dist/{message-buffer.js → utils/message-buffer.js} +0 -0
@@ -1,7 +1,7 @@
1
- import { RondevuAPI } from './api.js';
1
+ import { RondevuAPI } from '../api/client.js';
2
2
  import { EventEmitter } from 'eventemitter3';
3
- import { OffererConnection } from './offerer-connection.js';
4
- import { AnswererConnection } from './answerer-connection.js';
3
+ import { AnswererConnection } from '../connections/answerer.js';
4
+ import { OfferPool } from './offer-pool.js';
5
5
  // ICE server presets
6
6
  export const ICE_SERVER_PRESETS = {
7
7
  'ipv4-turn': [
@@ -146,15 +146,7 @@ export class Rondevu extends EventEmitter {
146
146
  this.usernameClaimed = false;
147
147
  // Service management
148
148
  this.currentService = null;
149
- this.maxOffers = 0;
150
- this.offerFactory = null;
151
- this.ttl = Rondevu.DEFAULT_TTL_MS;
152
- this.activeConnections = new Map();
153
- // Polling
154
- this.filling = false;
155
- this.fillingSemaphore = false; // Semaphore to prevent concurrent fillOffers calls
156
- this.pollingInterval = null;
157
- this.lastPollTimestamp = 0;
149
+ this.offerPool = null;
158
150
  this.apiUrl = apiUrl;
159
151
  this.username = username;
160
152
  this.keypair = keypair;
@@ -297,160 +289,43 @@ export class Rondevu extends EventEmitter {
297
289
  async publishService(options) {
298
290
  const { service, maxOffers, offerFactory, ttl, connectionConfig } = options;
299
291
  this.currentService = service;
300
- this.maxOffers = maxOffers;
301
- this.offerFactory = offerFactory || this.defaultOfferFactory.bind(this);
302
- this.ttl = ttl || Rondevu.DEFAULT_TTL_MS;
303
292
  this.connectionConfig = connectionConfig;
304
- this.debug(`Publishing service: ${service} with maxOffers: ${maxOffers}`);
305
- this.usernameClaimed = true;
306
- }
307
- /**
308
- * Create a single offer and publish it to the server using OffererConnection
309
- */
310
- async createOffer() {
311
- if (!this.currentService || !this.offerFactory) {
312
- throw new Error('Service not published. Call publishService() first.');
313
- }
314
- const rtcConfig = {
315
- iceServers: this.iceServers
316
- };
317
293
  // Auto-append username to service
318
- const serviceFqn = `${this.currentService}@${this.username}`;
319
- this.debug('Creating new offer...');
320
- // 1. Create RTCPeerConnection using factory (for now, keep compatibility)
321
- const pc = new RTCPeerConnection(rtcConfig);
322
- // 2. Call the factory to create offer
323
- let dc;
324
- let offer;
325
- try {
326
- const factoryResult = await this.offerFactory(pc);
327
- dc = factoryResult.dc;
328
- offer = factoryResult.offer;
329
- }
330
- catch (err) {
331
- pc.close();
332
- throw err;
333
- }
334
- // 3. Publish to server to get offerId
335
- const result = await this.api.publishService({
336
- serviceFqn,
337
- offers: [{ sdp: offer.sdp }],
338
- ttl: this.ttl,
339
- signature: '',
340
- message: '',
341
- });
342
- const offerId = result.offers[0].offerId;
343
- // 4. Create OffererConnection instance with already-created PC and DC
344
- const connection = new OffererConnection({
294
+ const serviceFqn = `${service}@${this.username}`;
295
+ this.debug(`Publishing service: ${service} with maxOffers: ${maxOffers}`);
296
+ // Create OfferPool (but don't start it yet - call startFilling() to begin)
297
+ this.offerPool = new OfferPool({
345
298
  api: this.api,
346
299
  serviceFqn,
347
- offerId,
348
- pc, // Pass the peer connection from factory
349
- dc, // Pass the data channel from factory
350
- config: {
351
- ...this.connectionConfig,
352
- debug: this.debugEnabled,
353
- },
300
+ maxOffers,
301
+ offerFactory: offerFactory || this.defaultOfferFactory.bind(this),
302
+ ttl: ttl || Rondevu.DEFAULT_TTL_MS,
303
+ iceServers: this.iceServers,
304
+ connectionConfig,
305
+ debugEnabled: this.debugEnabled,
354
306
  });
355
- // Setup connection event handlers
356
- connection.on('connected', () => {
357
- this.debug(`Connection established for offer ${offerId}`);
307
+ // Forward events from OfferPool
308
+ this.offerPool.on('connection:opened', (offerId, connection) => {
358
309
  this.emit('connection:opened', offerId, connection);
359
310
  });
360
- connection.on('failed', (error) => {
361
- this.debug(`Connection failed for offer ${offerId}:`, error);
362
- this.activeConnections.delete(offerId);
363
- this.fillOffers(); // Replace failed offer
311
+ this.offerPool.on('offer:created', (offerId, serviceFqn) => {
312
+ this.emit('offer:created', offerId, serviceFqn);
364
313
  });
365
- connection.on('closed', () => {
366
- this.debug(`Connection closed for offer ${offerId}`);
367
- this.activeConnections.delete(offerId);
368
- this.fillOffers(); // Replace closed offer
314
+ this.offerPool.on('connection:rotated', (oldOfferId, newOfferId, connection) => {
315
+ this.emit('connection:rotated', oldOfferId, newOfferId, connection);
369
316
  });
370
- // Store active connection
371
- this.activeConnections.set(offerId, connection);
372
- // Initialize the connection
373
- await connection.initialize();
374
- this.debug(`Offer created: ${offerId}`);
375
- this.emit('offer:created', offerId, serviceFqn);
376
- }
377
- /**
378
- * Fill offers to reach maxOffers count with semaphore protection
379
- */
380
- async fillOffers() {
381
- if (!this.filling || !this.currentService)
382
- return;
383
- // Semaphore to prevent concurrent fills
384
- if (this.fillingSemaphore) {
385
- this.debug('fillOffers already in progress, skipping');
386
- return;
387
- }
388
- this.fillingSemaphore = true;
389
- try {
390
- const currentCount = this.activeConnections.size;
391
- const needed = this.maxOffers - currentCount;
392
- this.debug(`Filling offers: current=${currentCount}, needed=${needed}`);
393
- for (let i = 0; i < needed; i++) {
394
- try {
395
- await this.createOffer();
396
- }
397
- catch (err) {
398
- console.error('[Rondevu] Failed to create offer:', err);
399
- }
400
- }
401
- }
402
- finally {
403
- this.fillingSemaphore = false;
404
- }
405
- }
406
- /**
407
- * Poll for answers and ICE candidates (internal use for automatic offer management)
408
- */
409
- async pollInternal() {
410
- if (!this.filling)
411
- return;
412
- try {
413
- const result = await this.api.poll(this.lastPollTimestamp);
414
- // Process answers - delegate to OffererConnections
415
- for (const answer of result.answers) {
416
- const connection = this.activeConnections.get(answer.offerId);
417
- if (connection) {
418
- try {
419
- await connection.processAnswer(answer.sdp, answer.answererId);
420
- this.lastPollTimestamp = Math.max(this.lastPollTimestamp, answer.answeredAt);
421
- // Create replacement offer
422
- this.fillOffers();
423
- }
424
- catch (err) {
425
- this.debug(`Failed to process answer for offer ${answer.offerId}:`, err);
426
- }
427
- }
428
- }
429
- }
430
- catch (err) {
431
- console.error('[Rondevu] Polling error:', err);
432
- }
317
+ this.usernameClaimed = true;
433
318
  }
434
319
  /**
435
320
  * Start filling offers and polling for answers/ICE
436
321
  * Call this after publishService() to begin accepting connections
437
322
  */
438
323
  async startFilling() {
439
- if (this.filling) {
440
- this.debug('Already filling');
441
- return;
442
- }
443
- if (!this.currentService) {
324
+ if (!this.offerPool) {
444
325
  throw new Error('No service published. Call publishService() first.');
445
326
  }
446
327
  this.debug('Starting offer filling and polling');
447
- this.filling = true;
448
- // Fill initial offers
449
- await this.fillOffers();
450
- // Start polling
451
- this.pollingInterval = setInterval(() => {
452
- this.pollInternal();
453
- }, Rondevu.POLLING_INTERVAL_MS);
328
+ await this.offerPool.start();
454
329
  }
455
330
  /**
456
331
  * Stop filling offers and polling
@@ -458,26 +333,14 @@ export class Rondevu extends EventEmitter {
458
333
  */
459
334
  stopFilling() {
460
335
  this.debug('Stopping offer filling and polling');
461
- this.filling = false;
462
- this.fillingSemaphore = false;
463
- // Stop polling
464
- if (this.pollingInterval) {
465
- clearInterval(this.pollingInterval);
466
- this.pollingInterval = null;
467
- }
468
- // Close all active connections
469
- for (const [offerId, connection] of this.activeConnections.entries()) {
470
- this.debug(`Closing connection ${offerId}`);
471
- connection.close();
472
- }
473
- this.activeConnections.clear();
336
+ this.offerPool?.stop();
474
337
  }
475
338
  /**
476
339
  * Get the count of active offers
477
340
  * @returns Number of active offers
478
341
  */
479
342
  getOfferCount() {
480
- return this.activeConnections.size;
343
+ return this.offerPool?.getOfferCount() ?? 0;
481
344
  }
482
345
  /**
483
346
  * Check if an offer is currently connected
@@ -485,20 +348,15 @@ export class Rondevu extends EventEmitter {
485
348
  * @returns True if the offer exists and is connected
486
349
  */
487
350
  isConnected(offerId) {
488
- const connection = this.activeConnections.get(offerId);
489
- return connection ? connection.getState() === 'connected' : false;
351
+ return this.offerPool?.isConnected(offerId) ?? false;
490
352
  }
491
353
  /**
492
354
  * Disconnect all active offers
493
355
  * Similar to stopFilling() but doesn't stop the polling/filling process
494
356
  */
495
- async disconnectAll() {
357
+ disconnectAll() {
496
358
  this.debug('Disconnecting all offers');
497
- for (const [offerId, connection] of this.activeConnections.entries()) {
498
- this.debug(`Closing connection ${offerId}`);
499
- connection.close();
500
- }
501
- this.activeConnections.clear();
359
+ this.offerPool?.disconnectAll();
502
360
  }
503
361
  /**
504
362
  * Get the current service status
@@ -507,9 +365,7 @@ export class Rondevu extends EventEmitter {
507
365
  getServiceStatus() {
508
366
  return {
509
367
  active: this.currentService !== null,
510
- offerCount: this.activeConnections.size,
511
- maxOffers: this.maxOffers,
512
- filling: this.filling
368
+ offerCount: this.offerPool?.getOfferCount() ?? 0
513
369
  };
514
370
  }
515
371
  /**
@@ -706,7 +562,7 @@ export class Rondevu extends EventEmitter {
706
562
  * Get active connections (for offerer side)
707
563
  */
708
564
  getActiveConnections() {
709
- return this.activeConnections;
565
+ return this.offerPool?.getActiveConnections() ?? new Map();
710
566
  }
711
567
  /**
712
568
  * Get all active offers (legacy compatibility)
@@ -714,7 +570,8 @@ export class Rondevu extends EventEmitter {
714
570
  */
715
571
  getActiveOffers() {
716
572
  const offers = [];
717
- for (const [offerId, connection] of this.activeConnections.entries()) {
573
+ const connections = this.offerPool?.getActiveConnections() ?? new Map();
574
+ for (const [offerId, connection] of connections.entries()) {
718
575
  const pc = connection.getPeerConnection();
719
576
  const dc = connection.getDataChannel();
720
577
  if (pc) {
@@ -2,7 +2,7 @@
2
2
  * Node.js Crypto adapter for Node.js environments
3
3
  * Requires Node.js 19+ or Node.js 18 with --experimental-global-webcrypto flag
4
4
  */
5
- import { CryptoAdapter, Keypair } from './crypto-adapter.js';
5
+ import { CryptoAdapter, Keypair } from './adapter.js';
6
6
  /**
7
7
  * Node.js Crypto implementation using Node.js built-in APIs
8
8
  * Uses Buffer for base64 encoding and crypto.randomBytes for random generation
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Web Crypto adapter for browser environments
3
3
  */
4
- import { CryptoAdapter, Keypair } from './crypto-adapter.js';
4
+ import { CryptoAdapter, Keypair } from './adapter.js';
5
5
  /**
6
6
  * Web Crypto implementation using browser APIs
7
7
  * Uses btoa/atob for base64 encoding and crypto.getRandomValues for random bytes
@@ -0,0 +1,42 @@
1
+ /**
2
+ * AsyncLock provides a mutual exclusion primitive for asynchronous operations.
3
+ * Ensures only one async operation can proceed at a time while queuing others.
4
+ */
5
+ export declare class AsyncLock {
6
+ private locked;
7
+ private queue;
8
+ /**
9
+ * Acquire the lock. If already locked, waits until released.
10
+ * @returns Promise that resolves when lock is acquired
11
+ */
12
+ acquire(): Promise<void>;
13
+ /**
14
+ * Release the lock. If others are waiting, grants lock to next in queue.
15
+ */
16
+ release(): void;
17
+ /**
18
+ * Run a function with the lock acquired, automatically releasing after.
19
+ * This is the recommended way to use AsyncLock to prevent forgetting to release.
20
+ *
21
+ * @param fn - Async function to run with lock held
22
+ * @returns Promise resolving to the function's return value
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const lock = new AsyncLock()
27
+ * const result = await lock.run(async () => {
28
+ * // Critical section - only one caller at a time
29
+ * return await doSomething()
30
+ * })
31
+ * ```
32
+ */
33
+ run<T>(fn: () => Promise<T>): Promise<T>;
34
+ /**
35
+ * Check if lock is currently held
36
+ */
37
+ isLocked(): boolean;
38
+ /**
39
+ * Get number of operations waiting for the lock
40
+ */
41
+ getQueueLength(): number;
42
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * AsyncLock provides a mutual exclusion primitive for asynchronous operations.
3
+ * Ensures only one async operation can proceed at a time while queuing others.
4
+ */
5
+ export class AsyncLock {
6
+ constructor() {
7
+ this.locked = false;
8
+ this.queue = [];
9
+ }
10
+ /**
11
+ * Acquire the lock. If already locked, waits until released.
12
+ * @returns Promise that resolves when lock is acquired
13
+ */
14
+ async acquire() {
15
+ if (!this.locked) {
16
+ this.locked = true;
17
+ return;
18
+ }
19
+ // Lock is held, wait in queue
20
+ return new Promise(resolve => {
21
+ this.queue.push(resolve);
22
+ });
23
+ }
24
+ /**
25
+ * Release the lock. If others are waiting, grants lock to next in queue.
26
+ */
27
+ release() {
28
+ const next = this.queue.shift();
29
+ if (next) {
30
+ // Grant lock to next waiter
31
+ next();
32
+ }
33
+ else {
34
+ // No waiters, mark as unlocked
35
+ this.locked = false;
36
+ }
37
+ }
38
+ /**
39
+ * Run a function with the lock acquired, automatically releasing after.
40
+ * This is the recommended way to use AsyncLock to prevent forgetting to release.
41
+ *
42
+ * @param fn - Async function to run with lock held
43
+ * @returns Promise resolving to the function's return value
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const lock = new AsyncLock()
48
+ * const result = await lock.run(async () => {
49
+ * // Critical section - only one caller at a time
50
+ * return await doSomething()
51
+ * })
52
+ * ```
53
+ */
54
+ async run(fn) {
55
+ await this.acquire();
56
+ try {
57
+ return await fn();
58
+ }
59
+ finally {
60
+ this.release();
61
+ }
62
+ }
63
+ /**
64
+ * Check if lock is currently held
65
+ */
66
+ isLocked() {
67
+ return this.locked;
68
+ }
69
+ /**
70
+ * Get number of operations waiting for the lock
71
+ */
72
+ getQueueLength() {
73
+ return this.queue.length;
74
+ }
75
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Message buffering system for storing messages during disconnections
3
3
  */
4
- import { BufferedMessage } from './connection-events.js';
4
+ import { BufferedMessage } from '../connections/events.js';
5
5
  export interface MessageBufferConfig {
6
6
  maxSize: number;
7
7
  maxAge: number;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@xtr-dev/rondevu-client",
3
- "version": "0.18.9",
3
+ "version": "0.20.1",
4
4
  "description": "TypeScript client for Rondevu with durable WebRTC connections, automatic reconnection, and message queuing",
5
5
  "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "dist/core/index.js",
7
+ "types": "dist/core/index.d.ts",
8
8
  "scripts": {
9
9
  "build": "tsc",
10
10
  "typecheck": "tsc --noEmit",
package/dist/index.d.ts DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * @xtr-dev/rondevu-client
3
- * WebRTC peer signaling client
4
- */
5
- export { Rondevu, RondevuError, NetworkError, ValidationError, ConnectionError } from './rondevu.js';
6
- export { RondevuAPI } from './api.js';
7
- export { RpcBatcher } from './rpc-batcher.js';
8
- export { RondevuConnection } from './connection.js';
9
- export { OffererConnection } from './offerer-connection.js';
10
- export { AnswererConnection } from './answerer-connection.js';
11
- export { ExponentialBackoff } from './exponential-backoff.js';
12
- export { MessageBuffer } from './message-buffer.js';
13
- export { WebCryptoAdapter } from './web-crypto-adapter.js';
14
- export { NodeCryptoAdapter } from './node-crypto-adapter.js';
15
- export type { Signaler, Binnable, } from './types.js';
16
- export type { Keypair, OfferRequest, ServiceRequest, Service, ServiceOffer, IceCandidate, } from './api.js';
17
- export type { RondevuOptions, PublishServiceOptions, ConnectToServiceOptions, ConnectionContext, OfferContext, OfferFactory, ActiveOffer, FindServiceOptions, ServiceResult, PaginatedServiceResult } from './rondevu.js';
18
- export type { CryptoAdapter } from './crypto-adapter.js';
19
- export type { ConnectionConfig, } from './connection-config.js';
20
- export type { ConnectionState, BufferedMessage, ReconnectInfo, StateChangeInfo, ConnectionEventMap, ConnectionEventName, ConnectionEventArgs, } from './connection-events.js';
21
- export type { OffererOptions, } from './offerer-connection.js';
22
- export type { AnswererOptions, } from './answerer-connection.js';
package/dist/index.js DELETED
@@ -1,17 +0,0 @@
1
- /**
2
- * @xtr-dev/rondevu-client
3
- * WebRTC peer signaling client
4
- */
5
- export { Rondevu, RondevuError, NetworkError, ValidationError, ConnectionError } from './rondevu.js';
6
- export { RondevuAPI } from './api.js';
7
- export { RpcBatcher } from './rpc-batcher.js';
8
- // Export connection classes
9
- export { RondevuConnection } from './connection.js';
10
- export { OffererConnection } from './offerer-connection.js';
11
- export { AnswererConnection } from './answerer-connection.js';
12
- // Export utilities
13
- export { ExponentialBackoff } from './exponential-backoff.js';
14
- export { MessageBuffer } from './message-buffer.js';
15
- // Export crypto adapters
16
- export { WebCryptoAdapter } from './web-crypto-adapter.js';
17
- export { NodeCryptoAdapter } from './node-crypto-adapter.js';
@@ -1,112 +0,0 @@
1
- import { Signaler, Binnable } from './types.js';
2
- import { Rondevu } from './rondevu.js';
3
- export interface PollingConfig {
4
- initialInterval?: number;
5
- maxInterval?: number;
6
- backoffMultiplier?: number;
7
- maxRetries?: number;
8
- jitter?: boolean;
9
- }
10
- /**
11
- * RondevuSignaler - Handles WebRTC signaling via Rondevu service
12
- *
13
- * Manages offer/answer exchange and ICE candidate polling for establishing
14
- * WebRTC connections through the Rondevu signaling server.
15
- *
16
- * Supports configurable polling with exponential backoff and jitter to reduce
17
- * server load and prevent thundering herd issues.
18
- *
19
- * @example
20
- * ```typescript
21
- * const signaler = new RondevuSignaler(
22
- * rondevuService,
23
- * 'chat.app@1.0.0',
24
- * 'peer-username',
25
- * { initialInterval: 500, maxInterval: 5000, jitter: true }
26
- * )
27
- *
28
- * // For offerer:
29
- * await signaler.setOffer(offer)
30
- * signaler.addAnswerListener(answer => {
31
- * // Handle remote answer
32
- * })
33
- *
34
- * // For answerer:
35
- * signaler.addOfferListener(offer => {
36
- * // Handle remote offer
37
- * })
38
- * await signaler.setAnswer(answer)
39
- * ```
40
- */
41
- export declare class RondevuSignaler implements Signaler {
42
- private readonly rondevu;
43
- private readonly service;
44
- private readonly host?;
45
- private offerId;
46
- private serviceFqn;
47
- private offerListeners;
48
- private answerListeners;
49
- private iceListeners;
50
- private pollingTimeout;
51
- private icePollingTimeout;
52
- private lastPollTimestamp;
53
- private isPolling;
54
- private isOfferer;
55
- private pollingConfig;
56
- constructor(rondevu: Rondevu, service: string, host?: string | undefined, pollingConfig?: PollingConfig);
57
- /**
58
- * Publish an offer as a service
59
- * Used by the offerer to make their offer available
60
- */
61
- setOffer(offer: RTCSessionDescriptionInit): Promise<void>;
62
- /**
63
- * Send an answer to the offerer
64
- * Used by the answerer to respond to an offer
65
- */
66
- setAnswer(answer: RTCSessionDescriptionInit): Promise<void>;
67
- /**
68
- * Listen for incoming offers
69
- * Used by the answerer to receive offers from the offerer
70
- */
71
- addOfferListener(callback: (offer: RTCSessionDescriptionInit) => void): Binnable;
72
- /**
73
- * Listen for incoming answers
74
- * Used by the offerer to receive the answer from the answerer
75
- */
76
- addAnswerListener(callback: (answer: RTCSessionDescriptionInit) => void): Binnable;
77
- /**
78
- * Send an ICE candidate to the remote peer
79
- */
80
- addIceCandidate(candidate: RTCIceCandidate): Promise<void>;
81
- /**
82
- * Listen for ICE candidates from the remote peer
83
- */
84
- addListener(callback: (candidate: RTCIceCandidate) => void): Binnable;
85
- /**
86
- * Search for an offer from the host
87
- * Used by the answerer to find the offerer's service
88
- */
89
- private searchForOffer;
90
- /**
91
- * Start combined polling for answers and ICE candidates (offerer side)
92
- * Uses poll() for efficient batch polling
93
- */
94
- private startPolling;
95
- /**
96
- * Stop combined polling
97
- */
98
- private stopPolling;
99
- /**
100
- * Start polling for ICE candidates (answerer side only)
101
- * Answerers use the separate endpoint since they don't have offers to poll
102
- */
103
- private startIcePolling;
104
- /**
105
- * Stop polling for ICE candidates
106
- */
107
- private stopIcePolling;
108
- /**
109
- * Stop all polling and cleanup
110
- */
111
- dispose(): void;
112
- }