Skip to content

Commit e0652a2

Browse files
Missing support for remote GDB via intermediate remote server WebFreak001#192
1 parent 7f9deb4 commit e0652a2

File tree

4 files changed

+181
-25
lines changed

4 files changed

+181
-25
lines changed

package-lock.json

Lines changed: 64 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,24 @@
201201
"bootstrap": {
202202
"type": "string",
203203
"description": "Content will be executed on the SSH host before the debugger call."
204+
},
205+
"proxyPort": {
206+
"type": "number",
207+
"description": "Port of the proxy server to connect to; (by default port = display + 6000)",
208+
"default": 22
209+
},
210+
"proxyHost": {
211+
"type": "string",
212+
"description": "Hostname/ip of the proxy server",
213+
"default": "localhost"
214+
},
215+
"proxyUser": {
216+
"type": "string",
217+
"description": "Username to connect as"
218+
},
219+
"proxyPassword": {
220+
"type": "string",
221+
"description": "Plain text password (unsafe; if possible use keyfile instead)"
204222
}
205223
}
206224
}
@@ -338,6 +356,24 @@
338356
"bootstrap": {
339357
"type": "string",
340358
"description": "Content will be executed on the SSH host before the debugger call."
359+
},
360+
"proxyPort": {
361+
"type": "number",
362+
"description": "Port of the proxy server to connect to; (by default port = display + 6000)",
363+
"default": 22
364+
},
365+
"proxyHost": {
366+
"type": "string",
367+
"description": "Hostname/ip of the proxy server",
368+
"default": "localhost"
369+
},
370+
"proxyUser": {
371+
"type": "string",
372+
"description": "Username to connect as"
373+
},
374+
"proxyPassword": {
375+
"type": "string",
376+
"description": "Plain text password (unsafe; if possible use keyfile instead)"
341377
}
342378
}
343379
}
@@ -411,6 +447,27 @@
411447
"valuesFormatting": "parseText"
412448
}
413449
},
450+
{
451+
"label": "GDB: Launch over SSH throw a proxy server",
452+
"description": "Remotely starts the program using gdb",
453+
"body": {
454+
"type": "gdb",
455+
"request": "launch",
456+
"name": "${6:Launch Program (SSH)}",
457+
"target": "${1:./bin/executable}",
458+
"cwd": "^\"\\${workspaceRoot}\"",
459+
"ssh": {
460+
"host": "${2:127.0.0.1}",
461+
"cwd": "${3:/home/remote_user/project/}",
462+
"keyfile": "${4:/home/my_user/.ssh/id_rsa}",
463+
"user": "${5:remote_user}",
464+
"proxyHost": "${7:proxy_host}",
465+
"proxyUser": "${8:proxy_user}",
466+
"proxyPassword": "${9:proxy_password}"
467+
},
468+
"valuesFormatting": "parseText"
469+
}
470+
},
414471
{
415472
"label": "GDB: Launch GUI over SSH with X11 forwarding",
416473
"description": "Remotely starts the program using gdb with X11 forwarding",
@@ -623,6 +680,24 @@
623680
"bootstrap": {
624681
"type": "string",
625682
"description": "Content will be executed on the SSH host before the debugger call."
683+
},
684+
"proxyPort": {
685+
"type": "number",
686+
"description": "Port of the proxy server to connect to; (by default port = display + 6000)",
687+
"default": 22
688+
},
689+
"proxyHost": {
690+
"type": "string",
691+
"description": "Hostname/ip of the proxy server",
692+
"default": "localhost"
693+
},
694+
"proxyUser": {
695+
"type": "string",
696+
"description": "Username to connect as"
697+
},
698+
"proxyPassword": {
699+
"type": "string",
700+
"description": "Plain text password (unsafe; if possible use keyfile instead)"
626701
}
627702
}
628703
}
@@ -953,9 +1028,10 @@
9531028
"postinstall": "node ./node_modules/vscode/bin/install"
9541029
},
9551030
"dependencies": {
1031+
"ssh2": "^0.8.2",
1032+
"ssh2-promise": "^0.1.7",
9561033
"vscode-debugadapter": "^1.16.0",
957-
"vscode-debugprotocol": "^1.16.0",
958-
"ssh2": "^0.8.2"
1034+
"vscode-debugprotocol": "^1.16.0"
9591035
},
9601036
"devDependencies": {
9611037
"@types/mocha": "^5.2.6",

src/backend/backend.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export interface SSHArguments {
4646
x11port: number;
4747
x11host: string;
4848
bootstrap: string;
49+
proxyPort: number;
50+
proxyHost: string;
51+
proxyUser: string;
52+
proxyPassword: string;
4953
}
5054

5155
export interface IBackend {

src/backend/mi2/mi2.ts

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as fs from "fs";
88
import { posix } from "path";
99
import * as nativePath from "path";
1010
const path = posix;
11-
import { Client } from "ssh2";
11+
import ssh2_promise = require('ssh2-promise');
1212

1313
export function escape(str: string) {
1414
return str.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
@@ -94,47 +94,60 @@ export class MI2 extends EventEmitter implements IBackend {
9494
return new Promise((resolve, reject) => {
9595
this.isSSH = true;
9696
this.sshReady = false;
97-
this.sshConn = new Client();
9897

9998
if (separateConsole !== undefined)
10099
this.log("stderr", "WARNING: Output to terminal emulators are not supported over SSH");
101100

102-
if (args.forwardX11) {
103-
this.sshConn.on("x11", (info, accept, reject) => {
104-
const xserversock = new net.Socket();
105-
xserversock.on("error", (err) => {
106-
this.log("stderr", "Could not connect to local X11 server! Did you enable it in your display manager?\n" + err);
107-
});
108-
xserversock.on("connect", () => {
109-
const xclientsock = accept();
110-
xclientsock.pipe(xserversock).pipe(xclientsock);
111-
});
112-
xserversock.connect(args.x11port, args.x11host);
113-
});
114-
}
115-
116101
const connectionArgs: any = {
117102
host: args.host,
118103
port: args.port,
119104
username: args.user
120105
};
121106

107+
const proxyConnection: any = {
108+
host: args.proxyHost,
109+
port: args.proxyPort,
110+
username: args.proxyUser
111+
};
112+
122113
if (args.useAgent) {
123114
connectionArgs.agent = process.env.SSH_AUTH_SOCK;
124115
} else if (args.keyfile) {
125-
if (require("fs").existsSync(args.keyfile))
126-
connectionArgs.privateKey = require("fs").readFileSync(args.keyfile);
127-
else {
116+
if (require("fs").existsSync(args.keyfile)) {
117+
connectionArgs.identity = args.keyfile;
118+
proxyConnection.identity = args.keyfile;
119+
} else {
128120
this.log("stderr", "SSH key file does not exist!");
129121
this.emit("quit");
130122
reject();
131123
return;
132124
}
133125
} else {
134126
connectionArgs.password = args.password;
127+
proxyConnection.password = args.proxyPassword;
135128
}
136129

137-
this.sshConn.on("ready", () => {
130+
if (proxyConnection.host !== undefined) {
131+
this.sshConn = new ssh2_promise([proxyConnection, connectionArgs]);
132+
} else {
133+
this.sshConn = new ssh2_promise(connectionArgs);
134+
}
135+
136+
if (args.forwardX11) {
137+
this.sshConn.on("x11", (info, accept, reject) => {
138+
const xserversock = new net.Socket();
139+
xserversock.on("error", (err) => {
140+
this.log("stderr", "Could not connect to local X11 server! Did you enable it in your display manager?\n" + err);
141+
});
142+
xserversock.on("connect", () => {
143+
const xclientsock = accept();
144+
xclientsock.pipe(xserversock).pipe(xclientsock);
145+
});
146+
xserversock.connect(args.x11port, args.x11host);
147+
});
148+
}
149+
150+
this.sshConn.connect().then(() => {
138151
this.log("stdout", "Running " + this.application + " over ssh...");
139152
const execArgs: any = {};
140153
if (args.forwardX11) {
@@ -172,12 +185,12 @@ export class MI2 extends EventEmitter implements IBackend {
172185
resolve();
173186
}, reject);
174187
});
175-
}).on("error", (err) => {
188+
}).catch("error", (err) => {
176189
this.log("stderr", "Could not run " + this.application + " over ssh!");
177190
this.log("stderr", err.toString());
178191
this.emit("quit");
179192
reject();
180-
}).connect(connectionArgs);
193+
});
181194
});
182195
}
183196

0 commit comments

Comments
 (0)