mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-19 18:07:58 +00:00
group various stream processors into middleware
This commit is contained in:
@@ -3,7 +3,7 @@ import colors from 'ansi-colors'
|
||||
import stripAnsi from 'strip-ansi'
|
||||
import { Injector } from '@angular/core'
|
||||
import { Profile, LogService } from 'tabby-core'
|
||||
import { BaseSession, LoginScriptsOptions, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||
import { BaseSession, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
|
||||
|
||||
@@ -41,6 +41,21 @@ enum TelnetOptions {
|
||||
NEW_ENVIRON = 0x27,
|
||||
}
|
||||
|
||||
class UnescapeFFMiddleware extends SessionMiddleware {
|
||||
feedFromSession (data: Buffer): void {
|
||||
while (data.includes(0xff)) {
|
||||
const pos = data.indexOf(0xff)
|
||||
|
||||
this.outputToTerminal.next(data.slice(0, pos))
|
||||
this.outputToTerminal.next(Buffer.from([0xff, 0xff]))
|
||||
|
||||
data = data.slice(pos + 1)
|
||||
}
|
||||
|
||||
this.outputToTerminal.next(data)
|
||||
}
|
||||
}
|
||||
|
||||
export class TelnetSession extends BaseSession {
|
||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||
|
||||
@@ -48,7 +63,6 @@ export class TelnetSession extends BaseSession {
|
||||
private socket: Socket
|
||||
private streamProcessor: TerminalStreamProcessor
|
||||
private telnetProtocol = false
|
||||
private echoEnabled = false
|
||||
private lastWidth = 0
|
||||
private lastHeight = 0
|
||||
private requestedOptions = new Set<number>()
|
||||
@@ -59,33 +73,10 @@ export class TelnetSession extends BaseSession {
|
||||
) {
|
||||
super(injector.get(LogService).create(`telnet-${profile.options.host}-${profile.options.port}`))
|
||||
this.streamProcessor = new TerminalStreamProcessor(profile.options)
|
||||
this.streamProcessor.outputToSession$.subscribe(data => {
|
||||
this.socket.write(this.unescapeFF(data))
|
||||
})
|
||||
this.streamProcessor.outputToTerminal$.subscribe(data => {
|
||||
this.emitOutput(data)
|
||||
})
|
||||
this.middleware.push(this.streamProcessor)
|
||||
this.setLoginScriptsOptions(profile.options)
|
||||
}
|
||||
|
||||
unescapeFF (data: Buffer): Buffer {
|
||||
if (!this.telnetProtocol) {
|
||||
return data
|
||||
}
|
||||
const result: Buffer[] = []
|
||||
while (data.includes(0xff)) {
|
||||
const pos = data.indexOf(0xff)
|
||||
|
||||
result.push(data.slice(0, pos))
|
||||
result.push(Buffer.from([0xff, 0xff]))
|
||||
|
||||
data = data.slice(pos + 1)
|
||||
}
|
||||
|
||||
result.push(data)
|
||||
return Buffer.concat(result)
|
||||
}
|
||||
|
||||
async start (): Promise<void> {
|
||||
this.socket = new Socket()
|
||||
this.emitServiceMessage(`Connecting to ${this.profile.options.host}`)
|
||||
@@ -124,6 +115,7 @@ export class TelnetSession extends BaseSession {
|
||||
onData (data: Buffer): void {
|
||||
if (!this.telnetProtocol && data[0] === TelnetCommands.IAC) {
|
||||
this.telnetProtocol = true
|
||||
this.middleware.push(new UnescapeFFMiddleware())
|
||||
this.requestOption(TelnetCommands.DO, TelnetOptions.SUPPRESS_GO_AHEAD)
|
||||
this.emitTelnet(TelnetCommands.WILL, TelnetOptions.TERMINAL_TYPE)
|
||||
this.emitTelnet(TelnetCommands.WILL, TelnetOptions.NEGO_WINDOW_SIZE)
|
||||
@@ -131,7 +123,7 @@ export class TelnetSession extends BaseSession {
|
||||
if (this.telnetProtocol) {
|
||||
data = this.processTelnetProtocol(data)
|
||||
}
|
||||
this.streamProcessor.feedFromSession(data)
|
||||
this.emitOutput(data)
|
||||
}
|
||||
|
||||
emitTelnet (command: TelnetCommands, option: TelnetOptions): void {
|
||||
@@ -190,7 +182,7 @@ export class TelnetSession extends BaseSession {
|
||||
this.emitTelnet(TelnetCommands.WILL, option)
|
||||
this.emitSize()
|
||||
} else if (option === TelnetOptions.ECHO) {
|
||||
this.echoEnabled = true
|
||||
this.streamProcessor.forceEcho = true
|
||||
this.emitTelnet(TelnetCommands.WILL, option)
|
||||
} else if (option === TelnetOptions.TERMINAL_TYPE) {
|
||||
this.emitTelnet(TelnetCommands.WILL, option)
|
||||
@@ -201,7 +193,7 @@ export class TelnetSession extends BaseSession {
|
||||
}
|
||||
if (command === TelnetCommands.DONT) {
|
||||
if (option === TelnetOptions.ECHO) {
|
||||
this.echoEnabled = false
|
||||
this.streamProcessor.forceEcho = false
|
||||
this.emitTelnet(TelnetCommands.WONT, option)
|
||||
} else {
|
||||
this.logger.debug('(!) Unhandled option')
|
||||
@@ -249,10 +241,7 @@ export class TelnetSession extends BaseSession {
|
||||
}
|
||||
|
||||
write (data: Buffer): void {
|
||||
if (this.echoEnabled) {
|
||||
this.emitOutput(data)
|
||||
}
|
||||
this.streamProcessor.feedFromTerminal(data)
|
||||
this.socket.write(data)
|
||||
}
|
||||
|
||||
kill (_signal?: string): void {
|
||||
|
Reference in New Issue
Block a user