fixed #8417 - ensure that serial output is chunked at utf8 char boundaries

This commit is contained in:
Eugene Pankov 2023-05-15 22:17:33 +02:00
parent 46a1dd39f0
commit b97c334660
No known key found for this signature in database
GPG key ID: 5896FCBBDD1CF4F4
4 changed files with 30 additions and 9 deletions

View file

@ -3,7 +3,7 @@ import { SerialPortStream } from '@serialport/stream'
import { LogService, NotificationsService } from 'tabby-core' import { LogService, NotificationsService } from 'tabby-core'
import { Subject, Observable } from 'rxjs' import { Subject, Observable } from 'rxjs'
import { Injector, NgZone } from '@angular/core' import { Injector, NgZone } from '@angular/core'
import { BaseSession, BaseTerminalProfile, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal' import { BaseSession, BaseTerminalProfile, LoginScriptsOptions, SessionMiddleware, StreamProcessingOptions, TerminalStreamProcessor, UTF8SplitterMiddleware } from 'tabby-terminal'
import { SerialService } from './services/serial.service' import { SerialService } from './services/serial.service'
export interface SerialProfile extends BaseTerminalProfile { export interface SerialProfile extends BaseTerminalProfile {
@ -64,6 +64,8 @@ export class SerialSession extends BaseSession {
this.middleware.unshift(new SlowFeedMiddleware()) this.middleware.unshift(new SlowFeedMiddleware())
} }
this.middleware.push(new UTF8SplitterMiddleware())
this.setLoginScriptsOptions(profile.options) this.setLoginScriptsOptions(profile.options)
} }

View file

@ -2,8 +2,8 @@ import { Observable, Subject } from 'rxjs'
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
import { ClientChannel } from 'ssh2' import { ClientChannel } from 'ssh2'
import { Injector } from '@angular/core' import { Injector } from '@angular/core'
import { LogService, UTF8Splitter } from 'tabby-core' import { LogService } from 'tabby-core'
import { BaseSession } from 'tabby-terminal' import { BaseSession, UTF8SplitterMiddleware } from 'tabby-terminal'
import { SSHSession } from './ssh' import { SSHSession } from './ssh'
import { SSHProfile } from '../api' import { SSHProfile } from '../api'
@ -13,7 +13,6 @@ export class SSHShellSession extends BaseSession {
get serviceMessage$ (): Observable<string> { return this.serviceMessage } get serviceMessage$ (): Observable<string> { return this.serviceMessage }
private serviceMessage = new Subject<string>() private serviceMessage = new Subject<string>()
private ssh: SSHSession|null private ssh: SSHSession|null
private decoder = new UTF8Splitter()
constructor ( constructor (
injector: Injector, injector: Injector,
@ -24,6 +23,7 @@ export class SSHShellSession extends BaseSession {
this.ssh = ssh this.ssh = ssh
this.setLoginScriptsOptions(this.profile.options) this.setLoginScriptsOptions(this.profile.options)
this.ssh.serviceMessage$.subscribe(m => this.serviceMessage.next(m)) this.ssh.serviceMessage$.subscribe(m => this.serviceMessage.next(m))
this.middleware.push(new UTF8SplitterMiddleware())
} }
async start (): Promise<void> { async start (): Promise<void> {
@ -61,14 +61,10 @@ export class SSHShellSession extends BaseSession {
}) })
this.shell.on('data', data => { this.shell.on('data', data => {
this.emitOutput(this.decoder.write(data)) this.emitOutput(data)
}) })
this.shell.on('end', () => { this.shell.on('end', () => {
const remainder = this.decoder.flush()
if (remainder.length) {
this.emitOutput(remainder)
}
this.logger.info('Shell session ended') this.logger.info('Shell session ended')
if (this.open) { if (this.open) {
this.destroy() this.destroy()

View file

@ -94,6 +94,7 @@ export * from './api/interfaces'
export * from './middleware/streamProcessing' export * from './middleware/streamProcessing'
export * from './middleware/loginScriptProcessing' export * from './middleware/loginScriptProcessing'
export * from './middleware/oscProcessing' export * from './middleware/oscProcessing'
export * from './middleware/utf8Splitter'
export * from './api/middleware' export * from './api/middleware'
export * from './session' export * from './session'
export { LoginScriptsSettingsComponent, StreamProcessingSettingsComponent } export { LoginScriptsSettingsComponent, StreamProcessingSettingsComponent }

View file

@ -0,0 +1,22 @@
import { UTF8Splitter } from 'tabby-core'
import { SessionMiddleware } from '../api/middleware'
/**
* Ensures that the session output is chunked at UTF8 character boundaries.
*/
export class UTF8SplitterMiddleware extends SessionMiddleware {
private decoder = new UTF8Splitter()
feedFromSession (data: Buffer): void {
super.feedFromSession(this.decoder.write(data))
}
close (): void {
const remainder = this.decoder.flush()
if (remainder.length) {
super.feedFromSession(remainder)
}
super.close()
}
}