werift 0.14.0 → 0.14.1-debug
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/binary.d.ts +10 -0
- package/lib/common/src/binary.js +83 -1
- package/lib/common/src/binary.js.map +1 -1
- package/lib/dtls/src/context/cipher.d.ts +1 -2
- package/lib/dtls/src/context/cipher.js +69 -68
- package/lib/dtls/src/context/cipher.js.map +1 -1
- package/lib/ice/src/ice.js +10 -4
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/rtp/src/index.d.ts +12 -9
- package/lib/rtp/src/index.js +12 -18
- package/lib/rtp/src/index.js.map +1 -1
- package/lib/rtp/src/processor/jitterBuffer.js +1 -1
- package/lib/rtp/src/processor/jitterBuffer.js.map +1 -1
- package/lib/rtp/src/rtp/red/encoder.d.ts +18 -0
- package/lib/rtp/src/rtp/red/encoder.js +40 -0
- package/lib/rtp/src/rtp/red/encoder.js.map +1 -0
- package/lib/rtp/src/rtp/{red.d.ts → red/packet.d.ts} +5 -5
- package/lib/rtp/src/rtp/red/packet.js +115 -0
- package/lib/rtp/src/rtp/red/packet.js.map +1 -0
- package/lib/rtp/src/rtp/rtp.d.ts +1 -1
- package/lib/rtp/src/rtp/rtp.js +1 -1
- package/lib/rtp/src/rtp/rtp.js.map +1 -1
- package/lib/webrtc/src/const.d.ts +2 -0
- package/lib/webrtc/src/const.js +3 -1
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/index.d.ts +1 -0
- package/lib/webrtc/src/index.js +1 -0
- package/lib/webrtc/src/index.js.map +1 -1
- package/lib/webrtc/src/media/receiver/red.js +8 -6
- package/lib/webrtc/src/media/receiver/red.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +3 -3
- package/lib/webrtc/src/media/rtpSender.js +4 -4
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +9 -3
- package/lib/webrtc/src/peerConnection.js +11 -2
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/sdp.js +2 -1
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/transport/dtls.d.ts +5 -0
- package/lib/webrtc/src/transport/dtls.js.map +1 -1
- package/lib/webrtc/src/utils.d.ts +10 -0
- package/lib/webrtc/src/utils.js +8 -1
- package/lib/webrtc/src/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/const.ts +6 -0
- package/src/index.ts +1 -0
- package/src/media/receiver/red.ts +11 -12
- package/src/media/rtpSender.ts +6 -6
- package/src/peerConnection.ts +22 -4
- package/src/sdp.ts +2 -1
- package/src/transport/dtls.ts +6 -0
- package/src/utils.ts +9 -0
- package/lib/rtp/src/rtp/red.js +0 -104
- package/lib/rtp/src/rtp/red.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dtls.js","sourceRoot":"","sources":["../../../../src/transport/dtls.ts"],"names":[],"mappings":"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","sourcesContent":["import { Certificate, PrivateKey } from \"@fidm/x509\";\nimport debug from \"debug\";\nimport Event from \"rx.mini\";\nimport { setTimeout } from \"timers/promises\";\n\nimport {\n DtlsClient,\n DtlsServer,\n DtlsSocket,\n Transport,\n} from \"../../../dtls/src\";\nimport {\n HashAlgorithm,\n NamedCurveAlgorithm,\n SignatureAlgorithm,\n SignatureHash,\n} from \"../../../dtls/src/cipher/const\";\nimport { CipherContext } from \"../../../dtls/src/context/cipher\";\nimport { Profile } from \"../../../dtls/src/context/srtp\";\nimport { Connection } from \"../../../ice/src\";\nimport {\n RtcpPacket,\n RtcpPacketConverter,\n RtpHeader,\n RtpPacket,\n SrtcpSession,\n SrtpSession,\n} from \"../../../rtp/src\";\nimport { keyLength, saltLength } from \"../../../rtp/src/srtp/const\";\nimport { RtpRouter } from \"../media/router\";\nimport { fingerprint, isDtls, isMedia, isRtcp } from \"../utils\";\nimport { RTCIceTransport } from \"./ice\";\n\nconst log = debug(\"werift:packages/webrtc/src/transport/dtls.ts\");\n\nexport class RTCDtlsTransport {\n state: DtlsState = \"new\";\n role: DtlsRole = \"auto\";\n srtpStarted = false;\n transportSequenceNumber = 0;\n\n dataReceiver: (buf: Buffer) => void = () => {};\n dtls?: DtlsSocket;\n srtp!: SrtpSession;\n srtcp!: SrtcpSession;\n\n readonly onStateChange = new Event<[DtlsState]>();\n\n private localCertificate?: RTCCertificate = this.certificates[0];\n private remoteParameters?: RTCDtlsParameters;\n\n constructor(\n readonly iceTransport: RTCIceTransport,\n readonly router: RtpRouter,\n readonly certificates: RTCCertificate[],\n private readonly srtpProfiles: Profile[] = []\n ) {}\n\n get localParameters() {\n return new RTCDtlsParameters(\n this.localCertificate ? this.localCertificate.getFingerprints() : [],\n this.role\n );\n }\n\n async setupCertificate() {\n if (!this.localCertificate) {\n const { certPem, keyPem, signatureHash } =\n await CipherContext.createSelfSignedCertificateWithKey(\n {\n signature: SignatureAlgorithm.ecdsa_3,\n hash: HashAlgorithm.sha256_4,\n },\n NamedCurveAlgorithm.secp256r1_23\n );\n this.localCertificate = new RTCCertificate(\n keyPem,\n certPem,\n signatureHash\n );\n }\n }\n\n setRemoteParams(remoteParameters: RTCDtlsParameters) {\n this.remoteParameters = remoteParameters;\n }\n\n async start() {\n if (this.state !== \"new\") throw new Error();\n if (this.remoteParameters?.fingerprints.length === 0) throw new Error();\n\n if (this.role === \"auto\") {\n if (this.iceTransport.role === \"controlling\") {\n this.role = \"server\";\n } else {\n this.role = \"client\";\n }\n }\n\n this.setState(\"connecting\");\n\n await new Promise<void>(async (r) => {\n if (this.role === \"server\") {\n this.dtls = new DtlsServer({\n cert: this.localCertificate?.certPem,\n key: this.localCertificate?.privateKey,\n signatureHash: this.localCertificate?.signatureHash,\n transport: createIceTransport(this.iceTransport.connection),\n srtpProfiles: this.srtpProfiles,\n extendedMasterSecret: true,\n // certificateRequest: true,\n });\n } else {\n this.dtls = new DtlsClient({\n cert: this.localCertificate?.certPem,\n key: this.localCertificate?.privateKey,\n signatureHash: this.localCertificate?.signatureHash,\n transport: createIceTransport(this.iceTransport.connection),\n srtpProfiles: this.srtpProfiles,\n extendedMasterSecret: true,\n });\n }\n this.dtls.onData.subscribe((buf) => {\n this.dataReceiver(buf);\n });\n this.dtls.onClose.once(() => {\n this.setState(\"closed\");\n });\n this.dtls.onConnect.once(r);\n this.dtls.onError.once((error) => {\n this.setState(\"failed\");\n log(\"dtls failed\", error);\n });\n\n if (this.dtls instanceof DtlsClient) {\n await setTimeout(100);\n this.dtls.connect().catch((error) => {\n this.setState(\"failed\");\n log(\"dtls connect failed\", error);\n });\n }\n });\n\n if (this.srtpProfiles.length > 0) {\n this.startSrtp();\n }\n this.setState(\"connected\");\n log(\"dtls connected\");\n }\n\n startSrtp() {\n if (!this.dtls) throw new Error();\n\n if (this.srtpStarted) return;\n this.srtpStarted = true;\n\n const profile = this.dtls.srtp.srtpProfile;\n if (!profile) {\n throw new Error(\"need srtpProfile\");\n }\n log(\"selected SRTP Profile\", profile);\n\n const { localKey, localSalt, remoteKey, remoteSalt } =\n this.dtls.extractSessionKeys(keyLength(profile), saltLength(profile));\n\n const config = {\n keys: {\n localMasterKey: localKey,\n localMasterSalt: localSalt,\n remoteMasterKey: remoteKey,\n remoteMasterSalt: remoteSalt,\n },\n profile,\n };\n this.srtp = new SrtpSession(config);\n this.srtcp = new SrtcpSession(config);\n\n this.iceTransport.connection.onData.subscribe((data) => {\n if (!isMedia(data)) return;\n if (isRtcp(data)) {\n const dec = this.srtcp.decrypt(data);\n const rtcps = RtcpPacketConverter.deSerialize(dec);\n rtcps.forEach((rtcp) => this.router.routeRtcp(rtcp));\n } else {\n const dec = this.srtp.decrypt(data);\n const rtp = RtpPacket.deSerialize(dec);\n this.router.routeRtp(rtp);\n }\n });\n }\n\n readonly sendData = async (data: Buffer) => {\n if (!this.dtls) throw new Error(\"dtls not established\");\n await this.dtls.send(data);\n };\n\n sendRtp(payload: Buffer, header: RtpHeader) {\n const enc = this.srtp.encrypt(payload, header);\n this.iceTransport.connection.send(enc);\n return enc.length;\n }\n\n async sendRtcp(packets: RtcpPacket[]) {\n const payload = Buffer.concat(packets.map((packet) => packet.serialize()));\n const enc = this.srtcp.encrypt(payload);\n try {\n await this.iceTransport.connection.send(enc);\n } catch (error) {\n throw new Error(\"ice\");\n }\n }\n\n private setState(state: DtlsState) {\n if (state != this.state) {\n this.state = state;\n this.onStateChange.execute(state);\n }\n }\n\n async stop() {\n this.setState(\"closed\");\n // todo impl send alert\n }\n}\n\nexport const DtlsStates = [\n \"new\",\n \"connecting\",\n \"connected\",\n \"closed\",\n \"failed\",\n] as const;\nexport type DtlsState = typeof DtlsStates[number];\n\nexport type DtlsRole = \"auto\" | \"server\" | \"client\";\n\nexport class RTCCertificate {\n publicKey: string;\n privateKey: string;\n\n constructor(\n privateKeyPem: string,\n public certPem: string,\n public signatureHash: SignatureHash\n ) {\n const cert = Certificate.fromPEM(Buffer.from(certPem));\n this.publicKey = cert.publicKey.toPEM();\n this.privateKey = PrivateKey.fromPEM(Buffer.from(privateKeyPem)).toPEM();\n }\n\n getFingerprints(): RTCDtlsFingerprint[] {\n return [\n new RTCDtlsFingerprint(\n \"sha-256\",\n fingerprint(\n Certificate.fromPEM(Buffer.from(this.certPem)).raw,\n \"sha256\"\n )\n ),\n ];\n }\n}\n\nexport class RTCDtlsFingerprint {\n constructor(public algorithm: string, public value: string) {}\n}\n\nexport class RTCDtlsParameters {\n constructor(\n public fingerprints: RTCDtlsFingerprint[] = [],\n public role: \"auto\" | \"client\" | \"server\"\n ) {}\n}\n\nclass IceTransport implements Transport {\n constructor(private ice: Connection) {\n ice.onData.subscribe((buf) => {\n if (isDtls(buf)) {\n if (this.onData) this.onData(buf);\n }\n });\n }\n onData?: (buf: Buffer) => void;\n\n readonly send = this.ice.send;\n\n close() {\n this.ice.close();\n }\n}\n\nconst createIceTransport = (ice: Connection) => new IceTransport(ice);\n"]}
|
|
1
|
+
{"version":3,"file":"dtls.js","sourceRoot":"","sources":["../../../../src/transport/dtls.ts"],"names":[],"mappings":"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","sourcesContent":["import { Certificate, PrivateKey } from \"@fidm/x509\";\nimport debug from \"debug\";\nimport Event from \"rx.mini\";\nimport { setTimeout } from \"timers/promises\";\n\nimport {\n DtlsClient,\n DtlsServer,\n DtlsSocket,\n Transport,\n} from \"../../../dtls/src\";\nimport {\n HashAlgorithm,\n NamedCurveAlgorithm,\n SignatureAlgorithm,\n SignatureHash,\n} from \"../../../dtls/src/cipher/const\";\nimport { CipherContext } from \"../../../dtls/src/context/cipher\";\nimport { Profile } from \"../../../dtls/src/context/srtp\";\nimport { Connection } from \"../../../ice/src\";\nimport {\n RtcpPacket,\n RtcpPacketConverter,\n RtpHeader,\n RtpPacket,\n SrtcpSession,\n SrtpSession,\n} from \"../../../rtp/src\";\nimport { keyLength, saltLength } from \"../../../rtp/src/srtp/const\";\nimport { RtpRouter } from \"../media/router\";\nimport { fingerprint, isDtls, isMedia, isRtcp } from \"../utils\";\nimport { RTCIceTransport } from \"./ice\";\n\nconst log = debug(\"werift:packages/webrtc/src/transport/dtls.ts\");\n\nexport class RTCDtlsTransport {\n state: DtlsState = \"new\";\n role: DtlsRole = \"auto\";\n srtpStarted = false;\n transportSequenceNumber = 0;\n\n dataReceiver: (buf: Buffer) => void = () => {};\n dtls?: DtlsSocket;\n srtp!: SrtpSession;\n srtcp!: SrtcpSession;\n\n readonly onStateChange = new Event<[DtlsState]>();\n\n private localCertificate?: RTCCertificate = this.certificates[0];\n private remoteParameters?: RTCDtlsParameters;\n\n constructor(\n readonly iceTransport: RTCIceTransport,\n readonly router: RtpRouter,\n readonly certificates: RTCCertificate[],\n private readonly srtpProfiles: Profile[] = []\n ) {}\n\n get localParameters() {\n return new RTCDtlsParameters(\n this.localCertificate ? this.localCertificate.getFingerprints() : [],\n this.role\n );\n }\n\n async setupCertificate() {\n if (!this.localCertificate) {\n const { certPem, keyPem, signatureHash } =\n await CipherContext.createSelfSignedCertificateWithKey(\n {\n signature: SignatureAlgorithm.ecdsa_3,\n hash: HashAlgorithm.sha256_4,\n },\n NamedCurveAlgorithm.secp256r1_23\n );\n this.localCertificate = new RTCCertificate(\n keyPem,\n certPem,\n signatureHash\n );\n }\n }\n\n setRemoteParams(remoteParameters: RTCDtlsParameters) {\n this.remoteParameters = remoteParameters;\n }\n\n async start() {\n if (this.state !== \"new\") throw new Error();\n if (this.remoteParameters?.fingerprints.length === 0) throw new Error();\n\n if (this.role === \"auto\") {\n if (this.iceTransport.role === \"controlling\") {\n this.role = \"server\";\n } else {\n this.role = \"client\";\n }\n }\n\n this.setState(\"connecting\");\n\n await new Promise<void>(async (r) => {\n if (this.role === \"server\") {\n this.dtls = new DtlsServer({\n cert: this.localCertificate?.certPem,\n key: this.localCertificate?.privateKey,\n signatureHash: this.localCertificate?.signatureHash,\n transport: createIceTransport(this.iceTransport.connection),\n srtpProfiles: this.srtpProfiles,\n extendedMasterSecret: true,\n // certificateRequest: true,\n });\n } else {\n this.dtls = new DtlsClient({\n cert: this.localCertificate?.certPem,\n key: this.localCertificate?.privateKey,\n signatureHash: this.localCertificate?.signatureHash,\n transport: createIceTransport(this.iceTransport.connection),\n srtpProfiles: this.srtpProfiles,\n extendedMasterSecret: true,\n });\n }\n this.dtls.onData.subscribe((buf) => {\n this.dataReceiver(buf);\n });\n this.dtls.onClose.once(() => {\n this.setState(\"closed\");\n });\n this.dtls.onConnect.once(r);\n this.dtls.onError.once((error) => {\n this.setState(\"failed\");\n log(\"dtls failed\", error);\n });\n\n if (this.dtls instanceof DtlsClient) {\n await setTimeout(100);\n this.dtls.connect().catch((error) => {\n this.setState(\"failed\");\n log(\"dtls connect failed\", error);\n });\n }\n });\n\n if (this.srtpProfiles.length > 0) {\n this.startSrtp();\n }\n this.setState(\"connected\");\n log(\"dtls connected\");\n }\n\n startSrtp() {\n if (!this.dtls) throw new Error();\n\n if (this.srtpStarted) return;\n this.srtpStarted = true;\n\n const profile = this.dtls.srtp.srtpProfile;\n if (!profile) {\n throw new Error(\"need srtpProfile\");\n }\n log(\"selected SRTP Profile\", profile);\n\n const { localKey, localSalt, remoteKey, remoteSalt } =\n this.dtls.extractSessionKeys(keyLength(profile), saltLength(profile));\n\n const config = {\n keys: {\n localMasterKey: localKey,\n localMasterSalt: localSalt,\n remoteMasterKey: remoteKey,\n remoteMasterSalt: remoteSalt,\n },\n profile,\n };\n this.srtp = new SrtpSession(config);\n this.srtcp = new SrtcpSession(config);\n\n this.iceTransport.connection.onData.subscribe((data) => {\n if (!isMedia(data)) return;\n if (isRtcp(data)) {\n const dec = this.srtcp.decrypt(data);\n const rtcps = RtcpPacketConverter.deSerialize(dec);\n rtcps.forEach((rtcp) => this.router.routeRtcp(rtcp));\n } else {\n const dec = this.srtp.decrypt(data);\n const rtp = RtpPacket.deSerialize(dec);\n this.router.routeRtp(rtp);\n }\n });\n }\n\n readonly sendData = async (data: Buffer) => {\n if (!this.dtls) throw new Error(\"dtls not established\");\n await this.dtls.send(data);\n };\n\n sendRtp(payload: Buffer, header: RtpHeader) {\n const enc = this.srtp.encrypt(payload, header);\n this.iceTransport.connection.send(enc);\n return enc.length;\n }\n\n async sendRtcp(packets: RtcpPacket[]) {\n const payload = Buffer.concat(packets.map((packet) => packet.serialize()));\n const enc = this.srtcp.encrypt(payload);\n try {\n await this.iceTransport.connection.send(enc);\n } catch (error) {\n throw new Error(\"ice\");\n }\n }\n\n private setState(state: DtlsState) {\n if (state != this.state) {\n this.state = state;\n this.onStateChange.execute(state);\n }\n }\n\n async stop() {\n this.setState(\"closed\");\n // todo impl send alert\n }\n}\n\nexport const DtlsStates = [\n \"new\",\n \"connecting\",\n \"connected\",\n \"closed\",\n \"failed\",\n] as const;\nexport type DtlsState = typeof DtlsStates[number];\n\nexport type DtlsRole = \"auto\" | \"server\" | \"client\";\n\nexport class RTCCertificate {\n publicKey: string;\n privateKey: string;\n\n constructor(\n privateKeyPem: string,\n public certPem: string,\n public signatureHash: SignatureHash\n ) {\n const cert = Certificate.fromPEM(Buffer.from(certPem));\n this.publicKey = cert.publicKey.toPEM();\n this.privateKey = PrivateKey.fromPEM(Buffer.from(privateKeyPem)).toPEM();\n }\n\n getFingerprints(): RTCDtlsFingerprint[] {\n return [\n new RTCDtlsFingerprint(\n \"sha-256\",\n fingerprint(\n Certificate.fromPEM(Buffer.from(this.certPem)).raw,\n \"sha256\"\n )\n ),\n ];\n }\n}\n\nexport type DtlsKeys = {\n certPem: string;\n keyPem: string;\n signatureHash: SignatureHash;\n};\n\nexport class RTCDtlsFingerprint {\n constructor(public algorithm: string, public value: string) {}\n}\n\nexport class RTCDtlsParameters {\n constructor(\n public fingerprints: RTCDtlsFingerprint[] = [],\n public role: \"auto\" | \"client\" | \"server\"\n ) {}\n}\n\nclass IceTransport implements Transport {\n constructor(private ice: Connection) {\n ice.onData.subscribe((buf) => {\n if (isDtls(buf)) {\n if (this.onData) this.onData(buf);\n }\n });\n }\n onData?: (buf: Buffer) => void;\n\n readonly send = this.ice.send;\n\n close() {\n this.ice.close();\n }\n}\n\nconst createIceTransport = (ice: Connection) => new IceTransport(ice);\n"]}
|
|
@@ -27,3 +27,13 @@ export declare class RtpBuilder {
|
|
|
27
27
|
timestamp: number;
|
|
28
28
|
create(payload: Buffer): RtpPacket;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param signatureHash
|
|
33
|
+
* @param namedCurveAlgorithm necessary when use ecdsa
|
|
34
|
+
*/
|
|
35
|
+
export declare const createSelfSignedCertificate: (signatureHash: import(".").SignatureHash, namedCurveAlgorithm?: import(".").NamedCurveAlgorithms | undefined) => Promise<{
|
|
36
|
+
certPem: string;
|
|
37
|
+
keyPem: string;
|
|
38
|
+
signatureHash: import(".").SignatureHash;
|
|
39
|
+
}>;
|
package/lib/webrtc/src/utils.js
CHANGED
|
@@ -3,12 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.RtpBuilder = exports.parseIceServers = exports.compactNtp = exports.ntpTime = exports.milliTime = exports.microTime = exports.reverseDirection = exports.orDirection = exports.andDirection = exports.reverseSimulcastDirection = exports.isRtcp = exports.isMedia = exports.isDtls = exports.fingerprint = void 0;
|
|
6
|
+
exports.createSelfSignedCertificate = exports.RtpBuilder = exports.parseIceServers = exports.compactNtp = exports.ntpTime = exports.milliTime = exports.microTime = exports.reverseDirection = exports.orDirection = exports.andDirection = exports.reverseSimulcastDirection = exports.isRtcp = exports.isMedia = exports.isDtls = exports.fingerprint = void 0;
|
|
7
7
|
/* eslint-disable prefer-const */
|
|
8
8
|
const crypto_1 = require("crypto");
|
|
9
9
|
const debug_1 = __importDefault(require("debug"));
|
|
10
10
|
const perf_hooks_1 = require("perf_hooks");
|
|
11
11
|
const src_1 = require("../../common/src");
|
|
12
|
+
const cipher_1 = require("../../dtls/src/context/cipher");
|
|
12
13
|
const src_2 = require("../../rtp/src");
|
|
13
14
|
const rtpTransceiver_1 = require("./media/rtpTransceiver");
|
|
14
15
|
const now = require("nano-time");
|
|
@@ -113,4 +114,10 @@ class RtpBuilder {
|
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
116
|
exports.RtpBuilder = RtpBuilder;
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param signatureHash
|
|
120
|
+
* @param namedCurveAlgorithm necessary when use ecdsa
|
|
121
|
+
*/
|
|
122
|
+
exports.createSelfSignedCertificate = cipher_1.CipherContext.createSelfSignedCertificateWithKey;
|
|
116
123
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":";;;;;;AAAA,iCAAiC;AACjC,mCAAoC;AACpC,kDAA0B;AAC1B,2CAAyC;AAEzC,0CAO0B;
|
|
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 debug from \"debug\";\nimport { performance } from \"perf_hooks\";\n\nimport {\n bufferReader,\n bufferWriter,\n random16,\n random32,\n uint16Add,\n uint32Add,\n} from \"../../common/src\";\nimport { CipherContext } from \"../../dtls/src/context/cipher\";\nimport { Address } from \"../../ice/src\";\nimport { RtpHeader, RtpPacket } from \"../../rtp/src\";\nimport { Direction, Directions } from \"./media/rtpTransceiver\";\nimport { RTCIceServer } from \"./peerConnection\";\nconst now = require(\"nano-time\");\n\nconst log = debug(\"werift/webrtc/utils\");\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 isMedia(buf: Buffer) {\n const firstByte = buf[0];\n return firstByte > 127 && firstByte < 192;\n}\n\nexport function isRtcp(buf: Buffer) {\n return buf.length >= 2 && buf[1] >= 192 && buf[1] <= 208;\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 const orDirection = (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\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/**https://datatracker.ietf.org/doc/html/rfc3550#section-4 */\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\nexport class RtpBuilder {\n sequenceNumber = random16();\n timestamp = random32();\n\n create(payload: Buffer) {\n this.sequenceNumber = uint16Add(this.sequenceNumber, 1);\n this.timestamp = uint32Add(this.timestamp, 960);\n\n const header = new RtpHeader({\n sequenceNumber: this.sequenceNumber,\n timestamp: Number(this.timestamp),\n payloadType: 96,\n extension: true,\n marker: false,\n padding: false,\n });\n const rtp = new RtpPacket(header, payload);\n return rtp;\n }\n}\n\n/**\n *\n * @param signatureHash\n * @param namedCurveAlgorithm necessary when use ecdsa\n */\nexport const createSelfSignedCertificate =\n CipherContext.createSelfSignedCertificateWithKey;\n"]}
|
package/package.json
CHANGED
package/src/const.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HashAlgorithms,
|
|
3
|
+
SignatureAlgorithm,
|
|
4
|
+
} from "../../dtls/src/cipher/const";
|
|
1
5
|
import {
|
|
2
6
|
ProtectionProfileAeadAes128Gcm,
|
|
3
7
|
ProtectionProfileAes128CmHmacSha1_80,
|
|
@@ -58,3 +62,5 @@ export const SRTP_PROFILE = {
|
|
|
58
62
|
|
|
59
63
|
export const SenderDirections = ["sendonly", "sendrecv"];
|
|
60
64
|
export const NotSenderDirections = ["inactive", "recvonly"];
|
|
65
|
+
|
|
66
|
+
export { HashAlgorithms, SignatureAlgorithm };
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,11 @@ export class RedHandler {
|
|
|
7
7
|
push(red: Red, rtp: RtpPacket) {
|
|
8
8
|
const packets: RtpPacket[] = [];
|
|
9
9
|
|
|
10
|
-
red.
|
|
10
|
+
red.blocks.forEach(({ blockPT, timestampOffset, block }, i) => {
|
|
11
|
+
const sequenceNumber = uint16Add(
|
|
12
|
+
rtp.header.sequenceNumber,
|
|
13
|
+
-(red.blocks.length - (i + 1))
|
|
14
|
+
);
|
|
11
15
|
if (timestampOffset) {
|
|
12
16
|
packets.push(
|
|
13
17
|
new RtpPacket(
|
|
@@ -15,13 +19,10 @@ export class RedHandler {
|
|
|
15
19
|
timestamp: uint32Add(rtp.header.timestamp, -timestampOffset),
|
|
16
20
|
payloadType: blockPT,
|
|
17
21
|
ssrc: rtp.header.ssrc,
|
|
18
|
-
sequenceNumber
|
|
19
|
-
rtp.header.sequenceNumber,
|
|
20
|
-
-(red.payloads.length - (i + 1))
|
|
21
|
-
),
|
|
22
|
+
sequenceNumber,
|
|
22
23
|
marker: true,
|
|
23
24
|
}),
|
|
24
|
-
|
|
25
|
+
block
|
|
25
26
|
)
|
|
26
27
|
);
|
|
27
28
|
} else {
|
|
@@ -31,19 +32,16 @@ export class RedHandler {
|
|
|
31
32
|
timestamp: rtp.header.timestamp,
|
|
32
33
|
payloadType: blockPT,
|
|
33
34
|
ssrc: rtp.header.ssrc,
|
|
34
|
-
sequenceNumber
|
|
35
|
-
rtp.header.sequenceNumber,
|
|
36
|
-
-(red.payloads.length - (i + 1))
|
|
37
|
-
),
|
|
35
|
+
sequenceNumber,
|
|
38
36
|
marker: true,
|
|
39
37
|
}),
|
|
40
|
-
|
|
38
|
+
block
|
|
41
39
|
)
|
|
42
40
|
);
|
|
43
41
|
}
|
|
44
42
|
});
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
const filtered = packets.filter((p) => {
|
|
47
45
|
if (this.sequenceNumbers.includes(p.header.sequenceNumber)) {
|
|
48
46
|
return false;
|
|
49
47
|
} else {
|
|
@@ -54,5 +52,6 @@ export class RedHandler {
|
|
|
54
52
|
return true;
|
|
55
53
|
}
|
|
56
54
|
});
|
|
55
|
+
return filtered;
|
|
57
56
|
}
|
|
58
57
|
}
|
package/src/media/rtpSender.ts
CHANGED
|
@@ -70,7 +70,7 @@ export class RTCRtpSender {
|
|
|
70
70
|
private repairedRtpStreamId?: string;
|
|
71
71
|
private rtxPayloadType?: number;
|
|
72
72
|
private rtxSequenceNumber = random16();
|
|
73
|
-
|
|
73
|
+
redRedundantPayloadType?: number;
|
|
74
74
|
redDistance = 2;
|
|
75
75
|
private headerExtensions: RTCRtpHeaderExtensionParameters[] = [];
|
|
76
76
|
private disposeTrack?: () => void;
|
|
@@ -91,7 +91,7 @@ export class RTCRtpSender {
|
|
|
91
91
|
private timestampOffset = 0;
|
|
92
92
|
private seqOffset = 0;
|
|
93
93
|
private rtpCache: RtpPacket[] = [];
|
|
94
|
-
|
|
94
|
+
codec?: RTCRtpCodecParameters;
|
|
95
95
|
|
|
96
96
|
track?: MediaStreamTrack;
|
|
97
97
|
stopped = false;
|
|
@@ -470,8 +470,8 @@ export function buildRedPacket(
|
|
|
470
470
|
) {
|
|
471
471
|
const red = new Red();
|
|
472
472
|
redundantPackets.forEach((redundant) => {
|
|
473
|
-
red.
|
|
474
|
-
|
|
473
|
+
red.blocks.push({
|
|
474
|
+
block: redundant.payload,
|
|
475
475
|
blockPT,
|
|
476
476
|
timestampOffset: uint32Add(
|
|
477
477
|
presentPacket.header.timestamp,
|
|
@@ -480,8 +480,8 @@ export function buildRedPacket(
|
|
|
480
480
|
});
|
|
481
481
|
});
|
|
482
482
|
|
|
483
|
-
red.
|
|
484
|
-
|
|
483
|
+
red.blocks.push({
|
|
484
|
+
block: presentPacket.payload,
|
|
485
485
|
blockPT,
|
|
486
486
|
});
|
|
487
487
|
return red;
|
package/src/peerConnection.ts
CHANGED
|
@@ -4,7 +4,7 @@ import Event from "rx.mini";
|
|
|
4
4
|
import * as uuid from "uuid";
|
|
5
5
|
|
|
6
6
|
import { Profile } from "../../dtls/src/context/srtp";
|
|
7
|
-
import { codecParametersFromString } from ".";
|
|
7
|
+
import { codecParametersFromString, DtlsKeys } from ".";
|
|
8
8
|
import {
|
|
9
9
|
DISCARD_HOST,
|
|
10
10
|
DISCARD_PORT,
|
|
@@ -97,7 +97,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
97
97
|
|
|
98
98
|
private readonly router = new RtpRouter();
|
|
99
99
|
private readonly certificates: RTCCertificate[] = [];
|
|
100
|
-
|
|
100
|
+
sctpRemotePort?: number;
|
|
101
101
|
private seenMid = new Set<string>();
|
|
102
102
|
private currentLocalDescription?: SessionDescription;
|
|
103
103
|
private currentRemoteDescription?: SessionDescription;
|
|
@@ -112,6 +112,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
112
112
|
iceServers,
|
|
113
113
|
iceTransportPolicy,
|
|
114
114
|
icePortRange,
|
|
115
|
+
dtls,
|
|
115
116
|
}: Partial<PeerConfig> = {}) {
|
|
116
117
|
super();
|
|
117
118
|
|
|
@@ -159,6 +160,15 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
159
160
|
v.id = 1 + i;
|
|
160
161
|
});
|
|
161
162
|
|
|
163
|
+
if (dtls) {
|
|
164
|
+
const { keys } = dtls;
|
|
165
|
+
if (keys) {
|
|
166
|
+
this.certificates.push(
|
|
167
|
+
new RTCCertificate(keys.keyPem, keys.certPem, keys.signatureHash)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
162
172
|
this.iceConnectionStateChange.subscribe((state) => {
|
|
163
173
|
switch (state) {
|
|
164
174
|
case "disconnected":
|
|
@@ -896,7 +906,7 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
896
906
|
return this.transceivers;
|
|
897
907
|
}
|
|
898
908
|
|
|
899
|
-
getSenders() {
|
|
909
|
+
getSenders(): RTCRtpSender[] {
|
|
900
910
|
return this.getTransceivers().map((t) => t.sender);
|
|
901
911
|
}
|
|
902
912
|
|
|
@@ -905,7 +915,11 @@ export class RTCPeerConnection extends EventTarget {
|
|
|
905
915
|
}
|
|
906
916
|
|
|
907
917
|
// todo fix
|
|
908
|
-
addTrack(
|
|
918
|
+
addTrack(
|
|
919
|
+
track: MediaStreamTrack,
|
|
920
|
+
/**todo impl */
|
|
921
|
+
ms?: MediaStream
|
|
922
|
+
) {
|
|
909
923
|
if (this.isClosed) throw new Error("is closed");
|
|
910
924
|
if (this.getSenders().find((sender) => sender.track?.uuid === track.uuid)) {
|
|
911
925
|
throw new Error("track exist");
|
|
@@ -1202,6 +1216,9 @@ export interface PeerConfig {
|
|
|
1202
1216
|
iceServers: RTCIceServer[];
|
|
1203
1217
|
/**Minimum port and Maximum port must not be the same value */
|
|
1204
1218
|
icePortRange: [number, number] | undefined;
|
|
1219
|
+
dtls: Partial<{
|
|
1220
|
+
keys: DtlsKeys;
|
|
1221
|
+
}>;
|
|
1205
1222
|
}
|
|
1206
1223
|
|
|
1207
1224
|
export const findCodecByMimeType = (
|
|
@@ -1252,6 +1269,7 @@ export const defaultPeerConfig: PeerConfig = {
|
|
|
1252
1269
|
iceTransportPolicy: "all",
|
|
1253
1270
|
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
|
|
1254
1271
|
icePortRange: undefined,
|
|
1272
|
+
dtls: {},
|
|
1255
1273
|
};
|
|
1256
1274
|
|
|
1257
1275
|
export interface RTCTrackEvent {
|
package/src/sdp.ts
CHANGED
|
@@ -223,7 +223,8 @@ export class SessionDescription {
|
|
|
223
223
|
case "sctpmap":
|
|
224
224
|
if (!value) throw new Error();
|
|
225
225
|
const [formatId, formatDesc] = divide(value, " ");
|
|
226
|
-
|
|
226
|
+
currentMedia.sctpMap[parseInt(formatId)] = formatDesc;
|
|
227
|
+
currentMedia.sctpPort = parseInt(formatId);
|
|
227
228
|
break;
|
|
228
229
|
case "sctp-port":
|
|
229
230
|
if (!value) throw new Error();
|
package/src/transport/dtls.ts
CHANGED
|
@@ -261,6 +261,12 @@ export class RTCCertificate {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
export type DtlsKeys = {
|
|
265
|
+
certPem: string;
|
|
266
|
+
keyPem: string;
|
|
267
|
+
signatureHash: SignatureHash;
|
|
268
|
+
};
|
|
269
|
+
|
|
264
270
|
export class RTCDtlsFingerprint {
|
|
265
271
|
constructor(public algorithm: string, public value: string) {}
|
|
266
272
|
}
|
package/src/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
uint16Add,
|
|
12
12
|
uint32Add,
|
|
13
13
|
} from "../../common/src";
|
|
14
|
+
import { CipherContext } from "../../dtls/src/context/cipher";
|
|
14
15
|
import { Address } from "../../ice/src";
|
|
15
16
|
import { RtpHeader, RtpPacket } from "../../rtp/src";
|
|
16
17
|
import { Direction, Directions } from "./media/rtpTransceiver";
|
|
@@ -128,3 +129,11 @@ export class RtpBuilder {
|
|
|
128
129
|
return rtp;
|
|
129
130
|
}
|
|
130
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param signatureHash
|
|
136
|
+
* @param namedCurveAlgorithm necessary when use ecdsa
|
|
137
|
+
*/
|
|
138
|
+
export const createSelfSignedCertificate =
|
|
139
|
+
CipherContext.createSelfSignedCertificateWithKey;
|
package/lib/rtp/src/rtp/red.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// rfc2198
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.RedHeader = exports.Red = void 0;
|
|
5
|
-
const src_1 = require("../../../common/src");
|
|
6
|
-
// 0 1 2 3
|
|
7
|
-
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
8
|
-
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
9
|
-
// |F| block PT | timestamp offset | block length |
|
|
10
|
-
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
11
|
-
// 0 1 2 3 4 5 6 7
|
|
12
|
-
// +-+-+-+-+-+-+-+-+
|
|
13
|
-
// |0| Block PT |
|
|
14
|
-
// +-+-+-+-+-+-+-+-+
|
|
15
|
-
class Red {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.payloads = [];
|
|
18
|
-
}
|
|
19
|
-
static deSerialize(buf) {
|
|
20
|
-
const red = new Red();
|
|
21
|
-
let offset = 0;
|
|
22
|
-
[red.header, offset] = RedHeader.deSerialize(buf);
|
|
23
|
-
red.header.payloads.forEach(({ blockLength, timestampOffset, blockPT }) => {
|
|
24
|
-
if (blockLength && timestampOffset) {
|
|
25
|
-
const payload = buf.slice(offset, offset + blockLength);
|
|
26
|
-
red.payloads.push({ bin: payload, blockPT, timestampOffset });
|
|
27
|
-
offset += blockLength;
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
const payload = buf.slice(offset);
|
|
31
|
-
red.payloads.push({ bin: payload, blockPT });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return red;
|
|
35
|
-
}
|
|
36
|
-
serialize() {
|
|
37
|
-
this.header = new RedHeader();
|
|
38
|
-
for (const { timestampOffset, blockPT, bin } of this.payloads) {
|
|
39
|
-
if (timestampOffset) {
|
|
40
|
-
this.header.payloads.push({
|
|
41
|
-
fBit: 1,
|
|
42
|
-
blockPT,
|
|
43
|
-
blockLength: bin.length,
|
|
44
|
-
timestampOffset,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
this.header.payloads.push({ fBit: 0, blockPT });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
let buf = this.header.serialize();
|
|
52
|
-
for (const { bin } of this.payloads) {
|
|
53
|
-
buf = Buffer.concat([buf, bin]);
|
|
54
|
-
}
|
|
55
|
-
return buf;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
exports.Red = Red;
|
|
59
|
-
class RedHeader {
|
|
60
|
-
constructor() {
|
|
61
|
-
this.payloads = [];
|
|
62
|
-
}
|
|
63
|
-
static deSerialize(buf) {
|
|
64
|
-
let offset = 0;
|
|
65
|
-
const header = new RedHeader();
|
|
66
|
-
for (;;) {
|
|
67
|
-
const payload = {};
|
|
68
|
-
header.payloads.push(payload);
|
|
69
|
-
payload.fBit = (0, src_1.getBit)(buf[offset], 0);
|
|
70
|
-
payload.blockPT = (0, src_1.getBit)(buf[offset], 1, 7);
|
|
71
|
-
offset++;
|
|
72
|
-
if (payload.fBit === 0) {
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
payload.timestampOffset =
|
|
76
|
-
(buf[offset] << 6) + ((buf[offset + 1] & 0b11111100) >> 2);
|
|
77
|
-
offset++;
|
|
78
|
-
payload.blockLength = ((buf[offset] & 0b11) << 8) + buf[offset + 1];
|
|
79
|
-
offset += 2;
|
|
80
|
-
}
|
|
81
|
-
return [header, offset];
|
|
82
|
-
}
|
|
83
|
-
serialize() {
|
|
84
|
-
let buf = Buffer.alloc(0);
|
|
85
|
-
for (const payload of this.payloads) {
|
|
86
|
-
if (payload.timestampOffset && payload.blockLength) {
|
|
87
|
-
const a = new src_1.BitWriter2(8)
|
|
88
|
-
.set(payload.fBit)
|
|
89
|
-
.set(payload.blockPT, 7).buffer;
|
|
90
|
-
const b = Buffer.alloc(3);
|
|
91
|
-
b.writeUInt16BE((payload.timestampOffset << 2) | (payload.blockLength >> 8));
|
|
92
|
-
b.writeUInt8(payload.blockLength & 0b11111111, 2);
|
|
93
|
-
buf = Buffer.concat([buf, a, b]);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
const chunk = new src_1.BitWriter2(8).set(0).set(payload.blockPT, 7).buffer;
|
|
97
|
-
buf = Buffer.concat([buf, chunk]);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return buf;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
exports.RedHeader = RedHeader;
|
|
104
|
-
//# sourceMappingURL=red.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"red.js","sourceRoot":"","sources":["../../../../../rtp/src/rtp/red.ts"],"names":[],"mappings":"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","sourcesContent":["// rfc2198\n\nimport { BitWriter2, getBit } from \"../../../common/src\";\n\n// 0 1 2 3\n// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n// |F| block PT | timestamp offset | block length |\n// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n// 0 1 2 3 4 5 6 7\n// +-+-+-+-+-+-+-+-+\n// |0| Block PT |\n// +-+-+-+-+-+-+-+-+\n\nexport class Red {\n header!: RedHeader;\n payloads: {\n bin: Buffer;\n blockPT: number;\n /**14bit */\n timestampOffset?: number;\n }[] = [];\n\n static deSerialize(buf: Buffer) {\n const red = new Red();\n let offset = 0;\n [red.header, offset] = RedHeader.deSerialize(buf);\n\n red.header.payloads.forEach(({ blockLength, timestampOffset, blockPT }) => {\n if (blockLength && timestampOffset) {\n const payload = buf.slice(offset, offset + blockLength);\n red.payloads.push({ bin: payload, blockPT, timestampOffset });\n offset += blockLength;\n } else {\n const payload = buf.slice(offset);\n red.payloads.push({ bin: payload, blockPT });\n }\n });\n\n return red;\n }\n\n serialize() {\n this.header = new RedHeader();\n\n for (const { timestampOffset, blockPT, bin } of this.payloads) {\n if (timestampOffset) {\n this.header.payloads.push({\n fBit: 1,\n blockPT,\n blockLength: bin.length,\n timestampOffset,\n });\n } else {\n this.header.payloads.push({ fBit: 0, blockPT });\n }\n }\n\n let buf = this.header.serialize();\n for (const { bin } of this.payloads) {\n buf = Buffer.concat([buf, bin]);\n }\n\n return buf;\n }\n}\n\nexport class RedHeader {\n payloads: RedHeaderPayload[] = [];\n\n static deSerialize(buf: Buffer) {\n let offset = 0;\n const header = new RedHeader();\n\n for (;;) {\n const payload: RedHeaderPayload = {} as any;\n header.payloads.push(payload);\n payload.fBit = getBit(buf[offset], 0);\n payload.blockPT = getBit(buf[offset], 1, 7);\n offset++;\n\n if (payload.fBit === 0) {\n break;\n }\n\n payload.timestampOffset =\n (buf[offset] << 6) + ((buf[offset + 1] & 0b11111100) >> 2);\n offset++;\n payload.blockLength = ((buf[offset] & 0b11) << 8) + buf[offset + 1];\n offset += 2;\n }\n\n return [header, offset] as const;\n }\n\n serialize() {\n let buf = Buffer.alloc(0);\n for (const payload of this.payloads) {\n if (payload.timestampOffset && payload.blockLength) {\n const a = new BitWriter2(8)\n .set(payload.fBit)\n .set(payload.blockPT, 7).buffer;\n const b = Buffer.alloc(3);\n b.writeUInt16BE(\n (payload.timestampOffset << 2) | (payload.blockLength >> 8)\n );\n b.writeUInt8(payload.blockLength & 0b11111111, 2);\n\n buf = Buffer.concat([buf, a, b]);\n } else {\n const chunk = new BitWriter2(8).set(0).set(payload.blockPT, 7).buffer;\n buf = Buffer.concat([buf, chunk]);\n }\n }\n return buf;\n }\n}\n\ninterface RedHeaderPayload {\n fBit: number;\n blockPT: number;\n /**14bit */\n timestampOffset?: number;\n /**10bit */\n blockLength?: number;\n}\n"]}
|