move createSession() into session

This commit is contained in:
Eugene Pankov 2021-07-04 17:11:21 +02:00
parent 827345d899
commit e17ba8c351
No known key found for this signature in database
GPG Key ID: 5896FCBBDD1CF4F4
8 changed files with 69 additions and 84 deletions

View File

@ -1,7 +1,8 @@
import stripAnsi from 'strip-ansi' import stripAnsi from 'strip-ansi'
import { SerialPort } from 'serialport' import SerialPort from 'serialport'
import { Logger, Profile } from 'tabby-core' import { Logger, LogService, NotificationsService, Profile } from 'tabby-core'
import { Subject, Observable } from 'rxjs' import { Subject, Observable } from 'rxjs'
import { Injector, NgZone } from '@angular/core'
import { BaseSession, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal' import { BaseSession, StreamProcessingOptions, TerminalStreamProcessor } from 'tabby-terminal'
export interface LoginScript { export interface LoginScript {
@ -46,9 +47,16 @@ export class SerialSession 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 streamProcessor: TerminalStreamProcessor private streamProcessor: TerminalStreamProcessor
private zone: NgZone
private notifications: NotificationsService
constructor (public profile: SerialProfile) { constructor (injector: Injector, public profile: SerialProfile) {
super() super()
this.logger = injector.get(LogService).create(`serial-${profile.options.port}`)
this.zone = injector.get(NgZone)
this.notifications = injector.get(NotificationsService)
this.scripts = profile.options.scripts ?? [] this.scripts = profile.options.scripts ?? []
this.streamProcessor = new TerminalStreamProcessor(profile.options) this.streamProcessor = new TerminalStreamProcessor(profile.options)
this.streamProcessor.outputToSession$.subscribe(data => { this.streamProcessor.outputToSession$.subscribe(data => {
@ -102,6 +110,46 @@ export class SerialSession extends BaseSession {
} }
async start (): Promise<void> { async start (): Promise<void> {
this.serial = new SerialPort(this.profile.options.port, {
autoOpen: false,
baudRate: parseInt(this.profile.options.baudrate as any),
dataBits: this.profile.options.databits ?? 8,
stopBits: this.profile.options.stopbits ?? 1,
parity: this.profile.options.parity ?? 'none',
rtscts: this.profile.options.rtscts ?? false,
xon: this.profile.options.xon ?? false,
xoff: this.profile.options.xoff ?? false,
xany: this.profile.options.xany ?? false,
})
let connected = false
await new Promise(async (resolve, reject) => {
this.serial.on('open', () => {
connected = true
this.zone.run(resolve)
})
this.serial.on('error', error => {
this.zone.run(() => {
if (connected) {
this.notifications.error(error.toString())
} else {
reject(error)
}
this.destroy()
})
})
this.serial.on('close', () => {
this.emitServiceMessage('Port closed')
this.destroy()
})
try {
this.serial.open()
} catch (e) {
this.notifications.error(e.message)
reject(e)
}
})
this.open = true this.open = true
this.serial.on('readable', () => { this.serial.on('readable', () => {

View File

@ -5,7 +5,6 @@ import { Component, Injector } from '@angular/core'
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { SelectorService } from 'tabby-core' import { SelectorService } from 'tabby-core'
import { BaseTerminalTabComponent } from 'tabby-terminal' import { BaseTerminalTabComponent } from 'tabby-terminal'
import { SerialService } from '../services/serial.service'
import { SerialSession, BAUD_RATES, SerialProfile } from '../api' import { SerialSession, BAUD_RATES, SerialProfile } from '../api'
/** @hidden */ /** @hidden */
@ -19,7 +18,6 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
profile?: SerialProfile profile?: SerialProfile
session: SerialSession|null = null session: SerialSession|null = null
serialPort: any serialPort: any
private serialService: SerialService
// eslint-disable-next-line @typescript-eslint/no-useless-constructor // eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor ( constructor (
@ -27,7 +25,6 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
private selector: SelectorService, private selector: SelectorService,
) { ) {
super(injector) super(injector)
this.serialService = injector.get(SerialService)
} }
ngOnInit () { ngOnInit () {
@ -67,7 +64,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
return return
} }
const session = this.serialService.createSession(this.profile) const session = new SerialSession(this.injector, this.profile)
this.setSession(session) this.setSession(session)
this.write(`Connecting to `) this.write(`Connecting to `)
@ -81,7 +78,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
spinner.start() spinner.start()
try { try {
this.serialPort = await this.serialService.connectSession(this.session!) await this.session!.start()
spinner.stop(true) spinner.stop(true)
session.emitServiceMessage('Port opened') session.emitServiceMessage('Port opened')
} catch (e) { } catch (e) {
@ -89,7 +86,6 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n') this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
return return
} }
await this.session!.start()
this.session!.resize(this.size.columns, this.size.rows) this.session!.resize(this.size.columns, this.size.rows)
} }

View File

@ -2,6 +2,7 @@ import slugify from 'slugify'
import deepClone from 'clone-deep' import deepClone from 'clone-deep'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { ProfileProvider, NewTabParameters, SelectorService } from 'tabby-core' import { ProfileProvider, NewTabParameters, SelectorService } from 'tabby-core'
import { InputMode, NewlineMode } from 'tabby-terminal'
import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component' import { SerialProfileSettingsComponent } from './components/serialProfileSettings.component'
import { SerialTabComponent } from './components/serialTab.component' import { SerialTabComponent } from './components/serialTab.component'
import { SerialService } from './services/serial.service' import { SerialService } from './services/serial.service'
@ -34,10 +35,10 @@ export class SerialProfilesService extends ProfileProvider {
xany: false, xany: false,
xoff: false, xoff: false,
xon: false, xon: false,
inputMode: null, inputMode: 'local-echo' as InputMode,
outputMode: null, outputMode: null,
inputNewlines: null, inputNewlines: null,
outputNewlines: null, outputNewlines: 'crlf' as NewlineMode,
}, },
isBuiltin: true, isBuiltin: true,
isTemplate: true, isTemplate: true,
@ -50,6 +51,8 @@ export class SerialProfilesService extends ProfileProvider {
isBuiltin: true, isBuiltin: true,
options: { options: {
port: p.name, port: p.name,
inputMode: 'local-echo' as InputMode,
outputNewlines: 'crlf' as NewlineMode,
}, },
})), })),
] ]

View File

@ -1,17 +1,13 @@
import { Injectable, NgZone } from '@angular/core' import { Injectable } from '@angular/core'
import SerialPort from 'serialport' import SerialPort from 'serialport'
import { LogService, NotificationsService, SelectorService, ProfilesService } from 'tabby-core' import { ProfilesService } from 'tabby-core'
import { SerialSession, SerialPortInfo, BAUD_RATES, SerialProfile } from '../api' import { SerialPortInfo, SerialProfile } from '../api'
import { SerialTabComponent } from '../components/serialTab.component' import { SerialTabComponent } from '../components/serialTab.component'
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class SerialService { export class SerialService {
private constructor ( private constructor (
private log: LogService,
private zone: NgZone,
private notifications: NotificationsService,
private profilesService: ProfilesService, private profilesService: ProfilesService,
private selector: SelectorService,
) { } ) { }
async listPorts (): Promise<SerialPortInfo[]> { async listPorts (): Promise<SerialPortInfo[]> {
@ -21,55 +17,6 @@ export class SerialService {
})) }))
} }
createSession (profile: SerialProfile): SerialSession {
const session = new SerialSession(profile)
session.logger = this.log.create(`serial-${profile.options.port}`)
return session
}
async connectSession (session: SerialSession): Promise<SerialPort> {
const serial = new SerialPort(session.profile.options.port, {
autoOpen: false,
baudRate: parseInt(session.profile.options.baudrate as any),
dataBits: session.profile.options.databits,
stopBits: session.profile.options.stopbits,
parity: session.profile.options.parity,
rtscts: session.profile.options.rtscts,
xon: session.profile.options.xon,
xoff: session.profile.options.xoff,
xany: session.profile.options.xany,
})
session.serial = serial
let connected = false
await new Promise(async (resolve, reject) => {
serial.on('open', () => {
connected = true
this.zone.run(resolve)
})
serial.on('error', error => {
this.zone.run(() => {
if (connected) {
this.notifications.error(error.toString())
} else {
reject(error)
}
})
})
serial.on('close', () => {
session.emitServiceMessage('Port closed')
session.destroy()
})
try {
serial.open()
} catch (e) {
this.notifications.error(e.message)
reject(e)
}
})
return serial
}
quickConnect (query: string): Promise<SerialTabComponent|null> { quickConnect (query: string): Promise<SerialTabComponent|null> {
let path = query let path = query
let baudrate = 115200 let baudrate = 115200
@ -95,11 +42,4 @@ export class SerialService {
window.localStorage.lastSerialConnection = JSON.stringify(profile) window.localStorage.lastSerialConnection = JSON.stringify(profile)
return this.profilesService.openNewTabForProfile(profile) as Promise<SerialTabComponent|null> return this.profilesService.openNewTabForProfile(profile) as Promise<SerialTabComponent|null>
} }
async connectFoundPort (port: SerialPortInfo): Promise<SerialTabComponent|null> {
const rate = await this.selector.show('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x,
})))
return this.quickConnect(`${port.name}@${rate}`)
}
} }

View File

@ -10,7 +10,7 @@ import stripAnsi from 'strip-ansi'
import socksv5 from 'socksv5' import socksv5 from 'socksv5'
import { Injector, NgZone } from '@angular/core' import { Injector, NgZone } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, FileProvidersService, HostAppService, Logger, NotificationsService, Platform, PlatformService, wrapPromise, PromptModalComponent, Profile } from 'tabby-core' import { ConfigService, FileProvidersService, HostAppService, Logger, NotificationsService, Platform, PlatformService, wrapPromise, PromptModalComponent, Profile, LogService } from 'tabby-core'
import { BaseSession } from 'tabby-terminal' import { BaseSession } from 'tabby-terminal'
import { Server, Socket, createServer, createConnection } from 'net' import { Server, Socket, createServer, createConnection } from 'net'
import { Client, ClientChannel, SFTPWrapper } from 'ssh2' import { Client, ClientChannel, SFTPWrapper } from 'ssh2'
@ -287,6 +287,8 @@ export class SSHSession extends BaseSession {
public profile: SSHProfile, public profile: SSHProfile,
) { ) {
super() super()
this.logger = injector.get(LogService).create(`ssh-${profile.options.host}-${profile.options.port}`)
this.passwordStorage = injector.get(PasswordStorageService) this.passwordStorage = injector.get(PasswordStorageService)
this.ngbModal = injector.get(NgbModal) this.ngbModal = injector.get(NgbModal)
this.hostApp = injector.get(HostAppService) this.hostApp = injector.get(HostAppService)

View File

@ -90,7 +90,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
throw new Error(`${session.profile.options.host}: jump host "${session.profile.options.jumpHost}" not found in your config`) throw new Error(`${session.profile.options.host}: jump host "${session.profile.options.jumpHost}" not found in your config`)
} }
const jumpSession = this.ssh.createSession(jumpConnection) const jumpSession = new SSHSession(this.injector, jumpConnection)
await this.setupOneSession(jumpSession) await this.setupOneSession(jumpSession)
@ -173,7 +173,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
return return
} }
const session = this.ssh.createSession(this.profile) const session = new SSHSession(this.injector, this.profile)
this.setSession(session) this.setSession(session)
try { try {

View File

@ -32,12 +32,6 @@ export class SSHService {
} }
} }
createSession (profile: SSHProfile): SSHSession {
const session = new SSHSession(this.injector, profile)
session.logger = this.log.create(`ssh-${profile.options.host}-${profile.options.port}`)
return session
}
async connectSession (session: SSHSession): Promise<void> { async connectSession (session: SSHSession): Promise<void> {
const log = (s: any) => session.emitServiceMessage(s) const log = (s: any) => session.emitServiceMessage(s)

View File

@ -87,8 +87,10 @@ export class TerminalStreamProcessor {
} }
resize (): void { resize (): void {
if (this.options.inputMode?.startsWith('readline')) {
this.inputReadlineOutStream.emit('resize') this.inputReadlineOutStream.emit('resize')
} }
}
close (): void { close (): void {
this.inputReadline.close() this.inputReadline.close()