werift 0.19.3 → 0.19.4

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.
@@ -1,7 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Flight3 = void 0;
7
+ const debug_1 = __importDefault(require("debug"));
4
8
  const flight_1 = require("../flight");
9
+ const log = (0, debug_1.default)("werift-dtls : packages/dtls/src/flight/client/flight3.ts : log");
5
10
  class Flight3 extends flight_1.Flight {
6
11
  constructor(udp, dtls) {
7
12
  super(udp, dtls, 3, 5);
@@ -12,6 +17,7 @@ class Flight3 extends flight_1.Flight {
12
17
  this.dtls.flight = 3;
13
18
  this.dtls.handshakeCache = [];
14
19
  const [clientHello] = this.dtls.lastFlight;
20
+ log("dtls version", clientHello.clientVersion);
15
21
  clientHello.cookie = verifyReq.cookie;
16
22
  this.dtls.cookie = verifyReq.cookie;
17
23
  const packets = this.createPacket([clientHello]);
@@ -1 +1 @@
1
- {"version":3,"file":"flight3.js","sourceRoot":"","sources":["../../../../../../dtls/src/flight/client/flight3.ts"],"names":[],"mappings":";;;AAIA,sCAAmC;AAEnC,MAAa,OAAQ,SAAQ,eAAM;IACjC,YAAY,GAAqB,EAAE,IAAiB;QAClD,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAmC;QAC5C,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAErB,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QAE9B,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAA2B,CAAC;QAC5D,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QAEpC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QAEjD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;CACF;AApBD,0BAoBC","sourcesContent":["import { DtlsContext } from \"../../context/dtls\";\nimport { TransportContext } from \"../../context/transport\";\nimport { ClientHello } from \"../../handshake/message/client/hello\";\nimport { ServerHelloVerifyRequest } from \"../../handshake/message/server/helloVerifyRequest\";\nimport { Flight } from \"../flight\";\n\nexport class Flight3 extends Flight {\n constructor(udp: TransportContext, dtls: DtlsContext) {\n super(udp, dtls, 3, 5);\n }\n\n async exec(verifyReq: ServerHelloVerifyRequest) {\n if (this.dtls.flight === 3) throw new Error();\n this.dtls.flight = 3;\n\n this.dtls.handshakeCache = [];\n\n const [clientHello] = this.dtls.lastFlight as [ClientHello];\n clientHello.cookie = verifyReq.cookie;\n this.dtls.cookie = verifyReq.cookie;\n\n const packets = this.createPacket([clientHello]);\n\n const buf = Buffer.concat(packets.map((v) => v.serialize()));\n await this.transmit([buf]);\n }\n}\n"]}
1
+ {"version":3,"file":"flight3.js","sourceRoot":"","sources":["../../../../../../dtls/src/flight/client/flight3.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAK1B,sCAAmC;AAEnC,MAAM,GAAG,GAAG,IAAA,eAAK,EACf,gEAAgE,CACjE,CAAC;AAEF,MAAa,OAAQ,SAAQ,eAAM;IACjC,YAAY,GAAqB,EAAE,IAAiB;QAClD,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAmC;QAC5C,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAErB,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QAE9B,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAA2B,CAAC;QAC5D,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;QAC/C,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QAEpC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QAEjD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;CACF;AArBD,0BAqBC","sourcesContent":["import debug from \"debug\";\nimport { DtlsContext } from \"../../context/dtls\";\nimport { TransportContext } from \"../../context/transport\";\nimport { ClientHello } from \"../../handshake/message/client/hello\";\nimport { ServerHelloVerifyRequest } from \"../../handshake/message/server/helloVerifyRequest\";\nimport { Flight } from \"../flight\";\n\nconst log = debug(\n \"werift-dtls : packages/dtls/src/flight/client/flight3.ts : log\",\n);\n\nexport class Flight3 extends Flight {\n constructor(udp: TransportContext, dtls: DtlsContext) {\n super(udp, dtls, 3, 5);\n }\n\n async exec(verifyReq: ServerHelloVerifyRequest) {\n if (this.dtls.flight === 3) throw new Error();\n this.dtls.flight = 3;\n\n this.dtls.handshakeCache = [];\n\n const [clientHello] = this.dtls.lastFlight as [ClientHello];\n log(\"dtls version\", clientHello.clientVersion);\n clientHello.cookie = verifyReq.cookie;\n this.dtls.cookie = verifyReq.cookie;\n\n const packets = this.createPacket([clientHello]);\n\n const buf = Buffer.concat(packets.map((v) => v.serialize()));\n await this.transmit([buf]);\n }\n}\n"]}
@@ -21,6 +21,7 @@ const const_2 = require("../../record/const");
21
21
  const log = (0, debug_1.default)("werift-dtls : packages/dtls/flight/server/flight2.ts : log");
22
22
  // HelloVerifyRequest do not retransmit
23
23
  const flight2 = (udp, dtls, cipher, srtp) => (clientHello) => {
24
+ log("dtls version", clientHello.clientVersion);
24
25
  dtls.flight = 2;
25
26
  // if flight 2 restarts due to packet loss, sequence numbers are reused from the top:
26
27
  // https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.2
@@ -77,9 +78,15 @@ const flight2 = (udp, dtls, cipher, srtp) => (clientHello) => {
77
78
  dtls.remoteExtendedMasterSecret = true;
78
79
  }
79
80
  break;
80
- case renegotiationIndication_1.RenegotiationIndication.type:
81
+ case renegotiationIndication_1.RenegotiationIndication.type: {
82
+ log(dtls.sessionId, "RenegotiationIndication", extension.data);
83
+ }
84
+ case 43:
81
85
  {
82
- log(dtls.sessionId, "RenegotiationIndication", extension.data);
86
+ // todo dtls1.3
87
+ const data = extension.data.subarray(1);
88
+ const versions = [...data].map((v) => v.toString(10));
89
+ log("dtls supported version", versions);
83
90
  }
84
91
  break;
85
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"flight2.js","sourceRoot":"","sources":["../../../../../../dtls/src/flight/server/flight2.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"crypto\";\nimport debug from \"debug\";\n\nimport {\n CipherSuite,\n NamedCurveAlgorithmList,\n NamedCurveAlgorithms,\n SignatureAlgorithm,\n} from \"../../cipher/const\";\nimport { generateKeyPair } from \"../../cipher/namedCurve\";\nimport { CipherContext } from \"../../context/cipher\";\nimport { DtlsContext } from \"../../context/dtls\";\nimport { Profile, SrtpContext } from \"../../context/srtp\";\nimport { TransportContext } from \"../../context/transport\";\nimport { EllipticCurves } from \"../../handshake/extensions/ellipticCurves\";\nimport { ExtendedMasterSecret } from \"../../handshake/extensions/extendedMasterSecret\";\nimport { RenegotiationIndication } from \"../../handshake/extensions/renegotiationIndication\";\nimport { Signature } from \"../../handshake/extensions/signature\";\nimport { UseSRTP } from \"../../handshake/extensions/useSrtp\";\nimport { ClientHello } from \"../../handshake/message/client/hello\";\nimport { ServerHelloVerifyRequest } from \"../../handshake/message/server/helloVerifyRequest\";\nimport { DtlsRandom } from \"../../handshake/random\";\nimport { createFragments, createPlaintext } from \"../../record/builder\";\nimport { ContentType } from \"../../record/const\";\n\nconst log = debug(\"werift-dtls : packages/dtls/flight/server/flight2.ts : log\");\n\n// HelloVerifyRequest do not retransmit\n\nexport const flight2 =\n (\n udp: TransportContext,\n dtls: DtlsContext,\n cipher: CipherContext,\n srtp: SrtpContext,\n ) =>\n (clientHello: ClientHello) => {\n dtls.flight = 2;\n\n // if flight 2 restarts due to packet loss, sequence numbers are reused from the top:\n // https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.2\n // The first message each side transmits in each handshake always has\n // message_seq = 0. Whenever each new message is generated, the\n // message_seq value is incremented by one. Note that in the case of a\n // rehandshake, this implies that the HelloRequest will have message_seq = 0\n // and the ServerHello will have message_seq = 1. When a message is\n // retransmitted, the same message_seq value is used.\n dtls.recordSequenceNumber = 0;\n dtls.sequenceNumber = 0;\n\n clientHello.extensions.forEach((extension) => {\n switch (extension.type) {\n case EllipticCurves.type: {\n const curves = EllipticCurves.fromData(extension.data).data;\n log(dtls.sessionId, \"curves\", curves);\n const curve = curves.filter((curve) =>\n NamedCurveAlgorithmList.includes(curve as any),\n )[0] as NamedCurveAlgorithms;\n cipher.namedCurve = curve;\n log(dtls.sessionId, \"curve selected\", cipher.namedCurve);\n }\n break;\n case Signature.type: {\n if (!cipher.signatureHashAlgorithm)\n throw new Error(\"need to set certificate\");\n\n const signatureHash = Signature.fromData(extension.data).data;\n log(dtls.sessionId, \"hash,signature\", signatureHash);\n const signature = signatureHash.find(\n (v) => v.signature === cipher.signatureHashAlgorithm?.signature,\n )?.signature;\n const hash = signatureHash.find(\n (v) => v.hash === cipher.signatureHashAlgorithm?.hash,\n )?.hash;\n if (signature == undefined || hash == undefined) {\n throw new Error(\"invalid signatureHash\");\n }\n }\n break;\n case UseSRTP.type: {\n if (!dtls.options?.srtpProfiles) return;\n if (dtls.options.srtpProfiles.length === 0) return;\n\n const useSrtp = UseSRTP.fromData(extension.data);\n log(dtls.sessionId, \"srtp profiles\", useSrtp.profiles);\n const profile = SrtpContext.findMatchingSRTPProfile(\n useSrtp.profiles as Profile[],\n dtls.options?.srtpProfiles,\n );\n if (!profile) {\n throw new Error();\n }\n srtp.srtpProfile = profile;\n log(dtls.sessionId, \"srtp profile selected\", srtp.srtpProfile);\n }\n break;\n case ExtendedMasterSecret.type: {\n dtls.remoteExtendedMasterSecret = true;\n }\n break;\n case RenegotiationIndication.type: {\n log(dtls.sessionId, \"RenegotiationIndication\", extension.data);\n }\n break;\n }\n });\n\n cipher.localRandom = new DtlsRandom();\n cipher.remoteRandom = DtlsRandom.from(clientHello.random);\n\n const suites = clientHello.cipherSuites;\n log(dtls.sessionId, \"cipher suites\", suites);\n const suite = (() => {\n switch (cipher.signatureHashAlgorithm?.signature) {\n case SignatureAlgorithm.ecdsa_3:\n return CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_49195;\n case SignatureAlgorithm.rsa_1:\n return CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256_49199;\n }\n })();\n if (suite === undefined || !suites.includes(suite)) {\n throw new Error(\"dtls cipher suite negotiation failed\");\n }\n cipher.cipherSuite = suite;\n log(dtls.sessionId, \"selected cipherSuite\", cipher.cipherSuite);\n\n cipher.localKeyPair = generateKeyPair(cipher.namedCurve);\n\n dtls.cookie ||= randomBytes(20);\n const helloVerifyReq = new ServerHelloVerifyRequest(\n {\n major: 255 - 1,\n minor: 255 - 2,\n },\n dtls.cookie,\n );\n const fragments = createFragments(dtls)([helloVerifyReq]);\n const packets = createPlaintext(dtls)(\n fragments.map((fragment) => ({\n type: ContentType.handshake,\n fragment: fragment.serialize(),\n })),\n ++dtls.recordSequenceNumber,\n );\n\n const chunk = packets.map((v) => v.serialize());\n for (const buf of chunk) {\n udp.send(buf);\n }\n };\n"]}
1
+ {"version":3,"file":"flight2.js","sourceRoot":"","sources":["../../../../../../dtls/src/flight/server/flight2.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"crypto\";\nimport debug from \"debug\";\n\nimport {\n CipherSuite,\n NamedCurveAlgorithmList,\n NamedCurveAlgorithms,\n SignatureAlgorithm,\n} from \"../../cipher/const\";\nimport { generateKeyPair } from \"../../cipher/namedCurve\";\nimport { CipherContext } from \"../../context/cipher\";\nimport { DtlsContext } from \"../../context/dtls\";\nimport { Profile, SrtpContext } from \"../../context/srtp\";\nimport { TransportContext } from \"../../context/transport\";\nimport { EllipticCurves } from \"../../handshake/extensions/ellipticCurves\";\nimport { ExtendedMasterSecret } from \"../../handshake/extensions/extendedMasterSecret\";\nimport { RenegotiationIndication } from \"../../handshake/extensions/renegotiationIndication\";\nimport { Signature } from \"../../handshake/extensions/signature\";\nimport { UseSRTP } from \"../../handshake/extensions/useSrtp\";\nimport { ClientHello } from \"../../handshake/message/client/hello\";\nimport { ServerHelloVerifyRequest } from \"../../handshake/message/server/helloVerifyRequest\";\nimport { DtlsRandom } from \"../../handshake/random\";\nimport { createFragments, createPlaintext } from \"../../record/builder\";\nimport { ContentType } from \"../../record/const\";\n\nconst log = debug(\"werift-dtls : packages/dtls/flight/server/flight2.ts : log\");\n\n// HelloVerifyRequest do not retransmit\n\nexport const flight2 =\n (\n udp: TransportContext,\n dtls: DtlsContext,\n cipher: CipherContext,\n srtp: SrtpContext,\n ) =>\n (clientHello: ClientHello) => {\n log(\"dtls version\", clientHello.clientVersion);\n\n dtls.flight = 2;\n\n // if flight 2 restarts due to packet loss, sequence numbers are reused from the top:\n // https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.2\n // The first message each side transmits in each handshake always has\n // message_seq = 0. Whenever each new message is generated, the\n // message_seq value is incremented by one. Note that in the case of a\n // rehandshake, this implies that the HelloRequest will have message_seq = 0\n // and the ServerHello will have message_seq = 1. When a message is\n // retransmitted, the same message_seq value is used.\n dtls.recordSequenceNumber = 0;\n dtls.sequenceNumber = 0;\n\n clientHello.extensions.forEach((extension) => {\n switch (extension.type) {\n case EllipticCurves.type: {\n const curves = EllipticCurves.fromData(extension.data).data;\n log(dtls.sessionId, \"curves\", curves);\n const curve = curves.filter((curve) =>\n NamedCurveAlgorithmList.includes(curve as any),\n )[0] as NamedCurveAlgorithms;\n cipher.namedCurve = curve;\n log(dtls.sessionId, \"curve selected\", cipher.namedCurve);\n }\n break;\n case Signature.type: {\n if (!cipher.signatureHashAlgorithm)\n throw new Error(\"need to set certificate\");\n\n const signatureHash = Signature.fromData(extension.data).data;\n log(dtls.sessionId, \"hash,signature\", signatureHash);\n const signature = signatureHash.find(\n (v) => v.signature === cipher.signatureHashAlgorithm?.signature,\n )?.signature;\n const hash = signatureHash.find(\n (v) => v.hash === cipher.signatureHashAlgorithm?.hash,\n )?.hash;\n if (signature == undefined || hash == undefined) {\n throw new Error(\"invalid signatureHash\");\n }\n }\n break;\n case UseSRTP.type: {\n if (!dtls.options?.srtpProfiles) return;\n if (dtls.options.srtpProfiles.length === 0) return;\n\n const useSrtp = UseSRTP.fromData(extension.data);\n log(dtls.sessionId, \"srtp profiles\", useSrtp.profiles);\n const profile = SrtpContext.findMatchingSRTPProfile(\n useSrtp.profiles as Profile[],\n dtls.options?.srtpProfiles,\n );\n if (!profile) {\n throw new Error();\n }\n srtp.srtpProfile = profile;\n log(dtls.sessionId, \"srtp profile selected\", srtp.srtpProfile);\n }\n break;\n case ExtendedMasterSecret.type: {\n dtls.remoteExtendedMasterSecret = true;\n }\n break;\n case RenegotiationIndication.type: {\n log(dtls.sessionId, \"RenegotiationIndication\", extension.data);\n }\n case 43: {\n // todo dtls1.3\n const data = extension.data.subarray(1);\n const versions = [...data].map((v) => v.toString(10));\n log(\"dtls supported version\", versions);\n }\n break;\n }\n });\n\n cipher.localRandom = new DtlsRandom();\n cipher.remoteRandom = DtlsRandom.from(clientHello.random);\n\n const suites = clientHello.cipherSuites;\n log(dtls.sessionId, \"cipher suites\", suites);\n const suite = (() => {\n switch (cipher.signatureHashAlgorithm?.signature) {\n case SignatureAlgorithm.ecdsa_3:\n return CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_49195;\n case SignatureAlgorithm.rsa_1:\n return CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256_49199;\n }\n })();\n if (suite === undefined || !suites.includes(suite)) {\n throw new Error(\"dtls cipher suite negotiation failed\");\n }\n cipher.cipherSuite = suite;\n log(dtls.sessionId, \"selected cipherSuite\", cipher.cipherSuite);\n\n cipher.localKeyPair = generateKeyPair(cipher.namedCurve);\n\n dtls.cookie ||= randomBytes(20);\n const helloVerifyReq = new ServerHelloVerifyRequest(\n {\n major: 255 - 1,\n minor: 255 - 2,\n },\n dtls.cookie,\n );\n const fragments = createFragments(dtls)([helloVerifyReq]);\n const packets = createPlaintext(dtls)(\n fragments.map((fragment) => ({\n type: ContentType.handshake,\n fragment: fragment.serialize(),\n })),\n ++dtls.recordSequenceNumber,\n );\n\n const chunk = packets.map((v) => v.serialize());\n for (const buf of chunk) {\n udp.send(buf);\n }\n };\n"]}
@@ -31,7 +31,9 @@ export declare class MediaStreamTrack extends EventTarget {
31
31
  export declare class MediaStream {
32
32
  id: string;
33
33
  tracks: MediaStreamTrack[];
34
- constructor(props: Partial<MediaStream> & Pick<MediaStream, "id">);
34
+ constructor(props: Partial<MediaStream> | MediaStreamTrack[]);
35
35
  addTrack(track: MediaStreamTrack): void;
36
36
  getTracks(): MediaStreamTrack[];
37
+ getAudioTracks(): MediaStreamTrack[];
38
+ getVideoTracks(): MediaStreamTrack[];
37
39
  }
@@ -118,6 +118,7 @@ class MediaStreamTrack extends helper_1.EventTarget {
118
118
  this.stopped = true;
119
119
  this.muted = true;
120
120
  this.onReceiveRtp.complete();
121
+ this.emit("ended");
121
122
  }
122
123
  });
123
124
  Object.defineProperty(this, "writeRtp", {
@@ -160,7 +161,13 @@ class MediaStream {
160
161
  writable: true,
161
162
  value: []
162
163
  });
163
- Object.assign(this, props);
164
+ if (Array.isArray(props)) {
165
+ this.tracks = props;
166
+ }
167
+ else {
168
+ Object.assign(this, props);
169
+ }
170
+ this.id ?? (this.id = (0, uuid_1.v4)());
164
171
  }
165
172
  addTrack(track) {
166
173
  track.streamId = this.id;
@@ -169,6 +176,12 @@ class MediaStream {
169
176
  getTracks() {
170
177
  return this.tracks;
171
178
  }
179
+ getAudioTracks() {
180
+ return this.tracks.filter((track) => track.kind === "audio");
181
+ }
182
+ getVideoTracks() {
183
+ return this.tracks.filter((track) => track.kind === "video");
184
+ }
172
185
  }
173
186
  exports.MediaStream = MediaStream;
174
187
  //# sourceMappingURL=track.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"track.js","sourceRoot":"","sources":["../../../../src/media/track.ts"],"names":[],"mappings":";;;;;;AAAA,sDAA4B;AAC5B,+BAA0B;AAE1B,0CAAoE;AACpE,sCAAwC;AAIxC,MAAa,gBAAiB,SAAQ,oBAAW;IAyB/C,YACE,KAAiE;QAEjE,KAAK,EAAE,CAAC;QA3BD;;;;mBAAO,IAAA,SAAE,GAAE;WAAC;QACrB,mBAAmB;QACnB;;;;;WAAkB;QAClB;;;;mBAAS,KAAK;WAAC;QACf;;;;;WAAc;QACd;;;;;WAAY;QACZ;;;;;WAAY;QACZ,eAAe;QACf;;;;;WAAc;QACd;;;;;WAAa;QACb;;;;;WAAmB;QACnB;;;;;WAA8B;QAC9B,eAAe;QACf;;;;mBAAU,IAAI;WAAC;QAEN;;;;mBAAe,IAAI,iBAAK,EAAe;WAAC;QACxC;;;;mBAAgB,IAAI,iBAAK,EAAgB;WAAC;QAC1C;;;;mBAAkB,IAAI,iBAAK,EAEjC;WAAC;QAEJ;;;;mBAAU,KAAK;WAAC;QAChB;;;;mBAAQ,IAAI;WAAC;QAgBb;;;;mBAAO,GAAG,EAAE;gBACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;gBAClB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC/B,CAAC;WAAC;QAEF;;;;mBAAW,CAAC,GAAuB,EAAE,EAAE;gBACrC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBACzC,CAAC;gBACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjB,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,eAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACvE,MAAM,CAAC,MAAM,CAAC,WAAW;oBACvB,IAAI,CAAC,KAAK,EAAE,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;gBACvD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACpC,CAAC;WAAC;QA5BA,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE3B,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;YAClC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IAClE,CAAC;CAqBF;AA1DD,4CA0DC;AAED,MAAa,WAAW;IAItB,YAAY,KAAqD;QAHjE;;;;;WAAY;QACZ;;;;mBAA6B,EAAE;WAAC;QAG9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,KAAuB;QAC9B,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAhBD,kCAgBC","sourcesContent":["import Event from \"rx.mini\";\nimport { v4 } from \"uuid\";\n\nimport { RtcpPacket, RtpHeader, RtpPacket } from \"../../../rtp/src\";\nimport { EventTarget } from \"../helper\";\nimport { Kind } from \"../types/domain\";\nimport { RTCRtpCodecParameters } from \"./parameters\";\n\nexport class MediaStreamTrack extends EventTarget {\n readonly uuid = v4();\n /**MediaStream ID*/\n streamId?: string;\n remote = false;\n label: string;\n kind!: Kind;\n id?: string;\n /**mediaSsrc */\n ssrc?: number;\n rid?: string;\n header?: RtpHeader;\n codec?: RTCRtpCodecParameters;\n /**todo impl */\n enabled = true;\n\n readonly onReceiveRtp = new Event<[RtpPacket]>();\n readonly onReceiveRtcp = new Event<[RtcpPacket]>();\n readonly onSourceChanged = new Event<\n [Pick<RtpHeader, \"sequenceNumber\" | \"timestamp\">]\n >();\n\n stopped = false;\n muted = true;\n\n constructor(\n props: Partial<MediaStreamTrack> & Pick<MediaStreamTrack, \"kind\">,\n ) {\n super();\n Object.assign(this, props);\n\n this.onReceiveRtp.subscribe((rtp) => {\n this.muted = false;\n this.header = rtp.header;\n });\n\n this.label = `${this.remote ? \"remote\" : \"local\"} ${this.kind}`;\n }\n\n stop = () => {\n this.stopped = true;\n this.muted = true;\n this.onReceiveRtp.complete();\n };\n\n writeRtp = (rtp: RtpPacket | Buffer) => {\n if (this.remote) {\n throw new Error(\"this is remoteTrack\");\n }\n if (this.stopped) {\n return;\n }\n\n const packet = Buffer.isBuffer(rtp) ? RtpPacket.deSerialize(rtp) : rtp;\n packet.header.payloadType =\n this.codec?.payloadType ?? packet.header.payloadType;\n this.onReceiveRtp.execute(packet);\n };\n}\n\nexport class MediaStream {\n id!: string;\n tracks: MediaStreamTrack[] = [];\n\n constructor(props: Partial<MediaStream> & Pick<MediaStream, \"id\">) {\n Object.assign(this, props);\n }\n\n addTrack(track: MediaStreamTrack) {\n track.streamId = this.id;\n this.tracks.push(track);\n }\n\n getTracks() {\n return this.tracks;\n }\n}\n"]}
1
+ {"version":3,"file":"track.js","sourceRoot":"","sources":["../../../../src/media/track.ts"],"names":[],"mappings":"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","sourcesContent":["import Event from \"rx.mini\";\nimport { v4 } from \"uuid\";\n\nimport { RtcpPacket, RtpHeader, RtpPacket } from \"../../../rtp/src\";\nimport { EventTarget } from \"../helper\";\nimport { Kind } from \"../types/domain\";\nimport { RTCRtpCodecParameters } from \"./parameters\";\n\nexport class MediaStreamTrack extends EventTarget {\n readonly uuid = v4();\n /**MediaStream ID*/\n streamId?: string;\n remote = false;\n label: string;\n kind!: Kind;\n id?: string;\n /**mediaSsrc */\n ssrc?: number;\n rid?: string;\n header?: RtpHeader;\n codec?: RTCRtpCodecParameters;\n /**todo impl */\n enabled = true;\n\n readonly onReceiveRtp = new Event<[RtpPacket]>();\n readonly onReceiveRtcp = new Event<[RtcpPacket]>();\n readonly onSourceChanged = new Event<\n [Pick<RtpHeader, \"sequenceNumber\" | \"timestamp\">]\n >();\n\n stopped = false;\n muted = true;\n\n constructor(\n props: Partial<MediaStreamTrack> & Pick<MediaStreamTrack, \"kind\">,\n ) {\n super();\n Object.assign(this, props);\n\n this.onReceiveRtp.subscribe((rtp) => {\n this.muted = false;\n this.header = rtp.header;\n });\n\n this.label = `${this.remote ? \"remote\" : \"local\"} ${this.kind}`;\n }\n\n stop = () => {\n this.stopped = true;\n this.muted = true;\n this.onReceiveRtp.complete();\n this.emit(\"ended\");\n };\n\n writeRtp = (rtp: RtpPacket | Buffer) => {\n if (this.remote) {\n throw new Error(\"this is remoteTrack\");\n }\n if (this.stopped) {\n return;\n }\n\n const packet = Buffer.isBuffer(rtp) ? RtpPacket.deSerialize(rtp) : rtp;\n packet.header.payloadType =\n this.codec?.payloadType ?? packet.header.payloadType;\n this.onReceiveRtp.execute(packet);\n };\n}\n\nexport class MediaStream {\n id!: string;\n tracks: MediaStreamTrack[] = [];\n\n constructor(props: Partial<MediaStream> | MediaStreamTrack[]) {\n if (Array.isArray(props)) {\n this.tracks = props;\n } else {\n Object.assign(this, props);\n }\n this.id ??= v4();\n }\n\n addTrack(track: MediaStreamTrack) {\n track.streamId = this.id;\n this.tracks.push(track);\n }\n\n getTracks() {\n return this.tracks;\n }\n\n getAudioTracks() {\n return this.tracks.filter((track) => track.kind === \"audio\");\n }\n\n getVideoTracks() {\n return this.tracks.filter((track) => track.kind === \"video\");\n }\n}\n"]}
@@ -1,2 +1,3 @@
1
1
  export * from "./recorder";
2
2
  export * from "./userMedia";
3
+ export * from "./navigator";
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./recorder"), exports);
18
18
  __exportStar(require("./userMedia"), exports);
19
+ __exportStar(require("./navigator"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/nonstandard/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,8CAA4B","sourcesContent":["export * from \"./recorder\";\nexport * from \"./userMedia\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/nonstandard/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,8CAA4B;AAC5B,8CAA4B","sourcesContent":["export * from \"./recorder\";\nexport * from \"./userMedia\";\nexport * from \"./navigator\";\n"]}
@@ -0,0 +1,71 @@
1
+ /// <reference types="react" />
2
+ /// <reference types="node" />
3
+ import { MediaStream, MediaStreamTrack } from "../media/track";
4
+ export declare class Navigator {
5
+ mediaDevices: MediaDevices;
6
+ constructor(props?: ConstructorParameters<typeof MediaDevices>[0]);
7
+ }
8
+ export declare class MediaDevices extends EventTarget {
9
+ video?: MediaStreamTrack;
10
+ audio?: MediaStreamTrack;
11
+ constructor(props: {
12
+ video?: MediaStreamTrack;
13
+ audio?: MediaStreamTrack;
14
+ });
15
+ readonly getUserMedia: (constraints: MediaStreamConstraints) => Promise<MediaStream>;
16
+ readonly getDisplayMedia: (constraints: MediaStreamConstraints) => Promise<MediaStream>;
17
+ }
18
+ interface MediaStreamConstraints {
19
+ audio?: boolean | MediaTrackConstraints;
20
+ peerIdentity?: string;
21
+ preferCurrentTab?: boolean;
22
+ video?: boolean | MediaTrackConstraints;
23
+ }
24
+ interface MediaTrackConstraints extends MediaTrackConstraintSet {
25
+ advanced?: MediaTrackConstraintSet[];
26
+ }
27
+ interface MediaTrackConstraintSet {
28
+ aspectRatio?: ConstrainDouble;
29
+ autoGainControl?: ConstrainBoolean;
30
+ channelCount?: ConstrainULong;
31
+ deviceId?: ConstrainDOMString;
32
+ displaySurface?: ConstrainDOMString;
33
+ echoCancellation?: ConstrainBoolean;
34
+ facingMode?: ConstrainDOMString;
35
+ frameRate?: ConstrainDouble;
36
+ groupId?: ConstrainDOMString;
37
+ height?: ConstrainULong;
38
+ noiseSuppression?: ConstrainBoolean;
39
+ sampleRate?: ConstrainULong;
40
+ sampleSize?: ConstrainULong;
41
+ width?: ConstrainULong;
42
+ }
43
+ type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;
44
+ interface ConstrainDOMStringParameters {
45
+ exact?: string | string[];
46
+ ideal?: string | string[];
47
+ }
48
+ type ConstrainBoolean = boolean | ConstrainBooleanParameters;
49
+ interface ConstrainBooleanParameters {
50
+ exact?: boolean;
51
+ ideal?: boolean;
52
+ }
53
+ type ConstrainULong = number | ConstrainULongRange;
54
+ interface ConstrainULongRange extends ULongRange {
55
+ exact?: number;
56
+ ideal?: number;
57
+ }
58
+ interface ULongRange {
59
+ max?: number;
60
+ min?: number;
61
+ }
62
+ type ConstrainDouble = number | ConstrainDoubleRange;
63
+ interface ConstrainDoubleRange extends DoubleRange {
64
+ exact?: number;
65
+ ideal?: number;
66
+ }
67
+ interface DoubleRange {
68
+ max?: number;
69
+ min?: number;
70
+ }
71
+ export {};
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MediaDevices = exports.Navigator = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const jspack_1 = require("@shinyoshiaki/jspack");
6
+ const track_1 = require("../media/track");
7
+ class Navigator {
8
+ constructor(props = {}) {
9
+ Object.defineProperty(this, "mediaDevices", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ this.mediaDevices = new MediaDevices(props);
16
+ }
17
+ }
18
+ exports.Navigator = Navigator;
19
+ class MediaDevices extends EventTarget {
20
+ constructor(props) {
21
+ super();
22
+ Object.defineProperty(this, "video", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ Object.defineProperty(this, "audio", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: void 0
33
+ });
34
+ Object.defineProperty(this, "getUserMedia", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: async (constraints) => {
39
+ const video = constraints.video
40
+ ? new track_1.MediaStreamTrack({ kind: "video" })
41
+ : undefined;
42
+ if (video) {
43
+ this.video?.onReceiveRtp.subscribe((rtp) => {
44
+ const cloned = rtp.clone();
45
+ cloned.header.ssrc = jspack_1.jspack.Unpack("!L", (0, crypto_1.randomBytes)(4))[0];
46
+ video.onReceiveRtp.execute(cloned);
47
+ });
48
+ }
49
+ const audio = constraints.audio
50
+ ? new track_1.MediaStreamTrack({ kind: "audio" })
51
+ : undefined;
52
+ if (audio) {
53
+ this.audio?.onReceiveRtp.subscribe((rtp) => {
54
+ const cloned = rtp.clone();
55
+ cloned.header.ssrc = jspack_1.jspack.Unpack("!L", (0, crypto_1.randomBytes)(4))[0];
56
+ audio.onReceiveRtp.execute(cloned);
57
+ });
58
+ }
59
+ if (constraints.video && constraints.audio) {
60
+ return new track_1.MediaStream([video, audio]);
61
+ }
62
+ else if (constraints.audio) {
63
+ return new track_1.MediaStream([audio]);
64
+ }
65
+ else if (constraints.video) {
66
+ return new track_1.MediaStream([video]);
67
+ }
68
+ throw new Error("Not implemented");
69
+ }
70
+ });
71
+ Object.defineProperty(this, "getDisplayMedia", {
72
+ enumerable: true,
73
+ configurable: true,
74
+ writable: true,
75
+ value: this.getUserMedia
76
+ });
77
+ this.video = props.video;
78
+ this.audio = props.audio;
79
+ }
80
+ }
81
+ exports.MediaDevices = MediaDevices;
82
+ //# sourceMappingURL=navigator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigator.js","sourceRoot":"","sources":["../../../../src/nonstandard/navigator.ts"],"names":[],"mappings":";;;AAAA,mCAAqC;AACrC,iDAA8C;AAC9C,0CAA+D;AAE/D,MAAa,SAAS;IAGpB,YAAY,QAAuD,EAAE;QAFrE;;;;;WAA2B;QAGzB,IAAI,CAAC,YAAY,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF;AAND,8BAMC;AAED,MAAa,YAAa,SAAQ,WAAW;IAI3C,YAAY,KAA6D;QACvE,KAAK,EAAE,CAAC;QAJV;;;;;WAAyB;QACzB;;;;;WAAyB;QAQhB;;;;mBAAe,KAAK,EAC3B,WAAmC,EACb,EAAE;gBACxB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK;oBAC7B,CAAC,CAAC,IAAI,wBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oBACzC,CAAC,CAAC,SAAS,CAAC;gBACd,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;wBACzC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;wBAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,eAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC5D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACrC,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK;oBAC7B,CAAC,CAAC,IAAI,wBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oBACzC,CAAC,CAAC,SAAS,CAAC;gBACd,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;wBACzC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;wBAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,eAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC5D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACrC,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,WAAW,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBAC3C,OAAO,IAAI,mBAAW,CAAC,CAAC,KAAM,EAAE,KAAM,CAAC,CAAC,CAAC;gBAC3C,CAAC;qBAAM,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBAC7B,OAAO,IAAI,mBAAW,CAAC,CAAC,KAAM,CAAC,CAAC,CAAC;gBACnC,CAAC;qBAAM,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;oBAC7B,OAAO,IAAI,mBAAW,CAAC,CAAC,KAAM,CAAC,CAAC,CAAC;gBACnC,CAAC;gBAED,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrC,CAAC;WAAC;QAEO;;;;mBAAkB,IAAI,CAAC,YAAY;WAAC;QAvC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,CAAC;CAsCF;AA9CD,oCA8CC","sourcesContent":["import { randomBytes } from \"crypto\";\nimport { jspack } from \"@shinyoshiaki/jspack\";\nimport { MediaStream, MediaStreamTrack } from \"../media/track\";\n\nexport class Navigator {\n mediaDevices: MediaDevices;\n\n constructor(props: ConstructorParameters<typeof MediaDevices>[0] = {}) {\n this.mediaDevices = new MediaDevices(props);\n }\n}\n\nexport class MediaDevices extends EventTarget {\n video?: MediaStreamTrack;\n audio?: MediaStreamTrack;\n\n constructor(props: { video?: MediaStreamTrack; audio?: MediaStreamTrack }) {\n super();\n this.video = props.video;\n this.audio = props.audio;\n }\n\n readonly getUserMedia = async (\n constraints: MediaStreamConstraints,\n ): Promise<MediaStream> => {\n const video = constraints.video\n ? new MediaStreamTrack({ kind: \"video\" })\n : undefined;\n if (video) {\n this.video?.onReceiveRtp.subscribe((rtp) => {\n const cloned = rtp.clone();\n cloned.header.ssrc = jspack.Unpack(\"!L\", randomBytes(4))[0];\n video.onReceiveRtp.execute(cloned);\n });\n }\n const audio = constraints.audio\n ? new MediaStreamTrack({ kind: \"audio\" })\n : undefined;\n if (audio) {\n this.audio?.onReceiveRtp.subscribe((rtp) => {\n const cloned = rtp.clone();\n cloned.header.ssrc = jspack.Unpack(\"!L\", randomBytes(4))[0];\n audio.onReceiveRtp.execute(cloned);\n });\n }\n\n if (constraints.video && constraints.audio) {\n return new MediaStream([video!, audio!]);\n } else if (constraints.audio) {\n return new MediaStream([audio!]);\n } else if (constraints.video) {\n return new MediaStream([video!]);\n }\n\n throw new Error(\"Not implemented\");\n };\n\n readonly getDisplayMedia = this.getUserMedia;\n}\n\ninterface MediaStreamConstraints {\n audio?: boolean | MediaTrackConstraints;\n peerIdentity?: string;\n preferCurrentTab?: boolean;\n video?: boolean | MediaTrackConstraints;\n}\n\ninterface MediaTrackConstraints extends MediaTrackConstraintSet {\n advanced?: MediaTrackConstraintSet[];\n}\n\ninterface MediaTrackConstraintSet {\n aspectRatio?: ConstrainDouble;\n autoGainControl?: ConstrainBoolean;\n channelCount?: ConstrainULong;\n deviceId?: ConstrainDOMString;\n displaySurface?: ConstrainDOMString;\n echoCancellation?: ConstrainBoolean;\n facingMode?: ConstrainDOMString;\n frameRate?: ConstrainDouble;\n groupId?: ConstrainDOMString;\n height?: ConstrainULong;\n noiseSuppression?: ConstrainBoolean;\n sampleRate?: ConstrainULong;\n sampleSize?: ConstrainULong;\n width?: ConstrainULong;\n}\n\ntype ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;\ninterface ConstrainDOMStringParameters {\n exact?: string | string[];\n ideal?: string | string[];\n}\ntype ConstrainBoolean = boolean | ConstrainBooleanParameters;\ninterface ConstrainBooleanParameters {\n exact?: boolean;\n ideal?: boolean;\n}\ntype ConstrainULong = number | ConstrainULongRange;\ninterface ConstrainULongRange extends ULongRange {\n exact?: number;\n ideal?: number;\n}\ninterface ULongRange {\n max?: number;\n min?: number;\n}\ntype ConstrainDouble = number | ConstrainDoubleRange;\ninterface ConstrainDoubleRange extends DoubleRange {\n exact?: number;\n ideal?: number;\n}\ninterface DoubleRange {\n max?: number;\n min?: number;\n}\n"]}
@@ -35,9 +35,10 @@ export declare const createSelfSignedCertificate: (signatureHash: import(".").Si
35
35
  signatureHash: import(".").SignatureHash;
36
36
  }>;
37
37
  export declare class MediaStreamTrackFactory {
38
- static rtpSource({ port, kind, }: {
38
+ static rtpSource({ port, kind, cb, }: {
39
39
  port?: number;
40
40
  kind: "audio" | "video";
41
+ cb?: (buf: Buffer) => Buffer;
41
42
  }): Promise<readonly [MediaStreamTrack, number, () => void]>;
42
43
  }
43
44
  export declare const deepMerge: <T>(dst: T, src: T) => T;
@@ -97,12 +97,15 @@ exports.parseIceServers = parseIceServers;
97
97
  */
98
98
  exports.createSelfSignedCertificate = cipher_1.CipherContext.createSelfSignedCertificateWithKey;
99
99
  class MediaStreamTrackFactory {
100
- static async rtpSource({ port, kind, }) {
100
+ static async rtpSource({ port, kind, cb, }) {
101
101
  port ?? (port = await (0, src_1.randomPort)());
102
102
  const track = new track_1.MediaStreamTrack({ kind });
103
103
  const udp = (0, dgram_1.createSocket)("udp4");
104
104
  udp.bind(port);
105
- const onMessage = (msg, rinfo) => {
105
+ const onMessage = (msg) => {
106
+ if (cb) {
107
+ msg = cb(msg);
108
+ }
106
109
  track.writeRtp(msg);
107
110
  };
108
111
  udp.addListener("message", onMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable prefer-const */\nimport { createHash } from \"crypto\";\nimport { RemoteInfo, createSocket } from \"dgram\";\nimport debug from \"debug\";\nimport mergeWith from \"lodash/mergeWith\";\nimport { performance } from \"perf_hooks\";\n\nimport { bufferReader, bufferWriter, randomPort } from \"../../common/src\";\nimport { CipherContext } from \"../../dtls/src/context/cipher\";\nimport { Address } from \"../../ice/src\";\nimport { Direction, Directions } from \"./media/rtpTransceiver\";\nimport { MediaStreamTrack } from \"./media/track\";\nimport { RTCIceServer } from \"./peerConnection\";\nconst now = require(\"nano-time\");\n\nconst log = debug(\"werift:packages/webrtc/src/utils.ts\");\n\nexport function fingerprint(file: Buffer, hashName: string) {\n const upper = (s: string) => s.toUpperCase();\n const colon = (s: any) => s.match(/(.{2})/g).join(\":\");\n\n const hash = createHash(hashName).update(file).digest(\"hex\");\n\n return colon(upper(hash));\n}\n\nexport function isDtls(buf: Buffer) {\n const firstByte = buf[0];\n return firstByte > 19 && firstByte < 64;\n}\n\nexport function reverseSimulcastDirection(dir: \"recv\" | \"send\") {\n if (dir === \"recv\") return \"send\";\n return \"recv\";\n}\n\nexport const andDirection = (a: Direction, b: Direction) =>\n Directions[Directions.indexOf(a) & Directions.indexOf(b)];\n\nexport function reverseDirection(dir: Direction): Direction {\n if (dir === \"sendonly\") return \"recvonly\";\n if (dir === \"recvonly\") return \"sendonly\";\n return dir;\n}\n\nexport const microTime = () => now.micro() as number;\n\nexport const milliTime = () => new Date().getTime();\n\nexport const timestampSeconds = () => Date.now() / 1000;\n\n/**https://datatracker.ietf.org/doc/html/rfc3550#section-4 */\nexport const ntpTime = () => {\n const now = performance.timeOrigin + performance.now() - Date.UTC(1900, 0, 1);\n\n const seconds = now / 1000;\n const [sec, msec] = seconds.toString().split(\".\").map(Number);\n\n const buf = bufferWriter([4, 4], [sec, msec]);\n\n return buf.readBigUInt64BE();\n};\n\n/**\n * https://datatracker.ietf.org/doc/html/rfc3550#section-4\n * @param ntp\n * @returns 32bit\n */\nexport const compactNtp = (ntp: bigint) => {\n const buf = bufferWriter([8], [ntp]);\n const [, sec, msec] = bufferReader(buf, [2, 2, 2, 2]);\n return bufferWriter([2, 2], [sec, msec]).readUInt32BE();\n};\n\nexport function parseIceServers(iceServers: RTCIceServer[]) {\n const url2Address = (url?: string) => {\n if (!url) return;\n const [address, port] = url.split(\":\");\n return [address, parseInt(port)] as Address;\n };\n\n const stunServer = url2Address(\n iceServers.find(({ urls }) => urls.includes(\"stun:\"))?.urls.slice(5),\n );\n const turnServer = url2Address(\n iceServers.find(({ urls }) => urls.includes(\"turn:\"))?.urls.slice(5),\n );\n const { credential, username } =\n iceServers.find(({ urls }) => urls.includes(\"turn:\")) || {};\n\n const options = {\n stunServer,\n turnServer,\n turnUsername: username,\n turnPassword: credential,\n };\n log(\"iceOptions\", options);\n return options;\n}\n\n/**\n *\n * @param signatureHash\n * @param namedCurveAlgorithm necessary when use ecdsa\n */\nexport const createSelfSignedCertificate =\n CipherContext.createSelfSignedCertificateWithKey;\n\nexport class MediaStreamTrackFactory {\n static async rtpSource({\n port,\n kind,\n }: {\n port?: number;\n kind: \"audio\" | \"video\";\n }) {\n port ??= await randomPort();\n const track = new MediaStreamTrack({ kind });\n\n const udp = createSocket(\"udp4\");\n udp.bind(port);\n const onMessage = (msg: Buffer, rinfo: RemoteInfo) => {\n track.writeRtp(msg);\n };\n udp.addListener(\"message\", onMessage);\n\n const dispose = () => {\n udp.removeListener(\"message\", onMessage);\n udp.close();\n };\n\n return [track, port, dispose] as const;\n }\n}\n\nexport const deepMerge = <T>(dst: T, src: T) =>\n mergeWith(dst, src, (obj, src) => {\n if (!(src == undefined)) {\n return src;\n }\n return obj;\n });\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable prefer-const */\nimport { createHash } from \"crypto\";\nimport { RemoteInfo, createSocket } from \"dgram\";\nimport debug from \"debug\";\nimport mergeWith from \"lodash/mergeWith\";\nimport { performance } from \"perf_hooks\";\n\nimport { bufferReader, bufferWriter, randomPort } from \"../../common/src\";\nimport { CipherContext } from \"../../dtls/src/context/cipher\";\nimport { Address } from \"../../ice/src\";\nimport { Direction, Directions } from \"./media/rtpTransceiver\";\nimport { MediaStreamTrack } from \"./media/track\";\nimport { RTCIceServer } from \"./peerConnection\";\nconst now = require(\"nano-time\");\n\nconst log = debug(\"werift:packages/webrtc/src/utils.ts\");\n\nexport function fingerprint(file: Buffer, hashName: string) {\n const upper = (s: string) => s.toUpperCase();\n const colon = (s: any) => s.match(/(.{2})/g).join(\":\");\n\n const hash = createHash(hashName).update(file).digest(\"hex\");\n\n return colon(upper(hash));\n}\n\nexport function isDtls(buf: Buffer) {\n const firstByte = buf[0];\n return firstByte > 19 && firstByte < 64;\n}\n\nexport function reverseSimulcastDirection(dir: \"recv\" | \"send\") {\n if (dir === \"recv\") return \"send\";\n return \"recv\";\n}\n\nexport const andDirection = (a: Direction, b: Direction) =>\n Directions[Directions.indexOf(a) & Directions.indexOf(b)];\n\nexport function reverseDirection(dir: Direction): Direction {\n if (dir === \"sendonly\") return \"recvonly\";\n if (dir === \"recvonly\") return \"sendonly\";\n return dir;\n}\n\nexport const microTime = () => now.micro() as number;\n\nexport const milliTime = () => new Date().getTime();\n\nexport const timestampSeconds = () => Date.now() / 1000;\n\n/**https://datatracker.ietf.org/doc/html/rfc3550#section-4 */\nexport const ntpTime = () => {\n const now = performance.timeOrigin + performance.now() - Date.UTC(1900, 0, 1);\n\n const seconds = now / 1000;\n const [sec, msec] = seconds.toString().split(\".\").map(Number);\n\n const buf = bufferWriter([4, 4], [sec, msec]);\n\n return buf.readBigUInt64BE();\n};\n\n/**\n * https://datatracker.ietf.org/doc/html/rfc3550#section-4\n * @param ntp\n * @returns 32bit\n */\nexport const compactNtp = (ntp: bigint) => {\n const buf = bufferWriter([8], [ntp]);\n const [, sec, msec] = bufferReader(buf, [2, 2, 2, 2]);\n return bufferWriter([2, 2], [sec, msec]).readUInt32BE();\n};\n\nexport function parseIceServers(iceServers: RTCIceServer[]) {\n const url2Address = (url?: string) => {\n if (!url) return;\n const [address, port] = url.split(\":\");\n return [address, parseInt(port)] as Address;\n };\n\n const stunServer = url2Address(\n iceServers.find(({ urls }) => urls.includes(\"stun:\"))?.urls.slice(5),\n );\n const turnServer = url2Address(\n iceServers.find(({ urls }) => urls.includes(\"turn:\"))?.urls.slice(5),\n );\n const { credential, username } =\n iceServers.find(({ urls }) => urls.includes(\"turn:\")) || {};\n\n const options = {\n stunServer,\n turnServer,\n turnUsername: username,\n turnPassword: credential,\n };\n log(\"iceOptions\", options);\n return options;\n}\n\n/**\n *\n * @param signatureHash\n * @param namedCurveAlgorithm necessary when use ecdsa\n */\nexport const createSelfSignedCertificate =\n CipherContext.createSelfSignedCertificateWithKey;\n\nexport class MediaStreamTrackFactory {\n static async rtpSource({\n port,\n kind,\n cb,\n }: {\n port?: number;\n kind: \"audio\" | \"video\";\n cb?: (buf: Buffer) => Buffer;\n }) {\n port ??= await randomPort();\n const track = new MediaStreamTrack({ kind });\n\n const udp = createSocket(\"udp4\");\n udp.bind(port);\n const onMessage = (msg: Buffer) => {\n if (cb) {\n msg = cb(msg);\n }\n track.writeRtp(msg);\n };\n udp.addListener(\"message\", onMessage);\n\n const dispose = () => {\n udp.removeListener(\"message\", onMessage);\n udp.close();\n };\n\n return [track, port, dispose] as const;\n }\n}\n\nexport const deepMerge = <T>(dst: T, src: T) =>\n mergeWith(dst, src, (obj, src) => {\n if (!(src == undefined)) {\n return src;\n }\n return obj;\n });\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "werift",
3
- "version": "0.19.3",
3
+ "version": "0.19.4",
4
4
  "description": "WebRTC Implementation for TypeScript (Node.js)",
5
5
  "keywords": ["WebRTC", "node.js"],
6
6
  "homepage": "https://github.com/shinyoshiaki/werift-webrtc",
@@ -49,6 +49,7 @@ export class MediaStreamTrack extends EventTarget {
49
49
  this.stopped = true;
50
50
  this.muted = true;
51
51
  this.onReceiveRtp.complete();
52
+ this.emit("ended");
52
53
  };
53
54
 
54
55
  writeRtp = (rtp: RtpPacket | Buffer) => {
@@ -70,8 +71,13 @@ export class MediaStream {
70
71
  id!: string;
71
72
  tracks: MediaStreamTrack[] = [];
72
73
 
73
- constructor(props: Partial<MediaStream> & Pick<MediaStream, "id">) {
74
- Object.assign(this, props);
74
+ constructor(props: Partial<MediaStream> | MediaStreamTrack[]) {
75
+ if (Array.isArray(props)) {
76
+ this.tracks = props;
77
+ } else {
78
+ Object.assign(this, props);
79
+ }
80
+ this.id ??= v4();
75
81
  }
76
82
 
77
83
  addTrack(track: MediaStreamTrack) {
@@ -82,4 +88,12 @@ export class MediaStream {
82
88
  getTracks() {
83
89
  return this.tracks;
84
90
  }
91
+
92
+ getAudioTracks() {
93
+ return this.tracks.filter((track) => track.kind === "audio");
94
+ }
95
+
96
+ getVideoTracks() {
97
+ return this.tracks.filter((track) => track.kind === "video");
98
+ }
85
99
  }
@@ -1,2 +1,3 @@
1
1
  export * from "./recorder";
2
2
  export * from "./userMedia";
3
+ export * from "./navigator";
@@ -0,0 +1,116 @@
1
+ import { randomBytes } from "crypto";
2
+ import { jspack } from "@shinyoshiaki/jspack";
3
+ import { MediaStream, MediaStreamTrack } from "../media/track";
4
+
5
+ export class Navigator {
6
+ mediaDevices: MediaDevices;
7
+
8
+ constructor(props: ConstructorParameters<typeof MediaDevices>[0] = {}) {
9
+ this.mediaDevices = new MediaDevices(props);
10
+ }
11
+ }
12
+
13
+ export class MediaDevices extends EventTarget {
14
+ video?: MediaStreamTrack;
15
+ audio?: MediaStreamTrack;
16
+
17
+ constructor(props: { video?: MediaStreamTrack; audio?: MediaStreamTrack }) {
18
+ super();
19
+ this.video = props.video;
20
+ this.audio = props.audio;
21
+ }
22
+
23
+ readonly getUserMedia = async (
24
+ constraints: MediaStreamConstraints,
25
+ ): Promise<MediaStream> => {
26
+ const video = constraints.video
27
+ ? new MediaStreamTrack({ kind: "video" })
28
+ : undefined;
29
+ if (video) {
30
+ this.video?.onReceiveRtp.subscribe((rtp) => {
31
+ const cloned = rtp.clone();
32
+ cloned.header.ssrc = jspack.Unpack("!L", randomBytes(4))[0];
33
+ video.onReceiveRtp.execute(cloned);
34
+ });
35
+ }
36
+ const audio = constraints.audio
37
+ ? new MediaStreamTrack({ kind: "audio" })
38
+ : undefined;
39
+ if (audio) {
40
+ this.audio?.onReceiveRtp.subscribe((rtp) => {
41
+ const cloned = rtp.clone();
42
+ cloned.header.ssrc = jspack.Unpack("!L", randomBytes(4))[0];
43
+ audio.onReceiveRtp.execute(cloned);
44
+ });
45
+ }
46
+
47
+ if (constraints.video && constraints.audio) {
48
+ return new MediaStream([video!, audio!]);
49
+ } else if (constraints.audio) {
50
+ return new MediaStream([audio!]);
51
+ } else if (constraints.video) {
52
+ return new MediaStream([video!]);
53
+ }
54
+
55
+ throw new Error("Not implemented");
56
+ };
57
+
58
+ readonly getDisplayMedia = this.getUserMedia;
59
+ }
60
+
61
+ interface MediaStreamConstraints {
62
+ audio?: boolean | MediaTrackConstraints;
63
+ peerIdentity?: string;
64
+ preferCurrentTab?: boolean;
65
+ video?: boolean | MediaTrackConstraints;
66
+ }
67
+
68
+ interface MediaTrackConstraints extends MediaTrackConstraintSet {
69
+ advanced?: MediaTrackConstraintSet[];
70
+ }
71
+
72
+ interface MediaTrackConstraintSet {
73
+ aspectRatio?: ConstrainDouble;
74
+ autoGainControl?: ConstrainBoolean;
75
+ channelCount?: ConstrainULong;
76
+ deviceId?: ConstrainDOMString;
77
+ displaySurface?: ConstrainDOMString;
78
+ echoCancellation?: ConstrainBoolean;
79
+ facingMode?: ConstrainDOMString;
80
+ frameRate?: ConstrainDouble;
81
+ groupId?: ConstrainDOMString;
82
+ height?: ConstrainULong;
83
+ noiseSuppression?: ConstrainBoolean;
84
+ sampleRate?: ConstrainULong;
85
+ sampleSize?: ConstrainULong;
86
+ width?: ConstrainULong;
87
+ }
88
+
89
+ type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;
90
+ interface ConstrainDOMStringParameters {
91
+ exact?: string | string[];
92
+ ideal?: string | string[];
93
+ }
94
+ type ConstrainBoolean = boolean | ConstrainBooleanParameters;
95
+ interface ConstrainBooleanParameters {
96
+ exact?: boolean;
97
+ ideal?: boolean;
98
+ }
99
+ type ConstrainULong = number | ConstrainULongRange;
100
+ interface ConstrainULongRange extends ULongRange {
101
+ exact?: number;
102
+ ideal?: number;
103
+ }
104
+ interface ULongRange {
105
+ max?: number;
106
+ min?: number;
107
+ }
108
+ type ConstrainDouble = number | ConstrainDoubleRange;
109
+ interface ConstrainDoubleRange extends DoubleRange {
110
+ exact?: number;
111
+ ideal?: number;
112
+ }
113
+ interface DoubleRange {
114
+ max?: number;
115
+ min?: number;
116
+ }
package/src/utils.ts CHANGED
@@ -110,16 +110,21 @@ export class MediaStreamTrackFactory {
110
110
  static async rtpSource({
111
111
  port,
112
112
  kind,
113
+ cb,
113
114
  }: {
114
115
  port?: number;
115
116
  kind: "audio" | "video";
117
+ cb?: (buf: Buffer) => Buffer;
116
118
  }) {
117
119
  port ??= await randomPort();
118
120
  const track = new MediaStreamTrack({ kind });
119
121
 
120
122
  const udp = createSocket("udp4");
121
123
  udp.bind(port);
122
- const onMessage = (msg: Buffer, rinfo: RemoteInfo) => {
124
+ const onMessage = (msg: Buffer) => {
125
+ if (cb) {
126
+ msg = cb(msg);
127
+ }
123
128
  track.writeRtp(msg);
124
129
  };
125
130
  udp.addListener("message", onMessage);