werift 0.15.3 → 0.15.6
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/lib/common/src/promise.d.ts +4 -3
- package/lib/common/src/promise.js +11 -5
- package/lib/common/src/promise.js.map +1 -1
- package/lib/ice/src/dns/lookup.d.ts +9 -0
- package/lib/ice/src/dns/lookup.js +66 -0
- package/lib/ice/src/dns/lookup.js.map +1 -0
- package/lib/ice/src/ice.d.ts +2 -0
- package/lib/ice/src/ice.js +24 -24
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/transport.js +2 -1
- package/lib/ice/src/transport.js.map +1 -1
- package/lib/ice/src/utils.d.ts +1 -0
- package/lib/ice/src/utils.js +9 -1
- package/lib/ice/src/utils.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.js +1 -1
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.d.ts +3 -1
- package/lib/webrtc/src/media/rtpTransceiver.js +7 -1
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +8 -3
- package/lib/webrtc/src/peerConnection.js +134 -54
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sdp.d.ts +0 -2
- package/lib/webrtc/src/sdp.js +0 -7
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/transport/ice.d.ts +7 -1
- package/lib/webrtc/src/transport/ice.js +12 -3
- package/lib/webrtc/src/transport/ice.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +2 -1
- package/lib/webrtc/src/transport/sctp.js +1 -1
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +1 -1
- package/src/media/rtpReceiver.ts +1 -1
- package/src/media/rtpTransceiver.ts +7 -1
- package/src/peerConnection.ts +213 -128
- package/src/sdp.ts +0 -8
- package/src/transport/ice.ts +13 -3
- package/src/transport/sctp.ts +2 -1
package/src/peerConnection.ts
CHANGED
|
@@ -230,11 +230,19 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
230
230
|
|
|
231
231
|
async createOffer() {
|
|
232
232
|
await this.ensureCerts();
|
|
233
|
+
const description = this.buildOfferSdp();
|
|
234
|
+
return description.toJSON();
|
|
235
|
+
}
|
|
233
236
|
|
|
237
|
+
buildOfferSdp() {
|
|
234
238
|
this.transceivers.forEach((transceiver) => {
|
|
235
|
-
transceiver.codecs
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
if (transceiver.codecs.length === 0) {
|
|
240
|
+
transceiver.codecs = this.configuration.codecs[transceiver.kind];
|
|
241
|
+
}
|
|
242
|
+
if (transceiver.headerExtensions.length === 0) {
|
|
243
|
+
transceiver.headerExtensions =
|
|
244
|
+
this.configuration.headerExtensions[transceiver.kind];
|
|
245
|
+
}
|
|
238
246
|
});
|
|
239
247
|
|
|
240
248
|
const description = new SessionDescription();
|
|
@@ -253,22 +261,24 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
253
261
|
return;
|
|
254
262
|
}
|
|
255
263
|
if (m.kind === "application") {
|
|
264
|
+
if (!this.sctpTransport) {
|
|
265
|
+
throw new Error("sctpTransport not found");
|
|
266
|
+
}
|
|
267
|
+
this.sctpTransport.mLineIndex = i;
|
|
256
268
|
description.media.push(
|
|
257
|
-
createMediaDescriptionForSctp(this.sctpTransport
|
|
269
|
+
createMediaDescriptionForSctp(this.sctpTransport)
|
|
258
270
|
);
|
|
259
271
|
} else {
|
|
260
272
|
const transceiver = this.getTransceiverByMid(mid);
|
|
261
273
|
if (!transceiver) {
|
|
262
|
-
|
|
263
|
-
return;
|
|
274
|
+
throw new Error("transceiver not found");
|
|
264
275
|
}
|
|
265
276
|
transceiver.mLineIndex = i;
|
|
266
277
|
description.media.push(
|
|
267
278
|
createMediaDescriptionForTransceiver(
|
|
268
279
|
transceiver,
|
|
269
280
|
this.cname,
|
|
270
|
-
transceiver.direction
|
|
271
|
-
mid
|
|
281
|
+
transceiver.direction
|
|
272
282
|
)
|
|
273
283
|
);
|
|
274
284
|
}
|
|
@@ -279,26 +289,27 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
279
289
|
.filter((t) => !description.media.find((m) => m.rtp.muxId === t.mid))
|
|
280
290
|
.forEach((transceiver) => {
|
|
281
291
|
transceiver.mLineIndex = description.media.length;
|
|
292
|
+
if (transceiver.mid == undefined) {
|
|
293
|
+
transceiver.mid = allocateMid(this.seenMid) + "_srtp";
|
|
294
|
+
}
|
|
282
295
|
description.media.push(
|
|
283
296
|
createMediaDescriptionForTransceiver(
|
|
284
297
|
transceiver,
|
|
285
298
|
this.cname,
|
|
286
|
-
transceiver.direction
|
|
287
|
-
allocateMid(this.seenMid)
|
|
299
|
+
transceiver.direction
|
|
288
300
|
)
|
|
289
301
|
);
|
|
290
302
|
});
|
|
291
303
|
|
|
292
304
|
if (
|
|
293
305
|
this.sctpTransport &&
|
|
294
|
-
!description.media.find((m) =>
|
|
306
|
+
!description.media.find((m) => m.kind === "application")
|
|
295
307
|
) {
|
|
296
|
-
description.media.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
);
|
|
308
|
+
this.sctpTransport.mLineIndex = description.media.length;
|
|
309
|
+
if (this.sctpTransport.mid == undefined) {
|
|
310
|
+
this.sctpTransport.mid = allocateMid(this.seenMid) + "_sctp";
|
|
311
|
+
}
|
|
312
|
+
description.media.push(createMediaDescriptionForSctp(this.sctpTransport));
|
|
302
313
|
}
|
|
303
314
|
|
|
304
315
|
if (this.configuration.bundlePolicy !== "disable") {
|
|
@@ -309,7 +320,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
309
320
|
description.group.push(bundle);
|
|
310
321
|
}
|
|
311
322
|
|
|
312
|
-
return description
|
|
323
|
+
return description;
|
|
313
324
|
}
|
|
314
325
|
|
|
315
326
|
createDataChannel(
|
|
@@ -423,19 +434,38 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
423
434
|
|
|
424
435
|
iceTransport.iceGather.onIceCandidate = (candidate) => {
|
|
425
436
|
if (!this.localDescription) return;
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
437
|
+
|
|
438
|
+
if (
|
|
439
|
+
this.configuration.bundlePolicy === "max-bundle" ||
|
|
440
|
+
this.remoteIsBundled
|
|
441
|
+
) {
|
|
442
|
+
candidate.sdpMLineIndex = 0;
|
|
443
|
+
const media = this._localDescription?.media[0];
|
|
444
|
+
if (media) {
|
|
445
|
+
candidate.sdpMid = media.rtp.muxId;
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
const transceiver = this.transceivers.find(
|
|
449
|
+
(t) => t.dtlsTransport.iceTransport.id === iceTransport.id
|
|
450
|
+
);
|
|
451
|
+
if (transceiver) {
|
|
452
|
+
candidate.sdpMLineIndex = transceiver.mLineIndex;
|
|
453
|
+
candidate.sdpMid = transceiver.mid;
|
|
454
|
+
}
|
|
455
|
+
if (
|
|
456
|
+
this.sctpTransport?.dtlsTransport.iceTransport.id === iceTransport.id
|
|
457
|
+
) {
|
|
458
|
+
candidate.sdpMLineIndex = this.sctpTransport.mLineIndex;
|
|
459
|
+
candidate.sdpMid = this.sctpTransport.mid;
|
|
460
|
+
}
|
|
431
461
|
}
|
|
432
|
-
|
|
433
|
-
candidate.sdpMid = media.rtp.muxId;
|
|
462
|
+
|
|
434
463
|
candidate.foundation = "candidate:" + candidate.foundation;
|
|
435
464
|
|
|
436
465
|
this.onIceCandidate.execute(candidate.toJSON());
|
|
437
|
-
if (this.onicecandidate)
|
|
466
|
+
if (this.onicecandidate) {
|
|
438
467
|
this.onicecandidate({ candidate: candidate.toJSON() });
|
|
468
|
+
}
|
|
439
469
|
this.emit("icecandidate", { candidate });
|
|
440
470
|
};
|
|
441
471
|
|
|
@@ -540,10 +570,20 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
540
570
|
// for trickle ice
|
|
541
571
|
this.setLocal(description);
|
|
542
572
|
|
|
543
|
-
//
|
|
544
|
-
|
|
545
|
-
|
|
573
|
+
// connect transports
|
|
574
|
+
if (description.type === "answer") {
|
|
575
|
+
log("callee start connect");
|
|
576
|
+
this.connect().catch((err) => {
|
|
577
|
+
log("connect failed", err);
|
|
578
|
+
this.setConnectionState("failed");
|
|
579
|
+
});
|
|
546
580
|
}
|
|
581
|
+
|
|
582
|
+
// # gather candidates
|
|
583
|
+
await Promise.all(
|
|
584
|
+
this.iceTransports.map((iceTransport) => iceTransport.iceGather.gather())
|
|
585
|
+
);
|
|
586
|
+
|
|
547
587
|
description.media
|
|
548
588
|
.filter((m) => ["audio", "video"].includes(m.kind))
|
|
549
589
|
.forEach((m, i) => {
|
|
@@ -556,15 +596,6 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
556
596
|
|
|
557
597
|
this.setLocal(description);
|
|
558
598
|
|
|
559
|
-
// connect transports
|
|
560
|
-
if (description.type === "answer") {
|
|
561
|
-
log("callee start connect");
|
|
562
|
-
this.connect().catch((err) => {
|
|
563
|
-
log("connect failed", err);
|
|
564
|
-
this.setConnectionState("failed");
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
599
|
if (this.shouldNegotiationneeded) {
|
|
569
600
|
this.needNegotiation();
|
|
570
601
|
}
|
|
@@ -581,10 +612,54 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
581
612
|
}
|
|
582
613
|
}
|
|
583
614
|
|
|
615
|
+
private getTransportByMid(mid: string) {
|
|
616
|
+
let iceTransport: RTCIceTransport | undefined;
|
|
617
|
+
|
|
618
|
+
const transceiver = this.transceivers.find((t) => t.mid === mid);
|
|
619
|
+
if (transceiver) {
|
|
620
|
+
iceTransport = transceiver.dtlsTransport.iceTransport;
|
|
621
|
+
} else if (!iceTransport && this.sctpTransport?.mid === mid) {
|
|
622
|
+
iceTransport = this.sctpTransport?.dtlsTransport.iceTransport;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return iceTransport;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
private getTransportByMLineIndex(index: number) {
|
|
629
|
+
const sdp = this.buildOfferSdp();
|
|
630
|
+
const media = sdp.media[index];
|
|
631
|
+
if (!media) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const transport = this.getTransportByMid(media.rtp.muxId!);
|
|
635
|
+
|
|
636
|
+
return transport;
|
|
637
|
+
}
|
|
638
|
+
|
|
584
639
|
async addIceCandidate(candidateMessage: RTCIceCandidate) {
|
|
585
640
|
const candidate = IceCandidate.fromJSON(candidateMessage);
|
|
586
|
-
|
|
641
|
+
if (!candidate) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
let iceTransport: RTCIceTransport | undefined;
|
|
646
|
+
|
|
647
|
+
if (typeof candidate.sdpMid === "number") {
|
|
648
|
+
iceTransport = this.getTransportByMid(candidate.sdpMid);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (!iceTransport && typeof candidate.sdpMLineIndex === "number") {
|
|
652
|
+
iceTransport = this.getTransportByMLineIndex(candidate.sdpMLineIndex);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (!iceTransport) {
|
|
656
|
+
iceTransport = this.iceTransports[0];
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if (iceTransport) {
|
|
587
660
|
await iceTransport.addRemoteCandidate(candidate);
|
|
661
|
+
} else {
|
|
662
|
+
log("iceTransport not found", candidate);
|
|
588
663
|
}
|
|
589
664
|
}
|
|
590
665
|
|
|
@@ -666,6 +741,16 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
666
741
|
return receiveParameters;
|
|
667
742
|
}
|
|
668
743
|
|
|
744
|
+
get remoteIsBundled() {
|
|
745
|
+
const remoteSdp = this._remoteDescription;
|
|
746
|
+
if (!remoteSdp) return;
|
|
747
|
+
const bundle = remoteSdp.group.find(
|
|
748
|
+
(g) =>
|
|
749
|
+
g.semantic === "BUNDLE" && this.configuration.bundlePolicy !== "disable"
|
|
750
|
+
);
|
|
751
|
+
return bundle;
|
|
752
|
+
}
|
|
753
|
+
|
|
669
754
|
async setRemoteDescription(sessionDescription: {
|
|
670
755
|
type: "offer" | "answer";
|
|
671
756
|
sdp: string;
|
|
@@ -682,91 +767,93 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
682
767
|
this.pendingRemoteDescription = remoteSdp;
|
|
683
768
|
}
|
|
684
769
|
|
|
685
|
-
const bundle = remoteSdp.group.find(
|
|
686
|
-
(g) =>
|
|
687
|
-
g.semantic === "BUNDLE" && this.configuration.bundlePolicy !== "disable"
|
|
688
|
-
);
|
|
689
770
|
let bundleTransport: RTCDtlsTransport | undefined;
|
|
690
771
|
|
|
691
772
|
// # apply description
|
|
692
|
-
await Promise.all(
|
|
693
|
-
enumerate(remoteSdp.media).map(async ([i, remoteMedia]) => {
|
|
694
|
-
let dtlsTransport: RTCDtlsTransport | undefined;
|
|
695
|
-
|
|
696
|
-
if (["audio", "video"].includes(remoteMedia.kind)) {
|
|
697
|
-
let transceiver = this.transceivers.find(
|
|
698
|
-
(t) =>
|
|
699
|
-
t.kind === remoteMedia.kind &&
|
|
700
|
-
[undefined, remoteMedia.rtp.muxId].includes(t.mid)
|
|
701
|
-
);
|
|
702
|
-
if (!transceiver) {
|
|
703
|
-
// create remote transceiver
|
|
704
|
-
transceiver = this.addTransceiver(remoteMedia.kind, {
|
|
705
|
-
direction: "recvonly",
|
|
706
|
-
});
|
|
707
|
-
this.onRemoteTransceiverAdded.execute(transceiver);
|
|
708
|
-
}
|
|
709
773
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
bundleTransport = transceiver.dtlsTransport;
|
|
713
|
-
} else {
|
|
714
|
-
transceiver.setDtlsTransport(bundleTransport);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
774
|
+
const transports = enumerate(remoteSdp.media).map(([i, remoteMedia]) => {
|
|
775
|
+
let dtlsTransport: RTCDtlsTransport | undefined;
|
|
717
776
|
|
|
718
|
-
|
|
777
|
+
if (["audio", "video"].includes(remoteMedia.kind)) {
|
|
778
|
+
let transceiver = this.transceivers.find(
|
|
779
|
+
(t) =>
|
|
780
|
+
t.kind === remoteMedia.kind &&
|
|
781
|
+
[undefined, remoteMedia.rtp.muxId].includes(t.mid)
|
|
782
|
+
);
|
|
783
|
+
if (!transceiver) {
|
|
784
|
+
// create remote transceiver
|
|
785
|
+
transceiver = this.addTransceiver(remoteMedia.kind, {
|
|
786
|
+
direction: "recvonly",
|
|
787
|
+
});
|
|
788
|
+
transceiver.mid = remoteMedia.rtp.muxId;
|
|
789
|
+
this.onRemoteTransceiverAdded.execute(transceiver);
|
|
790
|
+
}
|
|
719
791
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
792
|
+
if (this.remoteIsBundled) {
|
|
793
|
+
if (!bundleTransport) {
|
|
794
|
+
bundleTransport = transceiver.dtlsTransport;
|
|
795
|
+
} else {
|
|
796
|
+
transceiver.setDtlsTransport(bundleTransport);
|
|
724
797
|
}
|
|
798
|
+
}
|
|
725
799
|
|
|
726
|
-
|
|
727
|
-
if (!bundleTransport) {
|
|
728
|
-
bundleTransport = this.sctpTransport.dtlsTransport;
|
|
729
|
-
} else {
|
|
730
|
-
this.sctpTransport.setDtlsTransport(bundleTransport);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
800
|
+
dtlsTransport = transceiver.dtlsTransport;
|
|
733
801
|
|
|
734
|
-
|
|
802
|
+
this.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
|
|
803
|
+
} else if (remoteMedia.kind === "application") {
|
|
804
|
+
if (!this.sctpTransport) {
|
|
805
|
+
this.sctpTransport = this.createSctpTransport();
|
|
806
|
+
this.sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
807
|
+
}
|
|
735
808
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
809
|
+
if (this.remoteIsBundled) {
|
|
810
|
+
if (!bundleTransport) {
|
|
811
|
+
bundleTransport = this.sctpTransport.dtlsTransport;
|
|
812
|
+
} else {
|
|
813
|
+
this.sctpTransport.setDtlsTransport(bundleTransport);
|
|
814
|
+
}
|
|
739
815
|
}
|
|
740
816
|
|
|
741
|
-
|
|
817
|
+
dtlsTransport = this.sctpTransport.dtlsTransport;
|
|
742
818
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
819
|
+
this.setRemoteSCTP(remoteMedia, this.sctpTransport, i);
|
|
820
|
+
} else {
|
|
821
|
+
throw new Error("invalid media kind");
|
|
822
|
+
}
|
|
746
823
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
824
|
+
const iceTransport = dtlsTransport.iceTransport;
|
|
825
|
+
|
|
826
|
+
if (remoteMedia.iceParams && remoteMedia.dtlsParams) {
|
|
827
|
+
iceTransport.setRemoteParams(remoteMedia.iceParams);
|
|
828
|
+
dtlsTransport.setRemoteParams(remoteMedia.dtlsParams);
|
|
829
|
+
|
|
830
|
+
// One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
|
|
831
|
+
// RFC 8445 S6.1.1
|
|
832
|
+
if (remoteMedia.iceParams?.iceLite) {
|
|
833
|
+
iceTransport.connection.iceControlling = true;
|
|
752
834
|
}
|
|
835
|
+
}
|
|
753
836
|
|
|
754
|
-
|
|
755
|
-
|
|
837
|
+
// # add ICE candidates
|
|
838
|
+
remoteMedia.iceCandidates.forEach(iceTransport.addRemoteCandidate);
|
|
756
839
|
|
|
757
|
-
|
|
840
|
+
if (remoteMedia.iceCandidatesComplete) {
|
|
841
|
+
iceTransport.addRemoteCandidate(undefined);
|
|
842
|
+
}
|
|
758
843
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
844
|
+
// # set DTLS role
|
|
845
|
+
if (remoteSdp.type === "answer" && remoteMedia.dtlsParams?.role) {
|
|
846
|
+
dtlsTransport.role =
|
|
847
|
+
remoteMedia.dtlsParams.role === "client" ? "server" : "client";
|
|
848
|
+
}
|
|
849
|
+
return iceTransport;
|
|
850
|
+
});
|
|
762
851
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
})
|
|
769
|
-
);
|
|
852
|
+
if (remoteSdp.type === "offer") {
|
|
853
|
+
this.setSignalingState("have-remote-offer");
|
|
854
|
+
} else if (remoteSdp.type === "answer") {
|
|
855
|
+
this.setSignalingState("stable");
|
|
856
|
+
}
|
|
770
857
|
|
|
771
858
|
// connect transports
|
|
772
859
|
if (remoteSdp.type === "answer") {
|
|
@@ -777,11 +864,11 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
777
864
|
});
|
|
778
865
|
}
|
|
779
866
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
867
|
+
await Promise.all(
|
|
868
|
+
transports.map(async (iceTransport) => {
|
|
869
|
+
await iceTransport.iceGather.gather();
|
|
870
|
+
})
|
|
871
|
+
);
|
|
785
872
|
|
|
786
873
|
this.negotiationneeded = false;
|
|
787
874
|
if (this.shouldNegotiationneeded) {
|
|
@@ -878,7 +965,8 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
878
965
|
|
|
879
966
|
private setRemoteSCTP(
|
|
880
967
|
remoteMedia: MediaDescription,
|
|
881
|
-
sctpTransport: RTCSctpTransport
|
|
968
|
+
sctpTransport: RTCSctpTransport,
|
|
969
|
+
mLineIndex: number
|
|
882
970
|
) {
|
|
883
971
|
// # configure sctp
|
|
884
972
|
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
@@ -887,6 +975,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
887
975
|
}
|
|
888
976
|
|
|
889
977
|
sctpTransport.setRemotePort(this.sctpRemotePort);
|
|
978
|
+
sctpTransport.mLineIndex = mLineIndex;
|
|
890
979
|
if (!sctpTransport.mid) {
|
|
891
980
|
sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
892
981
|
}
|
|
@@ -1075,6 +1164,12 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1075
1164
|
}
|
|
1076
1165
|
|
|
1077
1166
|
async createAnswer() {
|
|
1167
|
+
await this.ensureCerts();
|
|
1168
|
+
const description = this.buildAnswer();
|
|
1169
|
+
return description.toJSON();
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
private buildAnswer() {
|
|
1078
1173
|
this.assertNotClosed();
|
|
1079
1174
|
if (
|
|
1080
1175
|
!["have-remote-offer", "have-local-pranswer"].includes(
|
|
@@ -1087,8 +1182,6 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1087
1182
|
throw new Error("wrong state");
|
|
1088
1183
|
}
|
|
1089
1184
|
|
|
1090
|
-
await this.ensureCerts();
|
|
1091
|
-
|
|
1092
1185
|
const description = new SessionDescription();
|
|
1093
1186
|
addSDPHeader("answer", description);
|
|
1094
1187
|
|
|
@@ -1101,18 +1194,14 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1101
1194
|
media = createMediaDescriptionForTransceiver(
|
|
1102
1195
|
transceiver,
|
|
1103
1196
|
this.cname,
|
|
1104
|
-
andDirection(transceiver.direction, transceiver.offerDirection)
|
|
1105
|
-
transceiver.mid!
|
|
1197
|
+
andDirection(transceiver.direction, transceiver.offerDirection)
|
|
1106
1198
|
);
|
|
1107
1199
|
dtlsTransport = transceiver.dtlsTransport;
|
|
1108
1200
|
} else if (remoteMedia.kind === "application") {
|
|
1109
1201
|
if (!this.sctpTransport || !this.sctpTransport.mid) {
|
|
1110
1202
|
throw new Error("sctpTransport not found");
|
|
1111
1203
|
}
|
|
1112
|
-
media = createMediaDescriptionForSctp(
|
|
1113
|
-
this.sctpTransport,
|
|
1114
|
-
this.sctpTransport.mid
|
|
1115
|
-
);
|
|
1204
|
+
media = createMediaDescriptionForSctp(this.sctpTransport);
|
|
1116
1205
|
|
|
1117
1206
|
dtlsTransport = this.sctpTransport.dtlsTransport;
|
|
1118
1207
|
} else {
|
|
@@ -1145,7 +1234,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1145
1234
|
description.group.push(bundle);
|
|
1146
1235
|
}
|
|
1147
1236
|
|
|
1148
|
-
return description
|
|
1237
|
+
return description;
|
|
1149
1238
|
}
|
|
1150
1239
|
|
|
1151
1240
|
async close() {
|
|
@@ -1282,8 +1371,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1282
1371
|
export function createMediaDescriptionForTransceiver(
|
|
1283
1372
|
transceiver: RTCRtpTransceiver,
|
|
1284
1373
|
cname: string,
|
|
1285
|
-
direction: Direction
|
|
1286
|
-
mid: string
|
|
1374
|
+
direction: Direction
|
|
1287
1375
|
) {
|
|
1288
1376
|
const media = new MediaDescription(
|
|
1289
1377
|
transceiver.kind,
|
|
@@ -1296,7 +1384,7 @@ export function createMediaDescriptionForTransceiver(
|
|
|
1296
1384
|
media.rtp = {
|
|
1297
1385
|
codecs: transceiver.codecs,
|
|
1298
1386
|
headerExtensions: transceiver.headerExtensions,
|
|
1299
|
-
muxId: mid,
|
|
1387
|
+
muxId: transceiver.mid,
|
|
1300
1388
|
};
|
|
1301
1389
|
media.rtcpHost = "0.0.0.0";
|
|
1302
1390
|
media.rtcpPort = 9;
|
|
@@ -1325,10 +1413,7 @@ export function createMediaDescriptionForTransceiver(
|
|
|
1325
1413
|
return media;
|
|
1326
1414
|
}
|
|
1327
1415
|
|
|
1328
|
-
export function createMediaDescriptionForSctp(
|
|
1329
|
-
sctp: RTCSctpTransport,
|
|
1330
|
-
mid: string
|
|
1331
|
-
) {
|
|
1416
|
+
export function createMediaDescriptionForSctp(sctp: RTCSctpTransport) {
|
|
1332
1417
|
const media = new MediaDescription(
|
|
1333
1418
|
"application",
|
|
1334
1419
|
DISCARD_PORT,
|
|
@@ -1336,7 +1421,7 @@ export function createMediaDescriptionForSctp(
|
|
|
1336
1421
|
["webrtc-datachannel"]
|
|
1337
1422
|
);
|
|
1338
1423
|
media.sctpPort = sctp.port;
|
|
1339
|
-
media.rtp.muxId = mid;
|
|
1424
|
+
media.rtp.muxId = sctp.mid;
|
|
1340
1425
|
media.sctpCapabilities = RTCSctpTransport.getCapabilities();
|
|
1341
1426
|
|
|
1342
1427
|
addTransportDescription(media, sctp.dtlsTransport);
|
package/src/sdp.ts
CHANGED
|
@@ -611,14 +611,6 @@ export function candidateFromSdp(sdp: string) {
|
|
|
611
611
|
|
|
612
612
|
export class RTCSessionDescription {
|
|
613
613
|
constructor(public sdp: string, public type: "offer" | "answer") {}
|
|
614
|
-
|
|
615
|
-
get object() {
|
|
616
|
-
return SessionDescription.parse(this.sdp);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
static isThis(o: any) {
|
|
620
|
-
if (typeof o?.sdp === "string") return true;
|
|
621
|
-
}
|
|
622
614
|
}
|
|
623
615
|
|
|
624
616
|
export function addSDPHeader(
|
package/src/transport/ice.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import Event from "rx.mini";
|
|
2
|
+
import { v4 } from "uuid";
|
|
2
3
|
|
|
3
4
|
import { Candidate, Connection, IceOptions } from "../../../ice/src";
|
|
4
5
|
import { candidateFromSdp, candidateToSdp } from "../sdp";
|
|
5
6
|
|
|
6
7
|
export class RTCIceTransport {
|
|
8
|
+
readonly id = v4();
|
|
7
9
|
connection = this.gather.connection;
|
|
8
10
|
state: RTCIceConnectionState = "new";
|
|
9
11
|
|
|
@@ -41,12 +43,12 @@ export class RTCIceTransport {
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
addRemoteCandidate =
|
|
46
|
+
addRemoteCandidate = (candidate?: IceCandidate) => {
|
|
45
47
|
if (!this.connection.remoteCandidatesEnd) {
|
|
46
48
|
if (!candidate) {
|
|
47
|
-
|
|
49
|
+
return this.connection.addRemoteCandidate(undefined);
|
|
48
50
|
} else {
|
|
49
|
-
|
|
51
|
+
return this.connection.addRemoteCandidate(candidateToIce(candidate));
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
};
|
|
@@ -182,6 +184,14 @@ export class RTCIceCandidate {
|
|
|
182
184
|
static isThis(o: any) {
|
|
183
185
|
if (typeof o?.candidate === "string") return true;
|
|
184
186
|
}
|
|
187
|
+
|
|
188
|
+
toJSON() {
|
|
189
|
+
return {
|
|
190
|
+
candidate: this.candidate,
|
|
191
|
+
sdpMid: this.sdpMid,
|
|
192
|
+
sdpMLineIndex: this.sdpMLineIndex,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
185
195
|
}
|
|
186
196
|
|
|
187
197
|
export class IceCandidate {
|
package/src/transport/sctp.ts
CHANGED
|
@@ -28,9 +28,10 @@ export class RTCSctpTransport {
|
|
|
28
28
|
sctp!: SCTP;
|
|
29
29
|
|
|
30
30
|
readonly onDataChannel = new Event<[RTCDataChannel]>();
|
|
31
|
-
readonly
|
|
31
|
+
readonly id = uuid.v4();
|
|
32
32
|
|
|
33
33
|
mid?: string;
|
|
34
|
+
mLineIndex?: number;
|
|
34
35
|
bundled = false;
|
|
35
36
|
dataChannels: { [key: number]: RTCDataChannel } = {};
|
|
36
37
|
|