diff --git a/node/.eslintrc.js b/node/.eslintrc.js index 61a42372e6..e541c5acd6 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -183,6 +183,7 @@ const eslintConfig = } ], 'space-in-parens' : [ 2, 'never' ], + 'space-infix-ops' : [ 2, { 'int32Hint': false } ], 'spaced-comment' : [ 2, 'always' ], 'strict' : 2, 'valid-typeof' : 2, diff --git a/node/src/DirectTransport.ts b/node/src/DirectTransport.ts index d5ee0b85fc..99da02ede9 100644 --- a/node/src/DirectTransport.ts +++ b/node/src/DirectTransport.ts @@ -33,6 +33,8 @@ export type DirectTransportOptions /** * Dump Transport. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); diff --git a/node/src/Router.ts b/node/src/Router.ts index 839aa06d0e..edecf0ce4b 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -24,7 +24,7 @@ import { RtpCapabilities, RtpCodecCapability } from './RtpParameters'; import { cryptoSuiteToFbs } from './SrtpParameters'; import { NumSctpStreams } from './SctpParameters'; import { AppData, Either } from './types'; -import { generateUUIDv4 } from './utils'; +import { generateUUIDv4, parseVector, parseStringStringVector, parseStringStringArrayVector } from './utils'; import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer'; import * as FbsAudioLevelObserver from './fbs/audio-level-observer'; import * as FbsRequest from './fbs/request'; @@ -128,6 +128,42 @@ export type PipeToRouterResult = pipeDataProducer?: DataProducer; }; +export type RouterDump = +{ + /** + * The Router id. + */ + id: string; + /** + * Id of Transports. + */ + transportIds: string[]; + /** + * Id of RtpObservers. + */ + rtpObserverIds: string[]; + /** + * Array of Producer id and its respective Consumer ids. + */ + mapProducerIdConsumerIds: { key: string; values: string[] }[]; + /** + * Array of Consumer id and its Producer id. + */ + mapConsumerIdProducerId: {key: string; value: string}[]; + /** + * Array of Producer id and its respective Observer ids. + */ + mapProducerIdObserverIds: {key: string; values: string[]}[]; + /** + * Array of Producer id and its respective DataConsumer ids. + */ + mapDataProducerIdDataConsumerIds: {key: string; values: string[]}[]; + /** + * Array of DataConsumer id and its DataProducer id. + */ + mapDataConsumerIdDataProducerId: {key: string; value: string}[]; +}; + type PipeTransportPair = { [key: string]: PipeTransport; @@ -376,7 +412,7 @@ export class Router /** * Dump Router. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); @@ -393,7 +429,7 @@ export class Router response.body(dump); - return dump.unpack(); + return parseRouterDumpResponse(dump); } /** @@ -1566,3 +1602,19 @@ export class Router } } } + +export function parseRouterDumpResponse( + binary: FbsRouter.DumpResponse +): RouterDump +{ + return { + id : binary.id()!, + transportIds : parseVector(binary, 'transportIds'), + rtpObserverIds : parseVector(binary, 'rtpObserverIds'), + mapProducerIdConsumerIds : parseStringStringArrayVector(binary, 'mapProducerIdConsumerIds'), + mapConsumerIdProducerId : parseStringStringVector(binary, 'mapConsumerIdProducerId'), + mapProducerIdObserverIds : parseStringStringArrayVector(binary, 'mapProducerIdObserverIds'), + mapDataProducerIdDataConsumerIds : parseStringStringArrayVector(binary, 'mapDataProducerIdDataConsumerIds'), + mapDataConsumerIdDataProducerId : parseStringStringVector(binary, 'mapDataConsumerIdDataProducerId') + }; +} diff --git a/node/src/RtpParameters.ts b/node/src/RtpParameters.ts index 532fb014b2..760aaa15c8 100644 --- a/node/src/RtpParameters.ts +++ b/node/src/RtpParameters.ts @@ -396,7 +396,7 @@ export function serializeRtpParameters( const rtcpFeedback: number[] = []; - for (const rtcp of codec.rtcpFeedback?? []) + for (const rtcp of codec.rtcpFeedback ?? []) { const typeOffset = builder.createString(rtcp.type); const rtcpParametersOffset = builder.createString(rtcp.parameter); @@ -575,7 +575,7 @@ export function serializeParameters( if (typeof value === 'boolean') { parameterOffset = FbsParameter.createParameter( - builder, keyOffset, FbsValue.Boolean, value === true ? 1:0 + builder, keyOffset, FbsValue.Boolean, value === true ? 1 : 0 ); } else if (typeof value === 'number') @@ -638,7 +638,7 @@ export function parseParameters(data: any): any { const parameters: any = {}; - for (let i=0; i { // Should not happen. - throw new Error('method not implemented in the subclass'); + throw new Error('method implemented in the subclass'); } /** @@ -610,7 +610,7 @@ export class Transport async getStats(): Promise { // Should not happen. - throw new Error('method not implemented in the subclass'); + throw new Error('method implemented in the subclass'); } /** @@ -622,7 +622,7 @@ export class Transport async connect(params: any): Promise { // Should not happen. - throw new Error('method not implemented in the subclass'); + throw new Error('method implemented in the subclass'); } /** diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index 8e1547a8be..ad45f9e179 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -29,7 +29,7 @@ export type WebRtcServerOptions = export type WebRtcServerListenInfo = TransportListenInfo; export type WebRtcServerEvents = -{ +{ workerclose: []; // Private events. '@close': []; @@ -42,6 +42,34 @@ export type WebRtcServerObserverEvents = webrtctransportunhandled: [WebRtcTransport]; }; +export type WebRtcServerDump = +{ + id: string; + udpSockets: IpPort[]; + tcpServers: IpPort[]; + webRtcTransportIds: string[]; + localIceUsernameFragments: IceUserNameFragment[]; + tupleHashes: TupleHash[]; +}; + +type IpPort = +{ + ip: string; + port: number; +}; + +type IceUserNameFragment = +{ + localIceUsernameFragment: string; + webRtcTransportId: string; +}; + +type TupleHash = +{ + tupleHash: number; + webRtcTransportId: string; +}; + type WebRtcServerInternal = { webRtcServerId: string; @@ -213,7 +241,7 @@ export class WebRtcServer /** * Dump WebRtcServer. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); @@ -248,32 +276,48 @@ export class WebRtcServer } } -// TODO: This function should return WebRtcServerDump TypeScript type but we -// don't have it yet (same for many other dump() methods everywhere). +function parseIpPort(binary: FbsWebRtcServer.IpPort): IpPort +{ + return { + ip : binary.ip()!, + port : binary.port() + }; +} + +function parseIceUserNameFragment(binary: FbsWebRtcServer.IceUserNameFragment): IceUserNameFragment +{ + return { + localIceUsernameFragment : binary.localIceUsernameFragment()!, + webRtcTransportId : binary.webRtcTransportId()! + }; +} + +function parseTupleHash(binary: FbsWebRtcServer.TupleHash): TupleHash +{ + return { + tupleHash : Number(binary.tupleHash()!), + webRtcTransportId : binary.webRtcTransportId()! + }; +} + function parseWebRtcServerDump( data: FbsWebRtcServer.DumpResponse -): any +): WebRtcServerDump { return { - id : data.id(), + id : data.id()!, udpSockets : utils.parseVector( - data, 'udpSockets', (udpSocket: any) => udpSocket.unpack() + data, 'udpSockets', parseIpPort ), tcpServers : utils.parseVector( - data, 'tcpServers', (tcpServer: any) => tcpServer.unpack() + data, 'tcpServers', parseIpPort ), webRtcTransportIds : utils.parseVector(data, 'webRtcTransportIds'), localIceUsernameFragments : utils.parseVector( - data, 'localIceUsernameFragments', (localIceUsernameFragment: any) => localIceUsernameFragment.unpack() + data, 'localIceUsernameFragments', parseIceUserNameFragment ), tupleHashes : utils.parseVector( - data, 'tupleHashes', (tupleHash: any) => - { - return { - localIceUsernameFragment : Number(tupleHash.localIceUsernameFragment()), - webRtcTransportId : tupleHash.webRtcTransportId() - }; - } + data, 'tupleHashes', parseTupleHash ) }; } diff --git a/node/src/WebRtcTransport.ts b/node/src/WebRtcTransport.ts index 9ef9b49b57..96b5165035 100644 --- a/node/src/WebRtcTransport.ts +++ b/node/src/WebRtcTransport.ts @@ -864,7 +864,7 @@ function parseDtlsParameters(binary: FbsWebRtcTransport.DtlsParameters): DtlsPar { const fingerprints: DtlsFingerprint[] = []; - for (let i=0; i /** * Dump Worker. */ - async dump(): Promise + async dump(): Promise { logger.debug('dump()'); @@ -595,7 +595,7 @@ export class Worker response.body(dump); - return dump.unpack(); + return parseWorkerDumpResponse(dump); } /** @@ -807,3 +807,19 @@ export class Worker this.#observer.safeEmit('close'); } } + +export function parseWorkerDumpResponse( + binary: FbsWorker.DumpResponse +): WorkerDump +{ + return { + pid : binary.pid()!, + webRtcServerIds : parseVector(binary, 'webRtcServerIds'), + routerIds : parseVector(binary, 'routerIds'), + channelMessageHandlers : + { + channelRequestHandlers : parseVector(binary.channelMessageHandlers()!, 'channelRequestHandlers'), + channelNotificationHandlers : parseVector(binary.channelMessageHandlers()!, 'channelNotificationHandlers') + } + }; +} diff --git a/node/src/ortc.ts b/node/src/ortc.ts index ba8d5f772a..dad1cf9c1b 100644 --- a/node/src/ortc.ts +++ b/node/src/ortc.ts @@ -1169,7 +1169,7 @@ export function getConsumerRtpParameters( } // Must sanitize the list of matched codecs by removing useless RTX codecs. - for (let idx = consumerParams.codecs.length -1; idx >= 0; --idx) + for (let idx = consumerParams.codecs.length - 1; idx >= 0; --idx) { const codec = consumerParams.codecs[idx]; diff --git a/node/src/tests/test-Consumer.ts b/node/src/tests/test-Consumer.ts index 642db30836..3723019460 100644 --- a/node/src/tests/test-Consumer.ts +++ b/node/src/tests/test-Consumer.ts @@ -1009,27 +1009,27 @@ test('consumer.close() succeeds', async () => expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); - let dump = await router.dump(); + const routerDump = await router.dump(); - expect(dump.mapProducerIdConsumerIds) + expect(routerDump.mapProducerIdConsumerIds) .toEqual(expect.arrayContaining([ { key: audioProducer.id, values: [ ] } ])); - expect(dump.mapConsumerIdProducerId) + expect(routerDump.mapConsumerIdProducerId) .toEqual(expect.arrayContaining([ { key: videoConsumer.id, value: videoProducer.id } ])); - expect(dump.mapConsumerIdProducerId) + expect(routerDump.mapConsumerIdProducerId) .toEqual(expect.arrayContaining([ { key: videoPipeConsumer.id, value: videoProducer.id } ])); - dump = await transport2.dump(); + const transportDump = await transport2.dump(); - dump.consumerIds = dump.consumerIds.sort(); + transportDump.consumerIds = transportDump.consumerIds.sort(); - expect(dump) + expect(transportDump) .toMatchObject( { id : transport2.id, diff --git a/node/src/utils.ts b/node/src/utils.ts index 72c736e03d..6f9ad900d2 100644 --- a/node/src/utils.ts +++ b/node/src/utils.ts @@ -76,7 +76,7 @@ export function parseVector( { const array: Type[] = []; - for (let i=0; i( return array; } +/** + * Parse flatbuffers vector of StringString into the corresponding array. + */ +export function parseStringStringVector( + binary: any, methodName: string +): { key: string; value: string }[] +{ + const array: { key: string; value: string }[] = []; + + for (let i = 0; i < binary[`${methodName}Length`](); ++i) + { + const kv = binary[methodName](i)!; + + array.push({ key: kv.key(), value: kv.value() }); + } + + return array; +} + /** * Parse flatbuffers vector of StringUint8 into the corresponding array. */ @@ -100,7 +119,7 @@ export function parseStringUint8Vector( { const array: {key: string; value: number}[] = []; - for (let i=0; i