@gjsify/webrtc 0.3.16 → 0.3.17
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/esm/get-user-media.js +1 -108
- package/lib/esm/gst-enum-maps.js +1 -84
- package/lib/esm/gst-init.js +6 -28
- package/lib/esm/gst-stats-parser.js +1 -106
- package/lib/esm/gst-utils.js +1 -27
- package/lib/esm/index.js +1 -23
- package/lib/esm/media-device-info.js +1 -24
- package/lib/esm/media-devices.js +1 -158
- package/lib/esm/media-stream-track.js +1 -139
- package/lib/esm/media-stream.js +1 -79
- package/lib/esm/register/data-channel.js +1 -12
- package/lib/esm/register/error.js +1 -12
- package/lib/esm/register/media-devices.js +1 -11
- package/lib/esm/register/media.js +1 -16
- package/lib/esm/register/peer-connection.js +1 -20
- package/lib/esm/register.js +1 -5
- package/lib/esm/rtc-certificate.js +1 -66
- package/lib/esm/rtc-data-channel.js +1 -250
- package/lib/esm/rtc-dtls-transport.js +1 -42
- package/lib/esm/rtc-dtmf-sender.js +1 -101
- package/lib/esm/rtc-error.js +1 -26
- package/lib/esm/rtc-events.js +1 -35
- package/lib/esm/rtc-ice-candidate.js +1 -74
- package/lib/esm/rtc-ice-transport.js +1 -97
- package/lib/esm/rtc-peer-connection.js +1 -812
- package/lib/esm/rtc-rtp-receiver.js +1 -93
- package/lib/esm/rtc-rtp-sender.js +1 -290
- package/lib/esm/rtc-rtp-transceiver.js +1 -96
- package/lib/esm/rtc-sctp-transport.js +1 -40
- package/lib/esm/rtc-session-description.js +1 -53
- package/lib/esm/rtc-stats-report.js +1 -40
- package/lib/esm/rtc-track-event.js +1 -31
- package/lib/esm/rtp-capabilities.js +1 -87
- package/lib/esm/tee-multiplexer.js +1 -60
- package/lib/esm/wpt-helpers.js +1 -138
- package/package.json +14 -14
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,139 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import "@gjsify/dom-events/register/event-target";
|
|
3
|
-
import GLib from "gi://GLib?version=2.0";
|
|
4
|
-
|
|
5
|
-
//#region src/media-stream-track.ts
|
|
6
|
-
var MediaStreamTrack = class MediaStreamTrack extends EventTarget {
|
|
7
|
-
id;
|
|
8
|
-
kind;
|
|
9
|
-
label;
|
|
10
|
-
_enabled = true;
|
|
11
|
-
_muted;
|
|
12
|
-
_ended = false;
|
|
13
|
-
_contentHint = "";
|
|
14
|
-
_onended = null;
|
|
15
|
-
_onmute = null;
|
|
16
|
-
_onunmute = null;
|
|
17
|
-
/** @internal GStreamer source element (e.g. pulsesrc, audiotestsrc) */
|
|
18
|
-
_gstSource = null;
|
|
19
|
-
/** @internal Pipeline the source currently lives in (updated by VideoBridge) */
|
|
20
|
-
_gstPipeline = null;
|
|
21
|
-
/** @internal Tee element inserted by VideoBridge for preview fan-out */
|
|
22
|
-
_gstTee = null;
|
|
23
|
-
/** @internal TeeMultiplexer for multi-PC fan-out (created on second addTrack) */
|
|
24
|
-
_teeMultiplexer = null;
|
|
25
|
-
/** @internal Callback set by RTCRtpSender to control valve drop property */
|
|
26
|
-
_enableCallback = null;
|
|
27
|
-
constructor(init) {
|
|
28
|
-
super();
|
|
29
|
-
this.id = init.id ?? GLib.uuid_string_random();
|
|
30
|
-
this.kind = init.kind;
|
|
31
|
-
this.label = init.label ?? "";
|
|
32
|
-
this._muted = init.muted ?? false;
|
|
33
|
-
if (init._gst) {
|
|
34
|
-
this._gstSource = init._gst.source;
|
|
35
|
-
this._gstPipeline = init._gst.pipeline;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
get enabled() {
|
|
39
|
-
return this._enabled;
|
|
40
|
-
}
|
|
41
|
-
set enabled(v) {
|
|
42
|
-
const val = !!v;
|
|
43
|
-
if (this._enabled === val) return;
|
|
44
|
-
this._enabled = val;
|
|
45
|
-
this._enableCallback?.(val);
|
|
46
|
-
}
|
|
47
|
-
get muted() {
|
|
48
|
-
return this._muted;
|
|
49
|
-
}
|
|
50
|
-
get readyState() {
|
|
51
|
-
return this._ended ? "ended" : "live";
|
|
52
|
-
}
|
|
53
|
-
get contentHint() {
|
|
54
|
-
return this._contentHint;
|
|
55
|
-
}
|
|
56
|
-
set contentHint(v) {
|
|
57
|
-
if (this.kind === "audio") {
|
|
58
|
-
if (v !== "" && v !== "speech" && v !== "speech-recognition" && v !== "music") return;
|
|
59
|
-
} else {
|
|
60
|
-
if (v !== "" && v !== "motion" && v !== "detail" && v !== "text") return;
|
|
61
|
-
}
|
|
62
|
-
this._contentHint = v;
|
|
63
|
-
}
|
|
64
|
-
get onended() {
|
|
65
|
-
return this._onended;
|
|
66
|
-
}
|
|
67
|
-
set onended(v) {
|
|
68
|
-
this._onended = v;
|
|
69
|
-
}
|
|
70
|
-
get onmute() {
|
|
71
|
-
return this._onmute;
|
|
72
|
-
}
|
|
73
|
-
set onmute(v) {
|
|
74
|
-
this._onmute = v;
|
|
75
|
-
}
|
|
76
|
-
get onunmute() {
|
|
77
|
-
return this._onunmute;
|
|
78
|
-
}
|
|
79
|
-
set onunmute(v) {
|
|
80
|
-
this._onunmute = v;
|
|
81
|
-
}
|
|
82
|
-
clone() {
|
|
83
|
-
const cloned = new MediaStreamTrack({
|
|
84
|
-
kind: this.kind,
|
|
85
|
-
label: this.label,
|
|
86
|
-
muted: this._muted
|
|
87
|
-
});
|
|
88
|
-
cloned._enabled = this._enabled;
|
|
89
|
-
return cloned;
|
|
90
|
-
}
|
|
91
|
-
stop() {
|
|
92
|
-
if (this._ended) return;
|
|
93
|
-
this._ended = true;
|
|
94
|
-
if (this._gstSource || this._gstPipeline) {
|
|
95
|
-
try {
|
|
96
|
-
this._gstPipeline?.set_state(Gst.State.NULL);
|
|
97
|
-
} catch {}
|
|
98
|
-
try {
|
|
99
|
-
this._gstSource?.set_state(Gst.State.NULL);
|
|
100
|
-
} catch {}
|
|
101
|
-
this._gstSource = null;
|
|
102
|
-
this._gstPipeline = null;
|
|
103
|
-
}
|
|
104
|
-
const ev = new Event("ended");
|
|
105
|
-
this._onended?.call(this, ev);
|
|
106
|
-
this.dispatchEvent(ev);
|
|
107
|
-
}
|
|
108
|
-
getCapabilities() {
|
|
109
|
-
return {};
|
|
110
|
-
}
|
|
111
|
-
getConstraints() {
|
|
112
|
-
return {};
|
|
113
|
-
}
|
|
114
|
-
getSettings() {
|
|
115
|
-
return {};
|
|
116
|
-
}
|
|
117
|
-
applyConstraints(_constraints) {
|
|
118
|
-
return Promise.reject(new DOMException("applyConstraints is not supported", "NotSupportedError"));
|
|
119
|
-
}
|
|
120
|
-
/** @internal — used by RTCRtpReceiver to toggle mute state */
|
|
121
|
-
_setMuted(muted) {
|
|
122
|
-
if (this._muted === muted) return;
|
|
123
|
-
this._muted = muted;
|
|
124
|
-
const ev = new Event(muted ? "mute" : "unmute");
|
|
125
|
-
if (muted) {
|
|
126
|
-
this._onmute?.call(this, ev);
|
|
127
|
-
} else {
|
|
128
|
-
this._onunmute?.call(this, ev);
|
|
129
|
-
}
|
|
130
|
-
this.dispatchEvent(ev);
|
|
131
|
-
}
|
|
132
|
-
/** @internal — called by RTCRtpSender to wire valve control */
|
|
133
|
-
_setEnableCallback(cb) {
|
|
134
|
-
this._enableCallback = cb;
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
//#endregion
|
|
139
|
-
export { MediaStreamTrack };
|
|
1
|
+
import{Gst as e}from"./gst-init.js";import"@gjsify/dom-events/register/event-target";import t from"gi://GLib?version=2.0";var n=class n extends EventTarget{id;kind;label;_enabled=!0;_muted;_ended=!1;_contentHint=``;_onended=null;_onmute=null;_onunmute=null;_gstSource=null;_gstPipeline=null;_gstTee=null;_teeMultiplexer=null;_enableCallback=null;constructor(e){super(),this.id=e.id??t.uuid_string_random(),this.kind=e.kind,this.label=e.label??``,this._muted=e.muted??!1,e._gst&&(this._gstSource=e._gst.source,this._gstPipeline=e._gst.pipeline)}get enabled(){return this._enabled}set enabled(e){let t=!!e;this._enabled!==t&&(this._enabled=t,this._enableCallback?.(t))}get muted(){return this._muted}get readyState(){return this._ended?`ended`:`live`}get contentHint(){return this._contentHint}set contentHint(e){if(this.kind===`audio`){if(e!==``&&e!==`speech`&&e!==`speech-recognition`&&e!==`music`)return}else if(e!==``&&e!==`motion`&&e!==`detail`&&e!==`text`)return;this._contentHint=e}get onended(){return this._onended}set onended(e){this._onended=e}get onmute(){return this._onmute}set onmute(e){this._onmute=e}get onunmute(){return this._onunmute}set onunmute(e){this._onunmute=e}clone(){let e=new n({kind:this.kind,label:this.label,muted:this._muted});return e._enabled=this._enabled,e}stop(){if(this._ended)return;if(this._ended=!0,this._gstSource||this._gstPipeline){try{this._gstPipeline?.set_state(e.State.NULL)}catch{}try{this._gstSource?.set_state(e.State.NULL)}catch{}this._gstSource=null,this._gstPipeline=null}let t=new Event(`ended`);this._onended?.call(this,t),this.dispatchEvent(t)}getCapabilities(){return{}}getConstraints(){return{}}getSettings(){return{}}applyConstraints(e){return Promise.reject(new DOMException(`applyConstraints is not supported`,`NotSupportedError`))}_setMuted(e){if(this._muted===e)return;this._muted=e;let t=new Event(e?`mute`:`unmute`);e?this._onmute?.call(this,t):this._onunmute?.call(this,t),this.dispatchEvent(t)}_setEnableCallback(e){this._enableCallback=e}};export{n as MediaStreamTrack};
|
package/lib/esm/media-stream.js
CHANGED
|
@@ -1,79 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import GLib from "gi://GLib?version=2.0";
|
|
3
|
-
|
|
4
|
-
//#region src/media-stream.ts
|
|
5
|
-
var MediaStream = class MediaStream extends EventTarget {
|
|
6
|
-
id;
|
|
7
|
-
_tracks = new Map();
|
|
8
|
-
_onaddtrack = null;
|
|
9
|
-
_onremovetrack = null;
|
|
10
|
-
constructor(streamOrTracks) {
|
|
11
|
-
super();
|
|
12
|
-
this.id = GLib.uuid_string_random();
|
|
13
|
-
if (streamOrTracks instanceof MediaStream) {
|
|
14
|
-
for (const track of streamOrTracks.getTracks()) {
|
|
15
|
-
this._tracks.set(track.id, track.clone());
|
|
16
|
-
}
|
|
17
|
-
} else if (Array.isArray(streamOrTracks)) {
|
|
18
|
-
for (const track of streamOrTracks) {
|
|
19
|
-
this._tracks.set(track.id, track);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
get active() {
|
|
24
|
-
for (const track of this._tracks.values()) {
|
|
25
|
-
if (track.readyState === "live") return true;
|
|
26
|
-
}
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
get onaddtrack() {
|
|
30
|
-
return this._onaddtrack;
|
|
31
|
-
}
|
|
32
|
-
set onaddtrack(v) {
|
|
33
|
-
this._onaddtrack = v;
|
|
34
|
-
}
|
|
35
|
-
get onremovetrack() {
|
|
36
|
-
return this._onremovetrack;
|
|
37
|
-
}
|
|
38
|
-
set onremovetrack(v) {
|
|
39
|
-
this._onremovetrack = v;
|
|
40
|
-
}
|
|
41
|
-
getTracks() {
|
|
42
|
-
return [...this._tracks.values()];
|
|
43
|
-
}
|
|
44
|
-
getAudioTracks() {
|
|
45
|
-
return this.getTracks().filter((t) => t.kind === "audio");
|
|
46
|
-
}
|
|
47
|
-
getVideoTracks() {
|
|
48
|
-
return this.getTracks().filter((t) => t.kind === "video");
|
|
49
|
-
}
|
|
50
|
-
getTrackById(id) {
|
|
51
|
-
return this._tracks.get(id) ?? null;
|
|
52
|
-
}
|
|
53
|
-
addTrack(track) {
|
|
54
|
-
if (this._tracks.has(track.id)) return;
|
|
55
|
-
this._tracks.set(track.id, track);
|
|
56
|
-
const ev = new MediaStreamTrackEvent("addtrack", { track });
|
|
57
|
-
this._onaddtrack?.call(this, ev);
|
|
58
|
-
this.dispatchEvent(ev);
|
|
59
|
-
}
|
|
60
|
-
removeTrack(track) {
|
|
61
|
-
if (!this._tracks.delete(track.id)) return;
|
|
62
|
-
const ev = new MediaStreamTrackEvent("removetrack", { track });
|
|
63
|
-
this._onremovetrack?.call(this, ev);
|
|
64
|
-
this.dispatchEvent(ev);
|
|
65
|
-
}
|
|
66
|
-
clone() {
|
|
67
|
-
return new MediaStream(this);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
var MediaStreamTrackEvent = class extends Event {
|
|
71
|
-
track;
|
|
72
|
-
constructor(type, init) {
|
|
73
|
-
super(type, init);
|
|
74
|
-
this.track = init.track;
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
//#endregion
|
|
79
|
-
export { MediaStream, MediaStreamTrackEvent };
|
|
1
|
+
import"@gjsify/dom-events/register/event-target";import e from"gi://GLib?version=2.0";var t=class t extends EventTarget{id;_tracks=new Map;_onaddtrack=null;_onremovetrack=null;constructor(n){if(super(),this.id=e.uuid_string_random(),n instanceof t)for(let e of n.getTracks())this._tracks.set(e.id,e.clone());else if(Array.isArray(n))for(let e of n)this._tracks.set(e.id,e)}get active(){for(let e of this._tracks.values())if(e.readyState===`live`)return!0;return!1}get onaddtrack(){return this._onaddtrack}set onaddtrack(e){this._onaddtrack=e}get onremovetrack(){return this._onremovetrack}set onremovetrack(e){this._onremovetrack=e}getTracks(){return[...this._tracks.values()]}getAudioTracks(){return this.getTracks().filter(e=>e.kind===`audio`)}getVideoTracks(){return this.getTracks().filter(e=>e.kind===`video`)}getTrackById(e){return this._tracks.get(e)??null}addTrack(e){if(this._tracks.has(e.id))return;this._tracks.set(e.id,e);let t=new n(`addtrack`,{track:e});this._onaddtrack?.call(this,t),this.dispatchEvent(t)}removeTrack(e){if(!this._tracks.delete(e.id))return;let t=new n(`removetrack`,{track:e});this._onremovetrack?.call(this,t),this.dispatchEvent(t)}clone(){return new t(this)}},n=class extends Event{track;constructor(e,t){super(e,t),this.track=t.track}};export{t as MediaStream,n as MediaStreamTrackEvent};
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RTCDataChannel } from "../rtc-data-channel.js";
|
|
3
|
-
|
|
4
|
-
//#region src/register/data-channel.ts
|
|
5
|
-
if (typeof globalThis.RTCDataChannel === "undefined") {
|
|
6
|
-
globalThis.RTCDataChannel = RTCDataChannel;
|
|
7
|
-
}
|
|
8
|
-
if (typeof globalThis.RTCDataChannelEvent === "undefined") {
|
|
9
|
-
globalThis.RTCDataChannelEvent = RTCDataChannelEvent;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
1
|
+
import{RTCDataChannelEvent as e}from"../rtc-events.js";import{RTCDataChannel as t}from"../rtc-data-channel.js";globalThis.RTCDataChannel===void 0&&(globalThis.RTCDataChannel=t),globalThis.RTCDataChannelEvent===void 0&&(globalThis.RTCDataChannelEvent=e);
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RTCErrorEvent } from "../rtc-events.js";
|
|
3
|
-
|
|
4
|
-
//#region src/register/error.ts
|
|
5
|
-
if (typeof globalThis.RTCError === "undefined") {
|
|
6
|
-
globalThis.RTCError = RTCError;
|
|
7
|
-
}
|
|
8
|
-
if (typeof globalThis.RTCErrorEvent === "undefined") {
|
|
9
|
-
globalThis.RTCErrorEvent = RTCErrorEvent;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
1
|
+
import{RTCError as e}from"../rtc-error.js";import{RTCErrorEvent as t}from"../rtc-events.js";globalThis.RTCError===void 0&&(globalThis.RTCError=e),globalThis.RTCErrorEvent===void 0&&(globalThis.RTCErrorEvent=t);
|
|
@@ -1,11 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
//#region src/register/media-devices.ts
|
|
4
|
-
if (typeof globalThis.navigator === "undefined") {
|
|
5
|
-
globalThis.navigator = {};
|
|
6
|
-
}
|
|
7
|
-
if (typeof globalThis.navigator.mediaDevices === "undefined") {
|
|
8
|
-
globalThis.navigator.mediaDevices = new MediaDevices();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
1
|
+
import{MediaDevices as e}from"../media-devices.js";globalThis.navigator===void 0&&(globalThis.navigator={}),globalThis.navigator.mediaDevices===void 0&&(globalThis.navigator.mediaDevices=new e);
|
|
@@ -1,16 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MediaStream } from "../media-stream.js";
|
|
3
|
-
import { RTCTrackEvent } from "../rtc-track-event.js";
|
|
4
|
-
|
|
5
|
-
//#region src/register/media.ts
|
|
6
|
-
if (typeof globalThis.MediaStream === "undefined") {
|
|
7
|
-
globalThis.MediaStream = MediaStream;
|
|
8
|
-
}
|
|
9
|
-
if (typeof globalThis.MediaStreamTrack === "undefined") {
|
|
10
|
-
globalThis.MediaStreamTrack = MediaStreamTrack;
|
|
11
|
-
}
|
|
12
|
-
if (typeof globalThis.RTCTrackEvent === "undefined") {
|
|
13
|
-
globalThis.RTCTrackEvent = RTCTrackEvent;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
1
|
+
import{MediaStreamTrack as e}from"../media-stream-track.js";import{MediaStream as t}from"../media-stream.js";import{RTCTrackEvent as n}from"../rtc-track-event.js";globalThis.MediaStream===void 0&&(globalThis.MediaStream=t),globalThis.MediaStreamTrack===void 0&&(globalThis.MediaStreamTrack=e),globalThis.RTCTrackEvent===void 0&&(globalThis.RTCTrackEvent=n);
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { RTCIceCandidate } from "../rtc-ice-candidate.js";
|
|
3
|
-
import { RTCPeerConnectionIceEvent } from "../rtc-events.js";
|
|
4
|
-
import { RTCPeerConnection } from "../rtc-peer-connection.js";
|
|
5
|
-
|
|
6
|
-
//#region src/register/peer-connection.ts
|
|
7
|
-
if (typeof globalThis.RTCPeerConnection === "undefined") {
|
|
8
|
-
globalThis.RTCPeerConnection = RTCPeerConnection;
|
|
9
|
-
}
|
|
10
|
-
if (typeof globalThis.RTCSessionDescription === "undefined") {
|
|
11
|
-
globalThis.RTCSessionDescription = RTCSessionDescription;
|
|
12
|
-
}
|
|
13
|
-
if (typeof globalThis.RTCIceCandidate === "undefined") {
|
|
14
|
-
globalThis.RTCIceCandidate = RTCIceCandidate;
|
|
15
|
-
}
|
|
16
|
-
if (typeof globalThis.RTCPeerConnectionIceEvent === "undefined") {
|
|
17
|
-
globalThis.RTCPeerConnectionIceEvent = RTCPeerConnectionIceEvent;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
//#endregion
|
|
1
|
+
import{RTCSessionDescription as e}from"../rtc-session-description.js";import{RTCIceCandidate as t}from"../rtc-ice-candidate.js";import{RTCPeerConnectionIceEvent as n}from"../rtc-events.js";import{RTCPeerConnection as r}from"../rtc-peer-connection.js";globalThis.RTCPeerConnection===void 0&&(globalThis.RTCPeerConnection=r),globalThis.RTCSessionDescription===void 0&&(globalThis.RTCSessionDescription=e),globalThis.RTCIceCandidate===void 0&&(globalThis.RTCIceCandidate=t),globalThis.RTCPeerConnectionIceEvent===void 0&&(globalThis.RTCPeerConnectionIceEvent=n);
|
package/lib/esm/register.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import "./register/data-channel.js";
|
|
3
|
-
import "./register/error.js";
|
|
4
|
-
import "./register/media.js";
|
|
5
|
-
import "./register/media-devices.js";
|
|
1
|
+
import"./register/peer-connection.js";import"./register/data-channel.js";import"./register/error.js";import"./register/media.js";import"./register/media-devices.js";
|
|
@@ -1,66 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
//#region src/rtc-certificate.ts
|
|
4
|
-
const DEFAULT_EXPIRY_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
5
|
-
var RTCCertificate = class {
|
|
6
|
-
expires;
|
|
7
|
-
_fingerprints;
|
|
8
|
-
_algorithm;
|
|
9
|
-
/** @internal — use RTCPeerConnection.generateCertificate() */
|
|
10
|
-
constructor(algorithm, expires, fingerprints) {
|
|
11
|
-
this._algorithm = algorithm;
|
|
12
|
-
this.expires = expires;
|
|
13
|
-
this._fingerprints = fingerprints;
|
|
14
|
-
}
|
|
15
|
-
getFingerprints() {
|
|
16
|
-
return [...this._fingerprints];
|
|
17
|
-
}
|
|
18
|
-
/** @internal — the algorithm name for debugging/inspection */
|
|
19
|
-
get _algorithmName() {
|
|
20
|
-
return this._algorithm;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Generate a self-signed certificate for use with RTCPeerConnection.
|
|
25
|
-
* Supports ECDSA P-256 and RSASSA-PKCS1-v1_5 with SHA-256.
|
|
26
|
-
*
|
|
27
|
-
* The actual DTLS certificate used by webrtcbin is generated internally
|
|
28
|
-
* by GStreamer — this provides the spec-compliant JS API surface.
|
|
29
|
-
*/
|
|
30
|
-
async function generateCertificate(keygenAlgorithm) {
|
|
31
|
-
let name;
|
|
32
|
-
if (typeof keygenAlgorithm === "string") {
|
|
33
|
-
name = keygenAlgorithm.toLowerCase();
|
|
34
|
-
} else if (keygenAlgorithm && typeof keygenAlgorithm === "object" && typeof keygenAlgorithm.name === "string") {
|
|
35
|
-
name = keygenAlgorithm.name.toLowerCase();
|
|
36
|
-
} else {
|
|
37
|
-
throw new DOMException("generateCertificate: algorithm must have a name property", "NotSupportedError");
|
|
38
|
-
}
|
|
39
|
-
if (name === "ecdsa") {
|
|
40
|
-
const curve = keygenAlgorithm.namedCurve;
|
|
41
|
-
if (curve && curve !== "P-256") {
|
|
42
|
-
throw new DOMException(`generateCertificate: unsupported ECDSA curve '${curve}'`, "NotSupportedError");
|
|
43
|
-
}
|
|
44
|
-
} else if (name === "rsassa-pkcs1-v1_5") {
|
|
45
|
-
const hash = keygenAlgorithm.hash;
|
|
46
|
-
const hashName = typeof hash === "string" ? hash : hash?.name;
|
|
47
|
-
if (hashName && hashName.toUpperCase() === "SHA-1") {
|
|
48
|
-
throw new DOMException("generateCertificate: SHA-1 is not supported for RSA certificates", "NotSupportedError");
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
throw new DOMException(`generateCertificate: unsupported algorithm '${name}'`, "NotSupportedError");
|
|
52
|
-
}
|
|
53
|
-
const uuid = GLib.uuid_string_random();
|
|
54
|
-
const checksum = GLib.Checksum.new(GLib.ChecksumType.SHA256);
|
|
55
|
-
checksum.update(new TextEncoder().encode(uuid + Date.now()));
|
|
56
|
-
const fingerprintHex = checksum.get_string();
|
|
57
|
-
const formatted = fingerprintHex.slice(0, 64).match(/.{2}/g).join(":").toUpperCase();
|
|
58
|
-
const expires = Date.now() + DEFAULT_EXPIRY_MS;
|
|
59
|
-
return new RTCCertificate(name, expires, [{
|
|
60
|
-
algorithm: "sha-256",
|
|
61
|
-
value: formatted
|
|
62
|
-
}]);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
//#endregion
|
|
66
|
-
export { RTCCertificate, generateCertificate };
|
|
1
|
+
import e from"gi://GLib?version=2.0";var t=class{expires;_fingerprints;_algorithm;constructor(e,t,n){this._algorithm=e,this.expires=t,this._fingerprints=n}getFingerprints(){return[...this._fingerprints]}get _algorithmName(){return this._algorithm}};async function n(n){let r;if(typeof n==`string`)r=n.toLowerCase();else if(n&&typeof n==`object`&&typeof n.name==`string`)r=n.name.toLowerCase();else throw new DOMException(`generateCertificate: algorithm must have a name property`,`NotSupportedError`);if(r===`ecdsa`){let e=n.namedCurve;if(e&&e!==`P-256`)throw new DOMException(`generateCertificate: unsupported ECDSA curve '${e}'`,`NotSupportedError`)}else if(r===`rsassa-pkcs1-v1_5`){let e=n.hash,t=typeof e==`string`?e:e?.name;if(t&&t.toUpperCase()===`SHA-1`)throw new DOMException(`generateCertificate: SHA-1 is not supported for RSA certificates`,`NotSupportedError`)}else throw new DOMException(`generateCertificate: unsupported algorithm '${r}'`,`NotSupportedError`);let i=e.uuid_string_random(),a=e.Checksum.new(e.ChecksumType.SHA256);a.update(new TextEncoder().encode(i+Date.now()));let o=a.get_string().slice(0,64).match(/.{2}/g).join(`:`).toUpperCase(),s=Date.now()+2592e6;return new t(r,s,[{algorithm:`sha-256`,value:o}])}export{t as RTCCertificate,n as generateCertificate};
|
|
@@ -1,250 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RTCErrorEvent } from "./rtc-events.js";
|
|
3
|
-
import { DOMException } from "@gjsify/dom-exception";
|
|
4
|
-
import GLib from "gi://GLib?version=2.0";
|
|
5
|
-
import { DataChannelBridge } from "@gjsify/webrtc-native";
|
|
6
|
-
import { Blob } from "@gjsify/buffer";
|
|
7
|
-
|
|
8
|
-
//#region src/rtc-data-channel.ts
|
|
9
|
-
const STATE_MAP = {
|
|
10
|
-
1: "connecting",
|
|
11
|
-
2: "open",
|
|
12
|
-
3: "closing",
|
|
13
|
-
4: "closed"
|
|
14
|
-
};
|
|
15
|
-
/** Convert a JS typed array / ArrayBuffer to a GLib.Bytes. */
|
|
16
|
-
function toGBytes(buffer) {
|
|
17
|
-
let view;
|
|
18
|
-
if (ArrayBuffer.isView(buffer)) {
|
|
19
|
-
view = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
20
|
-
} else {
|
|
21
|
-
view = new Uint8Array(buffer);
|
|
22
|
-
}
|
|
23
|
-
return new GLib.Bytes(view);
|
|
24
|
-
}
|
|
25
|
-
/** Convert a GLib.Bytes payload to an ArrayBuffer. */
|
|
26
|
-
function bytesToArrayBuffer(bytes) {
|
|
27
|
-
const arr = bytes.toArray?.();
|
|
28
|
-
if (arr instanceof Uint8Array) {
|
|
29
|
-
return arr.buffer.slice(arr.byteOffset, arr.byteOffset + arr.byteLength);
|
|
30
|
-
}
|
|
31
|
-
const data = bytes.get_data?.();
|
|
32
|
-
if (data instanceof Uint8Array) {
|
|
33
|
-
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
34
|
-
}
|
|
35
|
-
return new ArrayBuffer(0);
|
|
36
|
-
}
|
|
37
|
-
var RTCDataChannel = class extends EventTarget {
|
|
38
|
-
_native;
|
|
39
|
-
_bridge;
|
|
40
|
-
_binaryType = "arraybuffer";
|
|
41
|
-
_bufferedAmount = 0;
|
|
42
|
-
_closed = false;
|
|
43
|
-
_onopen = null;
|
|
44
|
-
_onclose = null;
|
|
45
|
-
_onerror = null;
|
|
46
|
-
_onmessage = null;
|
|
47
|
-
_onbufferedamountlow = null;
|
|
48
|
-
_onclosing = null;
|
|
49
|
-
/**
|
|
50
|
-
* @internal
|
|
51
|
-
* Accepts either a raw GstWebRTCDataChannel (for locally-created channels)
|
|
52
|
-
* or a pre-made DataChannelBridge (for remotely-originated channels that
|
|
53
|
-
* the WebrtcbinBridge already wrapped on the streaming thread to avoid
|
|
54
|
-
* missing early messages).
|
|
55
|
-
*/
|
|
56
|
-
constructor(source) {
|
|
57
|
-
super();
|
|
58
|
-
if (source.channel !== undefined && source.dispose_bridge) {
|
|
59
|
-
this._bridge = source;
|
|
60
|
-
this._native = this._bridge.channel;
|
|
61
|
-
} else {
|
|
62
|
-
this._native = source;
|
|
63
|
-
this._bridge = new DataChannelBridge({ channel: this._native });
|
|
64
|
-
}
|
|
65
|
-
this._bridge.connect("opened", () => this._handleOpen());
|
|
66
|
-
this._bridge.connect("closed", () => this._handleClose());
|
|
67
|
-
this._bridge.connect("error-occurred", (_b, message) => this._handleError(message));
|
|
68
|
-
this._bridge.connect("message-string", (_b, data) => this._handleString(data));
|
|
69
|
-
this._bridge.connect("message-data", (_b, data) => this._handleData(data));
|
|
70
|
-
this._bridge.connect("buffered-amount-low", () => this._handleBufferedAmountLow());
|
|
71
|
-
this._bridge.connect("ready-state-changed", () => this._handleReadyStateChange());
|
|
72
|
-
}
|
|
73
|
-
get label() {
|
|
74
|
-
return this._native.label;
|
|
75
|
-
}
|
|
76
|
-
get ordered() {
|
|
77
|
-
return this._native.ordered;
|
|
78
|
-
}
|
|
79
|
-
get protocol() {
|
|
80
|
-
return this._native.protocol;
|
|
81
|
-
}
|
|
82
|
-
get negotiated() {
|
|
83
|
-
return this._native.negotiated;
|
|
84
|
-
}
|
|
85
|
-
get id() {
|
|
86
|
-
return this._native.id >= 0 ? this._native.id : null;
|
|
87
|
-
}
|
|
88
|
-
get maxPacketLifeTime() {
|
|
89
|
-
const v = this._native.max_packet_lifetime;
|
|
90
|
-
return v >= 0 ? v : null;
|
|
91
|
-
}
|
|
92
|
-
get maxRetransmits() {
|
|
93
|
-
const v = this._native.max_retransmits;
|
|
94
|
-
return v >= 0 ? v : null;
|
|
95
|
-
}
|
|
96
|
-
get readyState() {
|
|
97
|
-
if (this._closed) return "closed";
|
|
98
|
-
return STATE_MAP[this._native.ready_state] ?? "connecting";
|
|
99
|
-
}
|
|
100
|
-
get bufferedAmount() {
|
|
101
|
-
try {
|
|
102
|
-
return Number(this._native.buffered_amount) || this._bufferedAmount;
|
|
103
|
-
} catch {
|
|
104
|
-
return this._bufferedAmount;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
get bufferedAmountLowThreshold() {
|
|
108
|
-
return Number(this._native.buffered_amount_low_threshold) || 0;
|
|
109
|
-
}
|
|
110
|
-
set bufferedAmountLowThreshold(v) {
|
|
111
|
-
this._native.buffered_amount_low_threshold = v;
|
|
112
|
-
}
|
|
113
|
-
get binaryType() {
|
|
114
|
-
return this._binaryType;
|
|
115
|
-
}
|
|
116
|
-
set binaryType(v) {
|
|
117
|
-
if (v !== "arraybuffer" && v !== "blob") return;
|
|
118
|
-
this._binaryType = v;
|
|
119
|
-
}
|
|
120
|
-
get onopen() {
|
|
121
|
-
return this._onopen;
|
|
122
|
-
}
|
|
123
|
-
set onopen(h) {
|
|
124
|
-
this._onopen = h;
|
|
125
|
-
}
|
|
126
|
-
get onclose() {
|
|
127
|
-
return this._onclose;
|
|
128
|
-
}
|
|
129
|
-
set onclose(h) {
|
|
130
|
-
this._onclose = h;
|
|
131
|
-
}
|
|
132
|
-
get onclosing() {
|
|
133
|
-
return this._onclosing;
|
|
134
|
-
}
|
|
135
|
-
set onclosing(h) {
|
|
136
|
-
this._onclosing = h;
|
|
137
|
-
}
|
|
138
|
-
get onerror() {
|
|
139
|
-
return this._onerror;
|
|
140
|
-
}
|
|
141
|
-
set onerror(h) {
|
|
142
|
-
this._onerror = h;
|
|
143
|
-
}
|
|
144
|
-
get onmessage() {
|
|
145
|
-
return this._onmessage;
|
|
146
|
-
}
|
|
147
|
-
set onmessage(h) {
|
|
148
|
-
this._onmessage = h;
|
|
149
|
-
}
|
|
150
|
-
get onbufferedamountlow() {
|
|
151
|
-
return this._onbufferedamountlow;
|
|
152
|
-
}
|
|
153
|
-
set onbufferedamountlow(h) {
|
|
154
|
-
this._onbufferedamountlow = h;
|
|
155
|
-
}
|
|
156
|
-
send(data) {
|
|
157
|
-
const state = this.readyState;
|
|
158
|
-
if (state !== "open") {
|
|
159
|
-
throw new DOMException(`RTCDataChannel.send: readyState is '${state}', expected 'open'`, "InvalidStateError");
|
|
160
|
-
}
|
|
161
|
-
if (typeof data === "string") {
|
|
162
|
-
this._native.send_string(data);
|
|
163
|
-
this._bufferedAmount += new TextEncoder().encode(data).byteLength;
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (data instanceof Blob) {
|
|
167
|
-
const blob = data;
|
|
168
|
-
blob.arrayBuffer().then((buf) => {
|
|
169
|
-
try {
|
|
170
|
-
this._native.send_data(toGBytes(buf));
|
|
171
|
-
this._bufferedAmount += buf.byteLength;
|
|
172
|
-
} catch {}
|
|
173
|
-
});
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
if (ArrayBuffer.isView(data)) {
|
|
177
|
-
const bytes = toGBytes(data);
|
|
178
|
-
this._native.send_data(bytes);
|
|
179
|
-
this._bufferedAmount += data.byteLength;
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (data instanceof ArrayBuffer) {
|
|
183
|
-
const bytes = toGBytes(data);
|
|
184
|
-
this._native.send_data(bytes);
|
|
185
|
-
this._bufferedAmount += data.byteLength;
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
throw new TypeError("RTCDataChannel.send: unsupported data type");
|
|
189
|
-
}
|
|
190
|
-
close() {
|
|
191
|
-
if (this._closed) return;
|
|
192
|
-
try {
|
|
193
|
-
this._native.close();
|
|
194
|
-
} catch {}
|
|
195
|
-
this._disconnectSignals();
|
|
196
|
-
this._closed = true;
|
|
197
|
-
}
|
|
198
|
-
/** @internal */
|
|
199
|
-
_disconnectSignals() {
|
|
200
|
-
try {
|
|
201
|
-
this._bridge.dispose_bridge();
|
|
202
|
-
} catch {}
|
|
203
|
-
}
|
|
204
|
-
_handleOpen() {
|
|
205
|
-
const ev = new Event("open");
|
|
206
|
-
this._onopen?.call(this, ev);
|
|
207
|
-
this.dispatchEvent(ev);
|
|
208
|
-
}
|
|
209
|
-
_handleClose() {
|
|
210
|
-
this._closed = true;
|
|
211
|
-
const ev = new Event("close");
|
|
212
|
-
this._onclose?.call(this, ev);
|
|
213
|
-
this.dispatchEvent(ev);
|
|
214
|
-
}
|
|
215
|
-
_handleError(message) {
|
|
216
|
-
const rtcErr = new RTCError({ errorDetail: "data-channel-failure" }, message || "RTCDataChannel error");
|
|
217
|
-
const ev = new RTCErrorEvent("error", { error: rtcErr });
|
|
218
|
-
this._onerror?.call(this, ev);
|
|
219
|
-
this.dispatchEvent(ev);
|
|
220
|
-
}
|
|
221
|
-
_handleString(data) {
|
|
222
|
-
const ev = new MessageEvent("message", { data });
|
|
223
|
-
this._onmessage?.call(this, ev);
|
|
224
|
-
this.dispatchEvent(ev);
|
|
225
|
-
}
|
|
226
|
-
_handleData(bytes) {
|
|
227
|
-
if (!bytes) return;
|
|
228
|
-
const buf = bytesToArrayBuffer(bytes);
|
|
229
|
-
const data = this._binaryType === "blob" ? new Blob([buf]) : buf;
|
|
230
|
-
const ev = new MessageEvent("message", { data });
|
|
231
|
-
this._onmessage?.call(this, ev);
|
|
232
|
-
this.dispatchEvent(ev);
|
|
233
|
-
}
|
|
234
|
-
_handleBufferedAmountLow() {
|
|
235
|
-
this._bufferedAmount = Number(this._native.buffered_amount) || 0;
|
|
236
|
-
const ev = new Event("bufferedamountlow");
|
|
237
|
-
this._onbufferedamountlow?.call(this, ev);
|
|
238
|
-
this.dispatchEvent(ev);
|
|
239
|
-
}
|
|
240
|
-
_handleReadyStateChange() {
|
|
241
|
-
if (this.readyState === "closing") {
|
|
242
|
-
const ev = new Event("closing");
|
|
243
|
-
this._onclosing?.call(this, ev);
|
|
244
|
-
this.dispatchEvent(ev);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
//#endregion
|
|
250
|
-
export { RTCDataChannel };
|
|
1
|
+
import{RTCError as e}from"./rtc-error.js";import{RTCErrorEvent as t}from"./rtc-events.js";import{DOMException as n}from"@gjsify/dom-exception";import r from"gi://GLib?version=2.0";import{DataChannelBridge as i}from"@gjsify/webrtc-native";import{Blob as a}from"@gjsify/buffer";const o={1:`connecting`,2:`open`,3:`closing`,4:`closed`};function s(e){let t;return t=ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(e),new r.Bytes(t)}function c(e){let t=e.toArray?.();if(t instanceof Uint8Array)return t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength);let n=e.get_data?.();return n instanceof Uint8Array?n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength):new ArrayBuffer(0)}var l=class extends EventTarget{_native;_bridge;_binaryType=`arraybuffer`;_bufferedAmount=0;_closed=!1;_onopen=null;_onclose=null;_onerror=null;_onmessage=null;_onbufferedamountlow=null;_onclosing=null;constructor(e){super(),e.channel!==void 0&&e.dispose_bridge?(this._bridge=e,this._native=this._bridge.channel):(this._native=e,this._bridge=new i({channel:this._native})),this._bridge.connect(`opened`,()=>this._handleOpen()),this._bridge.connect(`closed`,()=>this._handleClose()),this._bridge.connect(`error-occurred`,(e,t)=>this._handleError(t)),this._bridge.connect(`message-string`,(e,t)=>this._handleString(t)),this._bridge.connect(`message-data`,(e,t)=>this._handleData(t)),this._bridge.connect(`buffered-amount-low`,()=>this._handleBufferedAmountLow()),this._bridge.connect(`ready-state-changed`,()=>this._handleReadyStateChange())}get label(){return this._native.label}get ordered(){return this._native.ordered}get protocol(){return this._native.protocol}get negotiated(){return this._native.negotiated}get id(){return this._native.id>=0?this._native.id:null}get maxPacketLifeTime(){let e=this._native.max_packet_lifetime;return e>=0?e:null}get maxRetransmits(){let e=this._native.max_retransmits;return e>=0?e:null}get readyState(){return this._closed?`closed`:o[this._native.ready_state]??`connecting`}get bufferedAmount(){try{return Number(this._native.buffered_amount)||this._bufferedAmount}catch{return this._bufferedAmount}}get bufferedAmountLowThreshold(){return Number(this._native.buffered_amount_low_threshold)||0}set bufferedAmountLowThreshold(e){this._native.buffered_amount_low_threshold=e}get binaryType(){return this._binaryType}set binaryType(e){e!==`arraybuffer`&&e!==`blob`||(this._binaryType=e)}get onopen(){return this._onopen}set onopen(e){this._onopen=e}get onclose(){return this._onclose}set onclose(e){this._onclose=e}get onclosing(){return this._onclosing}set onclosing(e){this._onclosing=e}get onerror(){return this._onerror}set onerror(e){this._onerror=e}get onmessage(){return this._onmessage}set onmessage(e){this._onmessage=e}get onbufferedamountlow(){return this._onbufferedamountlow}set onbufferedamountlow(e){this._onbufferedamountlow=e}send(e){let t=this.readyState;if(t!==`open`)throw new n(`RTCDataChannel.send: readyState is '${t}', expected 'open'`,`InvalidStateError`);if(typeof e==`string`){this._native.send_string(e),this._bufferedAmount+=new TextEncoder().encode(e).byteLength;return}if(e instanceof a){e.arrayBuffer().then(e=>{try{this._native.send_data(s(e)),this._bufferedAmount+=e.byteLength}catch{}});return}if(ArrayBuffer.isView(e)){let t=s(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}if(e instanceof ArrayBuffer){let t=s(e);this._native.send_data(t),this._bufferedAmount+=e.byteLength;return}throw TypeError(`RTCDataChannel.send: unsupported data type`)}close(){if(!this._closed){try{this._native.close()}catch{}this._disconnectSignals(),this._closed=!0}}_disconnectSignals(){try{this._bridge.dispose_bridge()}catch{}}_handleOpen(){let e=new Event(`open`);this._onopen?.call(this,e),this.dispatchEvent(e)}_handleClose(){this._closed=!0;let e=new Event(`close`);this._onclose?.call(this,e),this.dispatchEvent(e)}_handleError(n){let r=new t(`error`,{error:new e({errorDetail:`data-channel-failure`},n||`RTCDataChannel error`)});this._onerror?.call(this,r),this.dispatchEvent(r)}_handleString(e){let t=new MessageEvent(`message`,{data:e});this._onmessage?.call(this,t),this.dispatchEvent(t)}_handleData(e){if(!e)return;let t=c(e),n=this._binaryType===`blob`?new a([t]):t,r=new MessageEvent(`message`,{data:n});this._onmessage?.call(this,r),this.dispatchEvent(r)}_handleBufferedAmountLow(){this._bufferedAmount=Number(this._native.buffered_amount)||0;let e=new Event(`bufferedamountlow`);this._onbufferedamountlow?.call(this,e),this.dispatchEvent(e)}_handleReadyStateChange(){if(this.readyState===`closing`){let e=new Event(`closing`);this._onclosing?.call(this,e),this.dispatchEvent(e)}}};export{l as RTCDataChannel};
|