Mercurial > hg > rlgwebd
comparison webtty.js @ 86:ad4229cf8321
WebTTY: use the pty.js module.
Convert TermSessions to spawn with the pty.js module instead of piping
everything through ptyhelper.
author | John "Elwin" Edwards <elwin@sdf.org> |
---|---|
date | Sun, 08 Jul 2012 21:20:56 -0700 |
parents | e4773ac5d4d5 |
children | f14e92f6d955 |
comparison
equal
deleted
inserted
replaced
85:4303d94d87a2 | 86:ad4229cf8321 |
---|---|
1 #!/usr/bin/env node | 1 #!/usr/bin/env node |
2 var http = require('http'); | 2 var http = require('http'); |
3 var url = require('url'); | 3 var url = require('url'); |
4 var path = require('path'); | 4 var path = require('path'); |
5 var fs = require('fs'); | 5 var fs = require('fs'); |
6 var child_process = require("child_process"); | 6 var pty = require("/usr/local/lib/node_modules/pty.js"); |
7 | 7 |
8 var serveStaticRoot = "/home/elwin/hk/nodejs/rlg/s/"; | 8 var serveStaticRoot = "/home/elwin/hk/nodejs/rlg/s/"; |
9 var ptyhelp = "/home/elwin/hk/nodejs/rlg/ptyhelper"; | 9 var ptyhelp = "/home/elwin/hk/nodejs/rlg/ptyhelper"; |
10 var sessions = {}; | 10 var sessions = {}; |
11 | 11 |
28 var childenv = {}; | 28 var childenv = {}; |
29 for (var key in process.env) { | 29 for (var key in process.env) { |
30 if (!(key in env_dontuse)) | 30 if (!(key in env_dontuse)) |
31 childenv[key] = process.env[key]; | 31 childenv[key] = process.env[key]; |
32 } | 32 } |
33 childenv["PTYHELPER"] = String(this.h) + "x" + String(this.w); | 33 var spawnopts = {"env": childenv, "cwd": process.env["HOME"], |
34 // Should setsid get set? | 34 "rows": this.h, "cols": this.w}; |
35 var spawnopts = {"env": childenv, "cwd": process.env["HOME"]}; | 35 this.term = pty.spawn("bash", [], spawnopts); |
36 this.child = child_process.spawn(ptyhelp, ["bash"], spawnopts); | |
37 var ss = this; | 36 var ss = this; |
38 /* Eventually we'll need to make sure the sessid isn't in use yet. */ | 37 /* Eventually we'll need to make sure the sessid isn't in use yet. */ |
39 this.sessid = sessid; | 38 this.sessid = sessid; |
40 this.alive = true; | 39 this.alive = true; |
41 this.data = []; // Buffer for the process' output. | 40 this.data = []; // Buffer for the process' output. |
42 this.nsend = 0; // Number to use for the next message sent. | 41 this.nsend = 0; // Number to use for the next message sent. |
43 this.nrecv = 0; // Number expected on the next message received. | 42 this.nrecv = 0; // Number expected on the next message received. |
44 this.msgQ = []; // Queue for messages that arrived out of order. | 43 this.msgQ = []; // Queue for messages that arrived out of order. |
45 this.child.stdout.on("data", function (buf) { | 44 this.term.on("data", function (buf) { |
46 ss.data.push(buf); | 45 ss.data.push(buf); |
47 }); | 46 }); |
48 this.child.stderr.on("data", function (buf) { | 47 this.term.on("exit", function () { |
49 ss.data.push(buf); | |
50 }); | |
51 this.child.on("exit", function (code, signal) { | |
52 ss.exitcode = (code != null ? code : 255); | |
53 ss.alive = false; | 48 ss.alive = false; |
54 /* Wait for all the data to get collected */ | 49 /* Wait for all the data to get collected */ |
55 setTimeout(ss.cleanup, 1000); | 50 setTimeout(ss.cleanup, 1000); |
56 }); | 51 }); |
57 this.write = function (data, n) { | 52 this.write = function (data, n) { |
61 } | 56 } |
62 if (n !== this.nrecv) { | 57 if (n !== this.nrecv) { |
63 console.log("Session " + this.sessid + ": Expected message " + this.nrecv + ", got " + n); | 58 console.log("Session " + this.sessid + ": Expected message " + this.nrecv + ", got " + n); |
64 } | 59 } |
65 this.nrecv = n + 1; | 60 this.nrecv = n + 1; |
66 this.child.stdin.write(data); | 61 this.term.write(data); |
67 }; | 62 }; |
68 this.read = function () { | 63 this.read = function () { |
69 if (this.data.length == 0) | 64 if (this.data.length == 0) |
70 return null; | 65 return null; |
71 var pos = 0; | 66 var pos = 0; |
72 var i = 0; | 67 var i = 0; |
73 for (i = 0; i < this.data.length; i++) | 68 for (i = 0; i < this.data.length; i++) |
74 pos += this.data[i].length; | 69 pos += Buffer.byteLength(this.data[i]); |
75 var nbuf = new Buffer(pos); | 70 var nbuf = new Buffer(pos); |
76 var tptr; | 71 var tptr; |
77 pos = 0; | 72 pos = 0; |
78 while (this.data.length > 0) { | 73 while (this.data.length > 0) { |
79 tptr = this.data.shift(); | 74 tptr = new Buffer(this.data.shift()); |
80 tptr.copy(nbuf, pos); | 75 tptr.copy(nbuf, pos); |
81 pos += tptr.length; | 76 pos += tptr.length; |
82 } | 77 } |
83 return nbuf; | 78 return nbuf; |
84 }; | 79 }; |
85 this.close = function () { | 80 this.close = function () { |
86 if (this.alive) | 81 if (this.alive) |
87 this.child.kill('SIGHUP'); | 82 this.term.kill('SIGHUP'); |
88 }; | 83 }; |
89 this.cleanup = function () { | 84 this.cleanup = function () { |
90 /* Call this when the child is dead. */ | 85 /* Call this when the child is dead. */ |
91 if (this.alive) | 86 if (this.alive) |
92 return; | 87 return; |
184 resheaders["Set-Cookie"] = "ID=" + sessid; | 179 resheaders["Set-Cookie"] = "ID=" + sessid; |
185 res.writeHead(200, resheaders); | 180 res.writeHead(200, resheaders); |
186 var logindict = {"login": true, "id": sessid, "w": w, "h": h}; | 181 var logindict = {"login": true, "id": sessid, "w": w, "h": h}; |
187 res.write(JSON.stringify(logindict)); | 182 res.write(JSON.stringify(logindict)); |
188 res.end(); | 183 res.end(); |
189 console.log("Started new session with key " + sessid + ", pid " + nsession.child.pid); | 184 console.log("Started new session with key " + sessid + ", pid " + nsession.term.pid); |
190 return; | 185 return; |
191 } | 186 } |
192 | 187 |
193 function findTermSession(req) { | 188 function findTermSession(req) { |
194 var cookies = getCookies(req); | 189 var cookies = getCookies(req); |
351 } | 346 } |
352 | 347 |
353 process.on("exit", function () { | 348 process.on("exit", function () { |
354 for (var sessid in sessions) { | 349 for (var sessid in sessions) { |
355 if (sessions[sessid].alive) | 350 if (sessions[sessid].alive) |
356 sessions[sessid].child.kill('SIGHUP'); | 351 sessions[sessid].term.kill('SIGHUP'); |
357 } | 352 } |
358 console.log("Quitting..."); | 353 console.log("Quitting..."); |
359 return; | 354 return; |
360 }); | 355 }); |
361 | 356 |