Updated terminal for windows, to workaround PseudoConsole process leak

Bryan Roe committed Jan 7, 2020 at 15:05 UTC f350350fc60c6f13ce920b5b983a93def506c518
1 file changed +42 -20
agents/meshcore.js
+42 -20
@@ -1131,48 +1131,67 @@ function createMeshCore(agent) {
1131 };
1132
1133 // Remote terminal using native pipes
1134 - if (process.platform == 'win32') {
1135 - try {
1134 + if (process.platform == 'win32')
1135 + {
1136 + try
1137 + {
1138 if (!require('win-terminal').PowerShellCapable() && (this.httprequest.protocol == 6 || this.httprequest.protocol == 9)) { throw ('PowerShell is not supported on this version of windows'); }
1137 - if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6)) {
1139 + if ((this.httprequest.protocol == 1) || (this.httprequest.protocol == 6))
1140 + {
1141 // Admin Terminal
1139 - if (require('win-virtual-terminal').supported) {
1142 + if (require('win-virtual-terminal').supported)
1143 + {
1144 // ConPTY PseudoTerminal
1141 - this.httprequest._term = require('win-virtual-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25);
1145 + // this.httprequest._term = require('win-virtual-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25);
1146 +
1147 + // The above line is commented out, because there is a bug with ClosePseudoConsole() API, so this is the workaround
1148 + this.httprequest._dispatcher = require('win-dispatcher').dispatch({ modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (this.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
1149 + this.httprequest._dispatcher.ws = this;
1150 + this.httprequest._dispatcher.on('connection', function (c)
1151 + {
1152 + console.log('client connected');
1153 + this.ws._term = c;
1154 + c.pipe(this.ws, { dataTypeSkip: 1 });
1155 + this.ws.pipe(c, { dataTypeSkip: 1 });
1156 + });
1157 }
1143 - else {
1158 + else
1159 + {
1160 // Legacy Terminal
1161 this.httprequest._term = require('win-terminal')[this.httprequest.protocol == 6 ? 'StartPowerShell' : 'Start'](80, 25);
1162 }
1163 }
1148 - else {
1164 + else
1165 + {
1166 // Logged in user
1167 var userPromise = require('user-sessions').enumerateUsers();
1168 userPromise.that = this;
1152 - userPromise.then(function (u) {
1169 + userPromise.then(function (u)
1170 + {
1171 var that = this.that;
1154 - if (u.Active.length > 0) {
1172 + if (u.Active.length > 0)
1173 + {
1174 var username = u.Active[0].Username;
1156 - if (require('win-virtual-terminal').supported) {
1175 + if (require('win-virtual-terminal').supported)
1176 + {
1177 // ConPTY PseudoTerminal
1178 that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-virtual-terminal', script: getJSModule('win-virtual-terminal') }], launch: { module: 'win-virtual-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
1179 }
1160 - else {
1180 + else
1181 + {
1182 // Legacy Terminal
1183 that.httprequest._dispatcher = require('win-dispatcher').dispatch({ user: username, modules: [{ name: 'win-terminal', script: getJSModule('win-terminal') }], launch: { module: 'win-terminal', method: (that.httprequest.protocol == 9 ? 'StartPowerShell' : 'Start'), args: [80, 25] } });
1184 }
1185 that.httprequest._dispatcher.ws = that;
1165 - that.httprequest._dispatcher.on('connection', function (c) {
1186 + that.httprequest._dispatcher.on('connection', function (c)
1187 + {
1188 console.log('client connected');
1189 this.ws._term = c;
1190 c.pipe(this.ws, { dataTypeSkip: 1 });
1169 - this.ws.pipe(c, { dataTypeSkip: 1, end: false });
1170 - this.ws.prependListener('end', function () {
1171 - if (this.httprequest._term) { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); }
1172 - });
1191 + this.ws.pipe(c, { dataTypeSkip: 1 });
1192 });
1193 }
1175 - });
1194 + });
1195 }
1196 } catch (e) {
1197 MeshServerLog('Failed to start remote terminal session, ' + e.toString() + ' (' + this.httprequest.remoteaddr + ')', this.httprequest);
@@ -1180,14 +1199,17 @@ function createMeshCore(agent) {
1199 this.end();
1200 return;
1201 }
1183 - if (!this.httprequest._dispatcher) {
1202 + if (!this.httprequest._dispatcher)
1203 + {
1204 this.httprequest._term.pipe(this, { dataTypeSkip: 1 });
1205 this.pipe(this.httprequest._term, { dataTypeSkip: 1, end: false });
1206 this.prependListener('end', function () { this.httprequest._term.end(function () { console.log("Terminal was closed"); }); });
1207 }
1208 }
1189 - else {
1190 - try {
1209 + else
1210 + {
1211 + try
1212 + {
1213 var bash = fs.existsSync('/bin/bash') ? '/bin/bash' : false;
1214 var sh = fs.existsSync('/bin/sh') ? '/bin/sh' : false;
1215 var script = fs.existsSync('/usr/bin/script') ? '/usr/bin/script' : false;