werift 0.15.2 → 0.15.5
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/index.js +5 -1
- package/lib/common/src/index.js.map +1 -1
- 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/dtls/src/cipher/namedCurve.js +5 -1
- package/lib/dtls/src/cipher/namedCurve.js.map +1 -1
- package/lib/dtls/src/cipher/prf.js +5 -1
- package/lib/dtls/src/cipher/prf.js.map +1 -1
- package/lib/dtls/src/cipher/suites/aead.js +5 -1
- package/lib/dtls/src/cipher/suites/aead.js.map +1 -1
- package/lib/dtls/src/context/cipher.js +5 -1
- package/lib/dtls/src/context/cipher.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 +28 -24
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/index.js +5 -1
- package/lib/ice/src/index.js.map +1 -1
- package/lib/ice/src/stun/attributes.js +5 -1
- package/lib/ice/src/stun/attributes.js.map +1 -1
- package/lib/rtp/src/container/webm.js +5 -1
- package/lib/rtp/src/container/webm.js.map +1 -1
- package/lib/rtp/src/index.js +5 -1
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/webrtc/src/index.js +5 -1
- package/lib/webrtc/src/index.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/rtpSender.js +5 -1
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.d.ts +3 -1
- package/lib/webrtc/src/media/rtpTransceiver.js +12 -2
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +5 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +6 -2
- package/lib/webrtc/src/peerConnection.js +126 -52
- 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 +6 -2
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +9 -19
- package/src/media/rtpReceiver.ts +1 -1
- package/src/media/rtpTransceiver.ts +7 -1
- package/src/peerConnection.ts +197 -124
- 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,32 @@ 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 (this.configuration.bundlePolicy === "max-bundle") {
|
|
439
|
+
candidate.sdpMLineIndex = 0;
|
|
440
|
+
candidate.sdpMid = this._localDescription?.media[0].rtp.muxId;
|
|
441
|
+
} else {
|
|
442
|
+
const transceiver = this.transceivers.find(
|
|
443
|
+
(t) => t.dtlsTransport.iceTransport.id === iceTransport.id
|
|
444
|
+
);
|
|
445
|
+
if (transceiver) {
|
|
446
|
+
candidate.sdpMLineIndex = transceiver.mLineIndex;
|
|
447
|
+
candidate.sdpMid = transceiver.mid;
|
|
448
|
+
}
|
|
449
|
+
if (
|
|
450
|
+
this.sctpTransport?.dtlsTransport.iceTransport.id === iceTransport.id
|
|
451
|
+
) {
|
|
452
|
+
candidate.sdpMLineIndex = this.sctpTransport.mLineIndex;
|
|
453
|
+
candidate.sdpMid = this.sctpTransport.mid;
|
|
454
|
+
}
|
|
431
455
|
}
|
|
432
|
-
|
|
433
|
-
candidate.sdpMid = media.rtp.muxId;
|
|
456
|
+
|
|
434
457
|
candidate.foundation = "candidate:" + candidate.foundation;
|
|
435
458
|
|
|
436
459
|
this.onIceCandidate.execute(candidate.toJSON());
|
|
437
|
-
if (this.onicecandidate)
|
|
460
|
+
if (this.onicecandidate) {
|
|
438
461
|
this.onicecandidate({ candidate: candidate.toJSON() });
|
|
462
|
+
}
|
|
439
463
|
this.emit("icecandidate", { candidate });
|
|
440
464
|
};
|
|
441
465
|
|
|
@@ -540,10 +564,20 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
540
564
|
// for trickle ice
|
|
541
565
|
this.setLocal(description);
|
|
542
566
|
|
|
543
|
-
//
|
|
544
|
-
|
|
545
|
-
|
|
567
|
+
// connect transports
|
|
568
|
+
if (description.type === "answer") {
|
|
569
|
+
log("callee start connect");
|
|
570
|
+
this.connect().catch((err) => {
|
|
571
|
+
log("connect failed", err);
|
|
572
|
+
this.setConnectionState("failed");
|
|
573
|
+
});
|
|
546
574
|
}
|
|
575
|
+
|
|
576
|
+
// # gather candidates
|
|
577
|
+
await Promise.all(
|
|
578
|
+
this.iceTransports.map((iceTransport) => iceTransport.iceGather.gather())
|
|
579
|
+
);
|
|
580
|
+
|
|
547
581
|
description.media
|
|
548
582
|
.filter((m) => ["audio", "video"].includes(m.kind))
|
|
549
583
|
.forEach((m, i) => {
|
|
@@ -556,15 +590,6 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
556
590
|
|
|
557
591
|
this.setLocal(description);
|
|
558
592
|
|
|
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
593
|
if (this.shouldNegotiationneeded) {
|
|
569
594
|
this.needNegotiation();
|
|
570
595
|
}
|
|
@@ -581,10 +606,54 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
581
606
|
}
|
|
582
607
|
}
|
|
583
608
|
|
|
609
|
+
private getTransportByMid(mid: string) {
|
|
610
|
+
let iceTransport: RTCIceTransport | undefined;
|
|
611
|
+
|
|
612
|
+
const transceiver = this.transceivers.find((t) => t.mid === mid);
|
|
613
|
+
if (transceiver) {
|
|
614
|
+
iceTransport = transceiver.dtlsTransport.iceTransport;
|
|
615
|
+
} else if (!iceTransport && this.sctpTransport?.mid === mid) {
|
|
616
|
+
iceTransport = this.sctpTransport?.dtlsTransport.iceTransport;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return iceTransport;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
private getTransportByMLineIndex(index: number) {
|
|
623
|
+
const sdp = this.buildOfferSdp();
|
|
624
|
+
const media = sdp.media[index];
|
|
625
|
+
if (!media) {
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
const transport = this.getTransportByMid(media.rtp.muxId!);
|
|
629
|
+
|
|
630
|
+
return transport;
|
|
631
|
+
}
|
|
632
|
+
|
|
584
633
|
async addIceCandidate(candidateMessage: RTCIceCandidate) {
|
|
585
634
|
const candidate = IceCandidate.fromJSON(candidateMessage);
|
|
586
|
-
|
|
635
|
+
if (!candidate) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
let iceTransport: RTCIceTransport | undefined;
|
|
640
|
+
|
|
641
|
+
if (typeof candidate.sdpMid === "number") {
|
|
642
|
+
iceTransport = this.getTransportByMid(candidate.sdpMid);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (!iceTransport && typeof candidate.sdpMLineIndex === "number") {
|
|
646
|
+
iceTransport = this.getTransportByMLineIndex(candidate.sdpMLineIndex);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (!iceTransport) {
|
|
650
|
+
iceTransport = this.iceTransports[0];
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (iceTransport) {
|
|
587
654
|
await iceTransport.addRemoteCandidate(candidate);
|
|
655
|
+
} else {
|
|
656
|
+
log("iceTransport not found", candidate);
|
|
588
657
|
}
|
|
589
658
|
}
|
|
590
659
|
|
|
@@ -689,84 +758,90 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
689
758
|
let bundleTransport: RTCDtlsTransport | undefined;
|
|
690
759
|
|
|
691
760
|
// # 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
761
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
bundleTransport = transceiver.dtlsTransport;
|
|
713
|
-
} else {
|
|
714
|
-
transceiver.setDtlsTransport(bundleTransport);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
762
|
+
const transports = enumerate(remoteSdp.media).map(([i, remoteMedia]) => {
|
|
763
|
+
let dtlsTransport: RTCDtlsTransport | undefined;
|
|
717
764
|
|
|
718
|
-
|
|
765
|
+
if (["audio", "video"].includes(remoteMedia.kind)) {
|
|
766
|
+
let transceiver = this.transceivers.find(
|
|
767
|
+
(t) =>
|
|
768
|
+
t.kind === remoteMedia.kind &&
|
|
769
|
+
[undefined, remoteMedia.rtp.muxId].includes(t.mid)
|
|
770
|
+
);
|
|
771
|
+
if (!transceiver) {
|
|
772
|
+
// create remote transceiver
|
|
773
|
+
transceiver = this.addTransceiver(remoteMedia.kind, {
|
|
774
|
+
direction: "recvonly",
|
|
775
|
+
});
|
|
776
|
+
transceiver.mid = remoteMedia.rtp.muxId;
|
|
777
|
+
this.onRemoteTransceiverAdded.execute(transceiver);
|
|
778
|
+
}
|
|
719
779
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
780
|
+
if (bundle) {
|
|
781
|
+
if (!bundleTransport) {
|
|
782
|
+
bundleTransport = transceiver.dtlsTransport;
|
|
783
|
+
} else {
|
|
784
|
+
transceiver.setDtlsTransport(bundleTransport);
|
|
724
785
|
}
|
|
786
|
+
}
|
|
725
787
|
|
|
726
|
-
|
|
727
|
-
if (!bundleTransport) {
|
|
728
|
-
bundleTransport = this.sctpTransport.dtlsTransport;
|
|
729
|
-
} else {
|
|
730
|
-
this.sctpTransport.setDtlsTransport(bundleTransport);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
788
|
+
dtlsTransport = transceiver.dtlsTransport;
|
|
733
789
|
|
|
734
|
-
|
|
790
|
+
this.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
|
|
791
|
+
} else if (remoteMedia.kind === "application") {
|
|
792
|
+
if (!this.sctpTransport) {
|
|
793
|
+
this.sctpTransport = this.createSctpTransport();
|
|
794
|
+
this.sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
795
|
+
}
|
|
735
796
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
797
|
+
if (bundle) {
|
|
798
|
+
if (!bundleTransport) {
|
|
799
|
+
bundleTransport = this.sctpTransport.dtlsTransport;
|
|
800
|
+
} else {
|
|
801
|
+
this.sctpTransport.setDtlsTransport(bundleTransport);
|
|
802
|
+
}
|
|
739
803
|
}
|
|
740
804
|
|
|
741
|
-
|
|
805
|
+
dtlsTransport = this.sctpTransport.dtlsTransport;
|
|
742
806
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
807
|
+
this.setRemoteSCTP(remoteMedia, this.sctpTransport, i);
|
|
808
|
+
} else {
|
|
809
|
+
throw new Error("invalid media kind");
|
|
810
|
+
}
|
|
746
811
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
812
|
+
const iceTransport = dtlsTransport.iceTransport;
|
|
813
|
+
|
|
814
|
+
if (remoteMedia.iceParams && remoteMedia.dtlsParams) {
|
|
815
|
+
iceTransport.setRemoteParams(remoteMedia.iceParams);
|
|
816
|
+
dtlsTransport.setRemoteParams(remoteMedia.dtlsParams);
|
|
817
|
+
|
|
818
|
+
// One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
|
|
819
|
+
// RFC 8445 S6.1.1
|
|
820
|
+
if (remoteMedia.iceParams?.iceLite) {
|
|
821
|
+
iceTransport.connection.iceControlling = true;
|
|
752
822
|
}
|
|
823
|
+
}
|
|
753
824
|
|
|
754
|
-
|
|
755
|
-
|
|
825
|
+
// # add ICE candidates
|
|
826
|
+
remoteMedia.iceCandidates.forEach(iceTransport.addRemoteCandidate);
|
|
756
827
|
|
|
757
|
-
|
|
828
|
+
if (remoteMedia.iceCandidatesComplete) {
|
|
829
|
+
iceTransport.addRemoteCandidate(undefined);
|
|
830
|
+
}
|
|
758
831
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
832
|
+
// # set DTLS role
|
|
833
|
+
if (remoteSdp.type === "answer" && remoteMedia.dtlsParams?.role) {
|
|
834
|
+
dtlsTransport.role =
|
|
835
|
+
remoteMedia.dtlsParams.role === "client" ? "server" : "client";
|
|
836
|
+
}
|
|
837
|
+
return iceTransport;
|
|
838
|
+
});
|
|
762
839
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
})
|
|
769
|
-
);
|
|
840
|
+
if (remoteSdp.type === "offer") {
|
|
841
|
+
this.setSignalingState("have-remote-offer");
|
|
842
|
+
} else if (remoteSdp.type === "answer") {
|
|
843
|
+
this.setSignalingState("stable");
|
|
844
|
+
}
|
|
770
845
|
|
|
771
846
|
// connect transports
|
|
772
847
|
if (remoteSdp.type === "answer") {
|
|
@@ -777,11 +852,11 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
777
852
|
});
|
|
778
853
|
}
|
|
779
854
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
855
|
+
await Promise.all(
|
|
856
|
+
transports.map(async (iceTransport) => {
|
|
857
|
+
await iceTransport.iceGather.gather();
|
|
858
|
+
})
|
|
859
|
+
);
|
|
785
860
|
|
|
786
861
|
this.negotiationneeded = false;
|
|
787
862
|
if (this.shouldNegotiationneeded) {
|
|
@@ -878,7 +953,8 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
878
953
|
|
|
879
954
|
private setRemoteSCTP(
|
|
880
955
|
remoteMedia: MediaDescription,
|
|
881
|
-
sctpTransport: RTCSctpTransport
|
|
956
|
+
sctpTransport: RTCSctpTransport,
|
|
957
|
+
mLineIndex: number
|
|
882
958
|
) {
|
|
883
959
|
// # configure sctp
|
|
884
960
|
this.sctpRemotePort = remoteMedia.sctpPort;
|
|
@@ -887,6 +963,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
887
963
|
}
|
|
888
964
|
|
|
889
965
|
sctpTransport.setRemotePort(this.sctpRemotePort);
|
|
966
|
+
sctpTransport.mLineIndex = mLineIndex;
|
|
890
967
|
if (!sctpTransport.mid) {
|
|
891
968
|
sctpTransport.mid = remoteMedia.rtp.muxId;
|
|
892
969
|
}
|
|
@@ -1075,6 +1152,12 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1075
1152
|
}
|
|
1076
1153
|
|
|
1077
1154
|
async createAnswer() {
|
|
1155
|
+
await this.ensureCerts();
|
|
1156
|
+
const description = this.buildAnswer();
|
|
1157
|
+
return description.toJSON();
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
private buildAnswer() {
|
|
1078
1161
|
this.assertNotClosed();
|
|
1079
1162
|
if (
|
|
1080
1163
|
!["have-remote-offer", "have-local-pranswer"].includes(
|
|
@@ -1087,8 +1170,6 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1087
1170
|
throw new Error("wrong state");
|
|
1088
1171
|
}
|
|
1089
1172
|
|
|
1090
|
-
await this.ensureCerts();
|
|
1091
|
-
|
|
1092
1173
|
const description = new SessionDescription();
|
|
1093
1174
|
addSDPHeader("answer", description);
|
|
1094
1175
|
|
|
@@ -1101,18 +1182,14 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1101
1182
|
media = createMediaDescriptionForTransceiver(
|
|
1102
1183
|
transceiver,
|
|
1103
1184
|
this.cname,
|
|
1104
|
-
andDirection(transceiver.direction, transceiver.offerDirection)
|
|
1105
|
-
transceiver.mid!
|
|
1185
|
+
andDirection(transceiver.direction, transceiver.offerDirection)
|
|
1106
1186
|
);
|
|
1107
1187
|
dtlsTransport = transceiver.dtlsTransport;
|
|
1108
1188
|
} else if (remoteMedia.kind === "application") {
|
|
1109
1189
|
if (!this.sctpTransport || !this.sctpTransport.mid) {
|
|
1110
1190
|
throw new Error("sctpTransport not found");
|
|
1111
1191
|
}
|
|
1112
|
-
media = createMediaDescriptionForSctp(
|
|
1113
|
-
this.sctpTransport,
|
|
1114
|
-
this.sctpTransport.mid
|
|
1115
|
-
);
|
|
1192
|
+
media = createMediaDescriptionForSctp(this.sctpTransport);
|
|
1116
1193
|
|
|
1117
1194
|
dtlsTransport = this.sctpTransport.dtlsTransport;
|
|
1118
1195
|
} else {
|
|
@@ -1145,7 +1222,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1145
1222
|
description.group.push(bundle);
|
|
1146
1223
|
}
|
|
1147
1224
|
|
|
1148
|
-
return description
|
|
1225
|
+
return description;
|
|
1149
1226
|
}
|
|
1150
1227
|
|
|
1151
1228
|
async close() {
|
|
@@ -1282,8 +1359,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
1282
1359
|
export function createMediaDescriptionForTransceiver(
|
|
1283
1360
|
transceiver: RTCRtpTransceiver,
|
|
1284
1361
|
cname: string,
|
|
1285
|
-
direction: Direction
|
|
1286
|
-
mid: string
|
|
1362
|
+
direction: Direction
|
|
1287
1363
|
) {
|
|
1288
1364
|
const media = new MediaDescription(
|
|
1289
1365
|
transceiver.kind,
|
|
@@ -1296,7 +1372,7 @@ export function createMediaDescriptionForTransceiver(
|
|
|
1296
1372
|
media.rtp = {
|
|
1297
1373
|
codecs: transceiver.codecs,
|
|
1298
1374
|
headerExtensions: transceiver.headerExtensions,
|
|
1299
|
-
muxId: mid,
|
|
1375
|
+
muxId: transceiver.mid,
|
|
1300
1376
|
};
|
|
1301
1377
|
media.rtcpHost = "0.0.0.0";
|
|
1302
1378
|
media.rtcpPort = 9;
|
|
@@ -1325,10 +1401,7 @@ export function createMediaDescriptionForTransceiver(
|
|
|
1325
1401
|
return media;
|
|
1326
1402
|
}
|
|
1327
1403
|
|
|
1328
|
-
export function createMediaDescriptionForSctp(
|
|
1329
|
-
sctp: RTCSctpTransport,
|
|
1330
|
-
mid: string
|
|
1331
|
-
) {
|
|
1404
|
+
export function createMediaDescriptionForSctp(sctp: RTCSctpTransport) {
|
|
1332
1405
|
const media = new MediaDescription(
|
|
1333
1406
|
"application",
|
|
1334
1407
|
DISCARD_PORT,
|
|
@@ -1336,7 +1409,7 @@ export function createMediaDescriptionForSctp(
|
|
|
1336
1409
|
["webrtc-datachannel"]
|
|
1337
1410
|
);
|
|
1338
1411
|
media.sctpPort = sctp.port;
|
|
1339
|
-
media.rtp.muxId = mid;
|
|
1412
|
+
media.rtp.muxId = sctp.mid;
|
|
1340
1413
|
media.sctpCapabilities = RTCSctpTransport.getCapabilities();
|
|
1341
1414
|
|
|
1342
1415
|
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
|
|