From 5053743b1bd13de9157ee11af1baf82fbab2d591 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Tue, 13 Jul 2021 19:27:02 +0200 Subject: [PATCH] fixed dynamic port forward listener not getting cleaned up - fixes #4200 --- tabby-core/src/services/config.service.ts | 16 +++++++-------- tabby-ssh/src/api.ts | 20 +++++++++---------- .../sshPortForwardingConfig.component.pug | 10 ++++++---- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tabby-core/src/services/config.service.ts b/tabby-core/src/services/config.service.ts index 5ab8b620..e0883cb8 100644 --- a/tabby-core/src/services/config.service.ts +++ b/tabby-core/src/services/config.service.ts @@ -21,7 +21,7 @@ function isStructuralMember (v) { } function isNonStructuralObjectMember (v): boolean { - return v instanceof Object && !(v instanceof Array) && v.__nonStructural + return v instanceof Object && (v instanceof Array || v.__nonStructural) } /** @hidden */ @@ -62,18 +62,18 @@ export class ConfigProxy { if (real[key] !== undefined) { return real[key] } else { + if (isNonStructuralObjectMember(defaults[key])) { + // The object might be modified outside + real[key] = this.__getDefault(key) + delete real[key].__nonStructural + return real[key] + } return this.__getDefault(key) } } this.__getDefault = (key: string) => { // eslint-disable-line @typescript-eslint/unbound-method - if (isNonStructuralObjectMember(defaults[key])) { - real[key] = { ...defaults[key] } - delete real[key].__nonStructural - return real[key] - } else { - return deepClone(defaults[key]) - } + return deepClone(defaults[key]) } this.__setValue = (key: string, value: any) => { // eslint-disable-line @typescript-eslint/unbound-method diff --git a/tabby-ssh/src/api.ts b/tabby-ssh/src/api.ts index 3feb1181..dda3243c 100644 --- a/tabby-ssh/src/api.ts +++ b/tabby-ssh/src/api.ts @@ -74,11 +74,11 @@ export class ForwardedPort implements ForwardedPortConfig { targetAddress: string targetPort: number - private listener: Server + private listener: Server|null = null async startLocalListener (callback: (accept: () => Socket, reject: () => void, sourceAddress: string|null, sourcePort: number|null, targetAddress: string, targetPort: number) => void): Promise { if (this.type === PortForwardType.Local) { - this.listener = createServer(s => callback( + const listener = this.listener = createServer(s => callback( () => s, () => s.destroy(), s.remoteAddress ?? null, @@ -87,9 +87,9 @@ export class ForwardedPort implements ForwardedPortConfig { this.targetPort, )) return new Promise((resolve, reject) => { - this.listener.listen(this.port, this.host) - this.listener.on('error', reject) - this.listener.on('listening', resolve) + listener.listen(this.port, this.host) + listener.on('error', reject) + listener.on('listening', resolve) }) } else if (this.type === PortForwardType.Dynamic) { return new Promise((resolve, reject) => { @@ -102,10 +102,10 @@ export class ForwardedPort implements ForwardedPortConfig { info.dstAddr, info.dstPort, ) - }) + }) as Server this.listener.on('error', reject) this.listener.listen(this.port, this.host, resolve) - ;(this.listener as any).useAuth(socksv5.auth.None()) + this.listener['useAuth'](socksv5.auth.None()) }) } else { throw new Error('Invalid forward type for a local listener') @@ -113,7 +113,7 @@ export class ForwardedPort implements ForwardedPortConfig { } stopLocalListener (): void { - this.listener.close() + this.listener?.close() } toString (): string { @@ -290,9 +290,7 @@ export class SSHSession extends BaseSession { this.destroyed$.subscribe(() => { for (const port of this.forwardedPorts) { - if (port.type === PortForwardType.Local) { - port.stopLocalListener() - } + port.stopLocalListener() } }) diff --git a/tabby-ssh/src/components/sshPortForwardingConfig.component.pug b/tabby-ssh/src/components/sshPortForwardingConfig.component.pug index d6758d5b..11980cab 100644 --- a/tabby-ssh/src/components/sshPortForwardingConfig.component.pug +++ b/tabby-ssh/src/components/sshPortForwardingConfig.component.pug @@ -1,4 +1,4 @@ -.list-group-light.mb-3 +.list-group.mb-3 .list-group-item.d-flex.align-items-center(*ngFor='let fw of model') strong(*ngIf='fw.type === PortForwardType.Local') Local strong(*ngIf='fw.type === PortForwardType.Remote') Remote @@ -7,15 +7,17 @@ .ml-2 → .ml-2(*ngIf='fw.type !== PortForwardType.Dynamic') {{fw.targetAddress}}:{{fw.targetPort}} .ml-2(*ngIf='fw.type === PortForwardType.Dynamic') SOCKS proxy - button.btn.btn-link.ml-auto((click)='remove(fw)') - i.fas.fa-trash-alt.mr-2 - span Remove + button.btn.btn-link.hover-reveal.ml-auto((click)='remove(fw)') + i.fas.fa-trash-alt .input-group.mb-2(*ngIf='newForward.type === PortForwardType.Dynamic') input.form-control(type='text', [(ngModel)]='newForward.host') .input-group-append .input-group-text : input.form-control(type='number', [(ngModel)]='newForward.port') + .input-group-append + .input-group-text → + .input-group-append.input-group-text(style='flex: 3 1 0') SOCKS proxy .input-group.mb-2(*ngIf='newForward.type !== PortForwardType.Dynamic') input.form-control(type='text', [(ngModel)]='newForward.host')