1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var _ = require("lodash")
|
8 | , util = require("util")
|
9 | , VantageUtil = require("./util")
|
10 | , chalk = require("chalk")
|
11 | ; require("native-promise-only")
|
12 | ;
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | function VantageClient(parent) {
|
23 | this.parent = parent;
|
24 |
|
25 |
|
26 |
|
27 | this.sessions = [];
|
28 |
|
29 | return this;
|
30 | }
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | var vantageClient = VantageClient.prototype;
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | exports = module.exports = VantageClient;
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | vantageClient.connect = function(server, port, options, cb) {
|
56 | var self = this;
|
57 |
|
58 | return new Promise(function(resolve, reject) {
|
59 |
|
60 |
|
61 |
|
62 | cb = (_.isFunction(options)) ? options : (cb || function(){});
|
63 | options = (_.isFunction(options)) ? {} : options;
|
64 | options = _.defaults(options, {
|
65 | ssl: false,
|
66 | user: void 0,
|
67 | pass: void 0,
|
68 | pipe: false,
|
69 | sessionId: self.parent.session.id
|
70 | });
|
71 |
|
72 | var method = (options.ssl) ? "https" : "http";
|
73 |
|
74 | var ssn = self.parent.getSessionById(options.sessionId);
|
75 |
|
76 | ssn.log("Connecting to " + server + ":" + port + " using " + method + "...");
|
77 |
|
78 | if (!ssn) {
|
79 | throw new Error("vantageClient.connect was called with an invalid Session ID: " + options.sessionId);
|
80 | }
|
81 |
|
82 | ssn.client = require("socket.io-client")(method + "://" + server + ":" + port, {
|
83 | "force new connection": true,
|
84 | "forceNew": true,
|
85 | "secure": true,
|
86 | "query": "id=" + self.parent.session.id + "&sessionId=" + options.sessionId,
|
87 | "reconnection": true,
|
88 | "reconnectionDelay": 1000,
|
89 | "reconnectionAttempts": 1
|
90 | });
|
91 |
|
92 | ssn.client.on("connect", function() {
|
93 |
|
94 | if (!ssn.client) { return; }
|
95 | self.parent.emit("client_connect", this);
|
96 |
|
97 | ssn.client.on("vantage-banner-downstream", function(data) {
|
98 | self.parent._proxy("vantage-banner-downstream", "downstream", data).then(function(){
|
99 | if (data.banner) {
|
100 | ssn.log(data.banner);
|
101 | }
|
102 | });
|
103 | });
|
104 |
|
105 | ssn.client.on("vantage-keypress-downstream", function(data) {
|
106 | self.parent._proxy("vantage-keypress-downstream", "downstream", data).then(function(){
|
107 | if (data.value !== undefined) {
|
108 | if (_.isArray(data.value)) {
|
109 | self.parent.ui.imprint();
|
110 | ssn.log(data.value);
|
111 | } else {
|
112 | self.parent.ui.redraw(data.value);
|
113 | }
|
114 | }
|
115 | });
|
116 | });
|
117 |
|
118 |
|
119 | ssn.client.on("vantage-command-downstream", function(data) {
|
120 | self.parent._proxy("vantage-command-downstream", "downstream", data).then(function(){
|
121 | if (data.completed === true) {
|
122 | data.data = VantageUtil.fixArgsForApply(data.data);
|
123 | if (self.parent._command) {
|
124 | if (self.parent._command.command !== data.command) {
|
125 | console.log("Downstream command does not match stored comand: ", data.command, " -vs -", self.parent._command.command);
|
126 | }
|
127 | var name = self.parent._command.command;
|
128 | var res = self.parent._command.resolve;
|
129 | var rej = self.parent._command.reject;
|
130 | var cbk = self.parent._command.callback;
|
131 | delete self.parent._command;
|
132 | self.parent._command = void 0;
|
133 | try {
|
134 | self.parent._queueHandler.call(self.parent);
|
135 | } catch(e) {
|
136 | console.log("Error on vantage command downstream: ", e.stack);
|
137 | }
|
138 |
|
139 | if (cbk !== undefined) {
|
140 | self.parent.emit("client_command_executed", { command: name });
|
141 | cbk.apply(null, data.data);
|
142 | } else if (data.error !== undefined && rej !== undefined) {
|
143 | self.parent.emit("client_command_error", { command: name, error: data.error });
|
144 | try {
|
145 | rej(data.error);
|
146 | } catch(e) {
|
147 | console.log("Error calling Promise reject on vantage command downstream: ", e);
|
148 | }
|
149 | } else if (res !== undefined) {
|
150 | self.parent.emit("client_command_executed", { command: name });
|
151 | if (data.error === undefined && _.isArray(data.data) && data.data.length === 2) {
|
152 | data.data.shift();
|
153 | }
|
154 | try {
|
155 | res.apply(null, data.data);
|
156 | } catch(e) {
|
157 | console.log("Error calling Promise resolve on vantage command downstream: ", e);
|
158 | }
|
159 | }
|
160 | }
|
161 | if (!self.parent.ui.midPrompt()) {
|
162 | self.parent._prompt({ sessionId: data.sessionId });
|
163 | }
|
164 | } else {
|
165 | console.log("Vantage command downstream was called with no completed boolean.");
|
166 | console.trace();
|
167 | }
|
168 | });
|
169 | });
|
170 |
|
171 | ssn.client.on("vantage-stdout-downstream", function(data) {
|
172 | self.parent._proxy("vantage-stdout-downstream", "downstream", data).then(function(){
|
173 | var stdout = data.value || "";
|
174 | stdout =
|
175 | (_.isString(stdout) && (util.inspect(stdout.slice(stdout.length - 2, stdout.length).trim() === "\n")))
|
176 | ? stdout.slice(0, stdout.length - 1)
|
177 | : stdout;
|
178 | ssn.log(stdout);
|
179 | });
|
180 | });
|
181 |
|
182 | ssn.client.on("vantage-heartbeat-downstream", function(data){
|
183 | self.parent._proxy("vantage-heartbeat-downstream", "downstream", data).then(function(){
|
184 | if (data.delimiter) {
|
185 | ssn.delimiter(data.delimiter);
|
186 | }
|
187 | self.parent.emit("vantage-heartbeat-downstream");
|
188 | });
|
189 | });
|
190 |
|
191 | ssn.client.on("vantage-mode-delimiter-downstream", function(data){
|
192 | self.parent._proxy("vantage-mode-delimiter-downstream", "downstream", data).then(function(){
|
193 | if (typeof data.value !== "undefined") {
|
194 | ssn.modeDelimiter(data.value);
|
195 | self.parent.emit("vantage-mode-delimiter-downstream");
|
196 | }
|
197 | });
|
198 | });
|
199 |
|
200 | ssn.client.on("vantage-delimiter-downstream", function(data){
|
201 | self.parent._proxy("vantage-delimiter-downstream", "downstream", data).then(function(){
|
202 | if (data.value) {
|
203 | ssn.delimiter(data.value);
|
204 | self.parent.emit("vantage-delimiter-downstream");
|
205 | }
|
206 | });
|
207 | });
|
208 |
|
209 | ssn.client.on("vantage-prompt-downstream", function(data) {
|
210 | self.parent._proxy("vantage-prompt-downstream", "downstream", data).then(function(){
|
211 | data = data || {};
|
212 | data.options = data.options || {};
|
213 |
|
214 |
|
215 | if (self.parent.ui.midPrompt()) {
|
216 | self.parent.ui.pause();
|
217 | }
|
218 | self.parent.ui.setDelimiter(data.options.message || ssn.delimiter);
|
219 | self.parent.ui.prompt(data.options, function(result) {
|
220 |
|
221 | self.parent.ui.setDelimiter(ssn.delimiter);
|
222 |
|
223 |
|
224 | self.parent._send("vantage-prompt-upstream", "upstream", { value: result, sessionId: data.sessionId });
|
225 | });
|
226 | });
|
227 | });
|
228 |
|
229 | ssn.client.on("vantage-close-downstream", function(data){
|
230 | ssn.client.close();
|
231 | if (self.parent._command !== undefined) {
|
232 | var name = self.parent._command.command;
|
233 | var res = self.parent._command.resolve;
|
234 | var cbk = self.parent._command.callback;
|
235 | delete self.parent._command;
|
236 | self.parent._command = void 0;
|
237 | self.parent._queueHandler.call(self.parent);
|
238 | if (name.indexOf("exit") > -1) {
|
239 | if (cbk !== undefined) {
|
240 | cbk(void 0, "Exited successfully.");
|
241 | } else if (res !== undefined) {
|
242 | res("Exited successfully.");
|
243 | }
|
244 | self.parent.emit("client_command_executed", { command: name });
|
245 | }
|
246 |
|
247 | } else {
|
248 | self.parent._send("vantage-command-downstream", "downstream", { completed: true, data: "Exited successfully.", sessionId: data.sessionId, command: "exit" });
|
249 | }
|
250 | });
|
251 |
|
252 | ssn.client.on("vantage-resume-downstream", function(data) {
|
253 | self.parent._proxy("vantage-resume-downstream", "downstream", data).then(function(){
|
254 | self.parent._prompt({ sessionId: data.sessionId });
|
255 | });
|
256 | });
|
257 |
|
258 | ssn.client.on("vantage-ssn-stdout-downstream", function(data) {
|
259 | self.parent._proxy("vantage-ssn-stdout-downstream", "downstream", data).then(function() {
|
260 | var sessn = self.parent.getSessionById(data.sessionId);
|
261 | if (sessn) {
|
262 | sessn.log.apply(sessn, data.value);
|
263 | }
|
264 | });
|
265 | });
|
266 |
|
267 | if (ssn.isLocal() && self.parent.ui.midPrompt()) {
|
268 | self.parent.ui.pause();
|
269 | }
|
270 |
|
271 | ssn.client.on("vantage-auth-downstream", function(data){
|
272 | data = data || {};
|
273 | var error = data.error;
|
274 | var authenticated = data.authenticated;
|
275 | if (authenticated === true) {
|
276 | ssn.user = options.user || "guest";
|
277 | resolve(void 0);
|
278 | cb(void 0);
|
279 | } else {
|
280 | self.parent._send("vantage-close-upstream", "upstream", { sessionId: ssn.id });
|
281 | reject(error || authenticated);
|
282 | cb(true, error || authenticated);
|
283 | }
|
284 | });
|
285 |
|
286 | var authData = {
|
287 | handshake: (ssn.client.io.opts || {}),
|
288 | user: options.user,
|
289 | pass: options.pass,
|
290 | sessionId: ssn.id
|
291 | };
|
292 |
|
293 | self.parent._send("vantage-auth-upstream", "upstream", authData);
|
294 | });
|
295 |
|
296 | function disconnect(data) {
|
297 | self.parent.emit("client_disconnect", data);
|
298 | if (ssn.client) {
|
299 | ssn.client.close();
|
300 | }
|
301 | if (!ssn.isLocal()) {
|
302 | self.parent._send("vantage-heartbeat-downstream", "downstream", {
|
303 | delimiter: self.parent._delimiter,
|
304 | sessionId: ssn.id
|
305 | });
|
306 | } else {
|
307 | ssn.delimiter(self.parent._delimiter);
|
308 | self.parent._prompt({ sessionId: ssn.id });
|
309 | }
|
310 | delete ssn.client;
|
311 | ssn.client = void 0;
|
312 | }
|
313 |
|
314 | ssn.client.on("connect_error", function(err) {
|
315 | self.parent.emit("client_connect_error", err);
|
316 | var sessn = self.parent.getSessionById(options.sessionId);
|
317 | var description =
|
318 | (_.isObject(err)) ? ((err.description === 503) ? "503 Service Unavailable" : err.description)
|
319 | : err;
|
320 | sessn.log(chalk.yellow("Connection Error: ") + description);
|
321 | disconnect(err);
|
322 | reject("Connection Error: " + description);
|
323 | cb("Error connecting: " + description);
|
324 | });
|
325 |
|
326 | ssn.client.on("error", function(err){
|
327 | self.parent.emit("client_error", err);
|
328 | ssn.log(err);
|
329 | disconnect(err);
|
330 | reject("Connection Error: " + err);
|
331 | cb("Error connecting: " + err);
|
332 | });
|
333 |
|
334 | ssn.client.on("disconnect", function(data) {
|
335 | self.parent.emit("client_disconnect", data);
|
336 |
|
337 | if (!ssn.isLocal()) {
|
338 | self.parent._send("vantage-heartbeat-downstream", "downstream", {
|
339 | delimiter: self.parent._delimiter,
|
340 | sessionId: ssn.id
|
341 | });
|
342 | } else {
|
343 | ssn.delimiter(self.parent._delimiter);
|
344 | self.parent._prompt({ sessionId: ssn.id });
|
345 | }
|
346 | delete ssn.client;
|
347 | ssn.client = void 0;
|
348 | });
|
349 | });
|
350 | };
|