@xtr-dev/rondevu-client 0.7.6 → 0.7.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.
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ TypeScript/JavaScript client for Rondevu, providing topic-based peer discovery,
|
|
|
16
16
|
|
|
17
17
|
- **Topic-Based Discovery**: Find peers by topics (e.g., torrent infohashes)
|
|
18
18
|
- **Stateless Authentication**: No server-side sessions, portable credentials
|
|
19
|
+
- **Protected Connections**: Optional secret-protected offers for access control
|
|
19
20
|
- **Bloom Filters**: Efficient peer exclusion for repeated discoveries
|
|
20
21
|
- **Multi-Offer Management**: Create and manage multiple offers per peer
|
|
21
22
|
- **Complete WebRTC Signaling**: Full offer/answer and ICE candidate exchange
|
|
@@ -68,7 +69,8 @@ peer.on('datachannel', (channel) => {
|
|
|
68
69
|
// Create offer and advertise on topics
|
|
69
70
|
const offerId = await peer.createOffer({
|
|
70
71
|
topics: ['my-app', 'room-123'],
|
|
71
|
-
ttl: 300000 // 5 minutes
|
|
72
|
+
ttl: 300000, // 5 minutes
|
|
73
|
+
secret: 'my-secret-password' // Optional: protect offer (max 128 chars)
|
|
72
74
|
});
|
|
73
75
|
|
|
74
76
|
console.log('Offer created:', offerId);
|
|
@@ -121,11 +123,50 @@ if (offers.length > 0) {
|
|
|
121
123
|
|
|
122
124
|
// Answer the offer
|
|
123
125
|
await peer.answer(offer.id, offer.sdp, {
|
|
124
|
-
topics: offer.topics
|
|
126
|
+
topics: offer.topics,
|
|
127
|
+
secret: 'my-secret-password' // Required if offer.hasSecret is true
|
|
125
128
|
});
|
|
126
129
|
}
|
|
127
130
|
```
|
|
128
131
|
|
|
132
|
+
## Protected Offers
|
|
133
|
+
|
|
134
|
+
You can protect offers with a secret to control who can answer them. This is useful for private rooms or invite-only connections.
|
|
135
|
+
|
|
136
|
+
### Creating a Protected Offer
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const offerId = await peer.createOffer({
|
|
140
|
+
topics: ['private-room'],
|
|
141
|
+
secret: 'my-secret-password' // Max 128 characters
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Share the secret with authorized peers through a secure channel
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Answering a Protected Offer
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
const offers = await client.offers.findByTopic('private-room');
|
|
151
|
+
|
|
152
|
+
// Check if offer requires a secret
|
|
153
|
+
if (offers[0].hasSecret) {
|
|
154
|
+
console.log('This offer requires a secret');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Provide the secret when answering
|
|
158
|
+
await peer.answer(offers[0].id, offers[0].sdp, {
|
|
159
|
+
topics: offers[0].topics,
|
|
160
|
+
secret: 'my-secret-password' // Must match the offer's secret
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Notes:**
|
|
165
|
+
- The actual secret is never exposed in public API responses - only a `hasSecret` boolean flag
|
|
166
|
+
- Answerers must provide the correct secret, or the answer will be rejected
|
|
167
|
+
- Secrets are limited to 128 characters
|
|
168
|
+
- Use this for access control, not for cryptographic security (use end-to-end encryption for that)
|
|
169
|
+
|
|
129
170
|
## Connection Lifecycle
|
|
130
171
|
|
|
131
172
|
The `RondevuPeer` uses a state machine for connection management:
|
|
@@ -368,7 +409,8 @@ localStorage.setItem('rondevu-creds', JSON.stringify(creds));
|
|
|
368
409
|
const offers = await client.offers.create([{
|
|
369
410
|
sdp: 'v=0...', // Your WebRTC offer SDP
|
|
370
411
|
topics: ['movie-xyz', 'hd-content'],
|
|
371
|
-
ttl: 300000 // 5 minutes
|
|
412
|
+
ttl: 300000, // 5 minutes
|
|
413
|
+
secret: 'my-secret-password' // Optional: protect offer (max 128 chars)
|
|
372
414
|
}]);
|
|
373
415
|
|
|
374
416
|
// Discover peers by topic
|
|
@@ -433,7 +475,8 @@ const offers = await client.offers.create([
|
|
|
433
475
|
{
|
|
434
476
|
sdp: 'v=0...',
|
|
435
477
|
topics: ['topic-1', 'topic-2'],
|
|
436
|
-
ttl: 300000 // optional, default 5 minutes
|
|
478
|
+
ttl: 300000, // optional, default 5 minutes
|
|
479
|
+
secret: 'my-secret-password' // optional, max 128 chars
|
|
437
480
|
}
|
|
438
481
|
]);
|
|
439
482
|
```
|
|
@@ -462,13 +505,18 @@ Delete a specific offer.
|
|
|
462
505
|
await client.offers.delete(offerId);
|
|
463
506
|
```
|
|
464
507
|
|
|
465
|
-
#### `client.offers.answer(offerId, sdp)`
|
|
508
|
+
#### `client.offers.answer(offerId, sdp, secret?)`
|
|
466
509
|
Answer an offer (locks it to answerer).
|
|
467
510
|
|
|
468
511
|
```typescript
|
|
469
|
-
await client.offers.answer(offerId, answerSdp);
|
|
512
|
+
await client.offers.answer(offerId, answerSdp, 'my-secret-password');
|
|
470
513
|
```
|
|
471
514
|
|
|
515
|
+
**Parameters:**
|
|
516
|
+
- `offerId`: The offer ID to answer
|
|
517
|
+
- `sdp`: The WebRTC answer SDP
|
|
518
|
+
- `secret` (optional): Required if the offer has `hasSecret: true`
|
|
519
|
+
|
|
472
520
|
#### `client.offers.getAnswers()`
|
|
473
521
|
Poll for answers to your offers.
|
|
474
522
|
|
|
@@ -20,7 +20,7 @@ export class AnsweringState extends PeerState {
|
|
|
20
20
|
const answer = await this.peer.pc.createAnswer();
|
|
21
21
|
// Send answer to server BEFORE setLocalDescription
|
|
22
22
|
// This registers us as the answerer so ICE candidates will be accepted
|
|
23
|
-
await this.peer.offersApi.answer(offerId, answer.sdp);
|
|
23
|
+
await this.peer.offersApi.answer(offerId, answer.sdp, options.secret);
|
|
24
24
|
// Enable trickle ICE - set up handler before ICE gathering starts
|
|
25
25
|
this.setupIceCandidateHandler();
|
|
26
26
|
// Set local description - ICE gathering starts here
|
|
@@ -26,7 +26,8 @@ export class CreatingOfferState extends PeerState {
|
|
|
26
26
|
const offers = await this.peer.offersApi.create([{
|
|
27
27
|
sdp: offer.sdp,
|
|
28
28
|
topics: options.topics,
|
|
29
|
-
ttl: options.ttl || 300000
|
|
29
|
+
ttl: options.ttl || 300000,
|
|
30
|
+
secret: options.secret
|
|
30
31
|
}]);
|
|
31
32
|
const offerId = offers[0].id;
|
|
32
33
|
this.peer.offerId = offerId; // Now handler can send candidates
|
package/dist/peer/types.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface PeerOptions {
|
|
|
21
21
|
topics: string[];
|
|
22
22
|
/** How long the offer should live (milliseconds) */
|
|
23
23
|
ttl?: number;
|
|
24
|
+
/** Optional secret to protect the offer (max 128 characters) */
|
|
25
|
+
secret?: string;
|
|
24
26
|
/** Whether to create a data channel automatically (for offerer) */
|
|
25
27
|
createDataChannel?: boolean;
|
|
26
28
|
/** Label for the automatically created data channel */
|