From d9b23c17dbaefa3b4b0fd3faee5f81c289a9629d Mon Sep 17 00:00:00 2001 From: myst Date: Mon, 4 Nov 2024 18:42:29 +0100 Subject: [PATCH] feat(backend): enabled status requests on demand --- .../models/telnet-status-subnogiation.ts | 3 ++ backend/src/features/telnet/telnet-client.ts | 39 +++++++++++++++++++ .../telnet/utils/handle-status-option.ts | 8 ---- 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 backend/src/features/telnet/models/telnet-status-subnogiation.ts diff --git a/backend/src/features/telnet/models/telnet-status-subnogiation.ts b/backend/src/features/telnet/models/telnet-status-subnogiation.ts new file mode 100644 index 0000000..f57e1b9 --- /dev/null +++ b/backend/src/features/telnet/models/telnet-status-subnogiation.ts @@ -0,0 +1,3 @@ +export enum TelnetStatusSubnogiation { + STATUS_SEND = 1, +} diff --git a/backend/src/features/telnet/telnet-client.ts b/backend/src/features/telnet/telnet-client.ts index f17f242..27aabc2 100644 --- a/backend/src/features/telnet/telnet-client.ts +++ b/backend/src/features/telnet/telnet-client.ts @@ -5,6 +5,7 @@ import tls from 'tls'; import { logger } from '../../shared/utils/logger.js'; import { TelnetOptions } from './models/telnet-options.js'; +import { TelnetStatusSubnogiation } from './models/telnet-status-subnogiation.js'; import { TelnetControlSequences } from './types/telnet-control-sequences.js'; import { TelnetNegotiations } from './types/telnet-negotiations.js'; import { TelnetOptionHandler } from './types/telnet-option-handler.js'; @@ -99,12 +100,50 @@ export class TelnetClient extends EventEmitter { this.telnetSocket.on('data', (chunkData: string | Buffer) => { this.emit('data', chunkData); }); + + this.on('negotiationChanged', (negotiation) => { + // Request initial status data after negotiation - we use TTYPE since this is subnegotiated the last + // Todo[myst]: Find a better way to do this but its not that easy, since everything is async + if (negotiation.option === TelnetOptions.TELOPT_TTYPE) { + this.requestStatus(); + } + }); } public sendMessage(data: string): void { this.telnetSocket.write(data); } + public requestStatus(): void { + const buffer = Buffer.from([TelnetStatusSubnogiation.STATUS_SEND]); + + if (!this.connected) { + return; + } + + const clientOption = + this._negotiations[TelnetOptions.TELOPT_STATUS]?.client; + + const serverOption = + this._negotiations[TelnetOptions.TELOPT_STATUS]?.server; + + if ( + clientOption === undefined || + clientOption !== TelnetControlSequences.DO + ) { + return; + } + + if ( + serverOption === undefined || + serverOption !== TelnetControlSequences.WILL + ) { + return; + } + + this.telnetSocket.writeSub(TelnetOptions.TELOPT_STATUS, buffer); + } + public disconnect(): void { logger.info(`[Telnet-Client] Disconnect`); diff --git a/backend/src/features/telnet/utils/handle-status-option.ts b/backend/src/features/telnet/utils/handle-status-option.ts index 206f752..eb2f0eb 100644 --- a/backend/src/features/telnet/utils/handle-status-option.ts +++ b/backend/src/features/telnet/utils/handle-status-option.ts @@ -5,10 +5,6 @@ import { TelnetControlSequences } from '../types/telnet-control-sequences.js'; import { TelnetOptionHandler } from '../types/telnet-option-handler.js'; import { TelnetOptionResult } from '../types/telnet-option-result.js'; -enum TelnetStatusSubnogiation { - STATUS_SEND = 1, -} - const handleStatusDo = (socket: TelnetSocket) => (): TelnetOptionResult => { socket.writeWill(TelnetOptions.TELOPT_STATUS); @@ -24,10 +20,6 @@ const handleStatusDont = (socket: TelnetSocket) => (): TelnetOptionResult => { const handleStatusWill = (socket: TelnetSocket) => (): TelnetOptionResult => { socket.writeDo(TelnetOptions.TELOPT_STATUS); - const buffer = Buffer.from([TelnetStatusSubnogiation.STATUS_SEND]); - - socket.writeSub(TelnetOptions.TELOPT_STATUS, buffer); - return { controlSequence: TelnetControlSequences.DO }; };