comparison rlgwebd.js @ 168:0ceaca924b4c

Remove the TermSession 'open' event. Failure is now signaled with a TermSession.failed flag. Playing two games at the same time no longer causes crashes, but it does send the same output to both players.
author John "Elwin" Edwards
date Fri, 09 Jan 2015 08:55:38 -0500
parents fba1b34e7554
children 6f4b7e1b32e8
comparison
equal deleted inserted replaced
167:fba1b34e7554 168:0ceaca924b4c
71 * lkey: (String, key) The user's id, a key into logins. 71 * lkey: (String, key) The user's id, a key into logins.
72 * dims: (Array [Number, Number]) Height and width of the pty. 72 * dims: (Array [Number, Number]) Height and width of the pty.
73 * handlers: (Object) Key-value pairs, event names and functions to 73 * handlers: (Object) Key-value pairs, event names and functions to
74 * install to handle them. 74 * install to handle them.
75 * Events: 75 * Events:
76 * "open": Emitted on startup. Parameters: success (Boolean)
77 * "data": Data generated by child. Parameters: buf (Buffer) 76 * "data": Data generated by child. Parameters: buf (Buffer)
78 * "exit": Child terminated. Parameters: none 77 * "exit": Child terminated. Parameters: none
79 */ 78 */
80 function TermSession(game, lkey, dims, handlers) { 79 function TermSession(game, lkey, dims, handlers) {
81 var ss = this; 80 var ss = this;
86 /* Don't launch anything that's not a real game. */ 85 /* Don't launch anything that's not a real game. */
87 if (game in games) { 86 if (game in games) {
88 this.game = games[game]; 87 this.game = games[game];
89 } 88 }
90 else { 89 else {
91 this.emit('open', false); 90 this.failed = true;
92 return; 91 return;
93 } 92 }
94 if (lkey in logins) { 93 if (lkey in logins) {
95 this.key = lkey; 94 this.key = lkey;
96 this.pname = logins[lkey].name; 95 this.pname = logins[lkey].name;
97 } 96 }
98 else { 97 else {
99 this.emit('open', false); 98 this.failed = true;
100 return; 99 return;
101 } 100 }
102 /* Grab a spot in the sessions table. */ 101 /* Grab a spot in the sessions table. */
103 sessions[this.game.uname + "/" + this.pname] = this; 102 sessions[this.game.uname + "/" + this.pname] = this;
104 /* Set up the sizes. */ 103 /* Set up the sizes. */
116 var args = ["-n", this.pname]; 115 var args = ["-n", this.pname];
117 var spawnopts = {"env": childenv, "cwd": "/", "rows": this.h, "cols": this.w, 116 var spawnopts = {"env": childenv, "cwd": "/", "rows": this.h, "cols": this.w,
118 "name": "xterm-256color"}; 117 "name": "xterm-256color"};
119 this.term = pty.spawn(this.game.path, args, spawnopts); 118 this.term = pty.spawn(this.game.path, args, spawnopts);
120 tslog("%s playing %s (pid %d)", this.pname, this.game.uname, this.term.pid); 119 tslog("%s playing %s (pid %d)", this.pname, this.game.uname, this.term.pid);
121 this.emit('open', true, this.game.uname, this.pname); 120 this.failed = false;
122 gamemux.emit('begin', this.game.uname, this.pname); 121 gamemux.emit('begin', this.game.uname, this.pname);
123 /* Set up the lockfile and ttyrec */ 122 /* Set up the lockfile and ttyrec */
124 this.lasttime = new Date(); 123 this.lasttime = new Date();
125 var ts = timestamp(this.lasttime); 124 var ts = timestamp(this.lasttime);
126 var progressdir = path.join("/dgldir/inprogress", this.game.uname); 125 var progressdir = path.join("/dgldir/inprogress", this.game.uname);
322 conn.sendUTF(JSON.stringify({"t": "d", 321 conn.sendUTF(JSON.stringify({"t": "d",
323 "d": session.framebuf.toString("hex", 0, session.frameoff)})); 322 "d": session.framebuf.toString("hex", 0, session.frameoff)}));
324 } 323 }
325 324
326 function wsPlay(wsReq, game, lkey, dims) { 325 function wsPlay(wsReq, game, lkey, dims) {
326 tslog("wsPlay: running for %s/%s", game, logins[lkey].name);
327 tslog("Request is for %s", logins[wsReq.resourceURL.query["key"]].name);
327 var conn; 328 var conn;
328 var session; 329 var session;
329 /* Listeners on the WebSocket */ 330 /* Listeners on the WebSocket */
330 function messageH(message) { 331 function messageH(message) {
331 var parsedMsg = getMsgWS(message); 332 var parsedMsg = getMsgWS(message);
343 } 344 }
344 function closeH() { 345 function closeH() {
345 session.close(); 346 session.close();
346 } 347 }
347 /* These listen on the TermSession. */ 348 /* These listen on the TermSession. */
348 function openH(success, gname, pname) {
349 if (success) {
350 var tag = gname + "/" + pname;
351 var reply = {"t": "s", "tag": tag, "w": sessions[tag].w, "h":
352 sessions[tag].h, "p": pname, "g": gname};
353 conn = wsReq.accept(null, wsReq.origin);
354 conn.sendUTF(JSON.stringify(reply));
355 conn.on('message', messageH);
356 conn.on('close', closeH);
357 }
358 else {
359 wsReq.reject(500, errorcodes[5]);
360 tslog("Unable to allocate TTY for %s", game);
361 }
362 }
363 function dataH(chunk) { 349 function dataH(chunk) {
364 var msg = {}; 350 var msg = {};
365 msg.t = "d"; 351 msg.t = "d";
366 msg.d = chunk.toString("hex"); 352 msg.d = chunk.toString("hex");
367 conn.sendUTF(JSON.stringify(msg)); 353 conn.sendUTF(JSON.stringify(msg));
368 } 354 }
369 function exitH() { 355 function exitH() {
370 if (conn.connected) 356 if (conn.connected)
371 conn.sendUTF(JSON.stringify({"t": "q"})); 357 conn.sendUTF(JSON.stringify({"t": "q"}));
372 conn.close(); 358 conn.close();
373 session.removeListener('open', openH);
374 session.removeListener('data', dataH); 359 session.removeListener('data', dataH);
375 session.removeListener('exit', exitH); 360 session.removeListener('exit', exitH);
376 } 361 }
377 var handlers = {'open': openH, 'data': dataH, 'exit': exitH}; 362 var handlers = {'data': dataH, 'exit': exitH};
378 session = new TermSession(game, lkey, dims, handlers); 363 session = new TermSession(game, lkey, dims, handlers);
364 if (!session.failed) {
365 var tag = session.game.uname + "/" + session.pname;
366 var reply = {"t": "s", "tag": tag, "w": session.w, "h": session.h,
367 "p": session.pname, "g": session.game.uname};
368 tslog("Accepting for %s", tag);
369 tslog("Request is for %s", logins[wsReq.resourceURL.query["key"]].name);
370 tslog("Session is for %s", session.pname);
371 conn = wsReq.accept(null, wsReq.origin);
372 conn.sendUTF(JSON.stringify(reply));
373 conn.on('message', messageH);
374 conn.on('close', closeH);
375 }
376 else {
377 wsReq.reject(500, errorcodes[5]);
378 tslog("Unable to allocate TTY for %s", game);
379 }
379 } 380 }
380 381
381 function wsStart(wsReq) { 382 function wsStart(wsReq) {
382 var playmatch = wsReq.resourceURL.pathname.match(/^\/play\/([^\/]*)$/); 383 var playmatch = wsReq.resourceURL.pathname.match(/^\/play\/([^\/]*)$/);
383 if (!playmatch[1] || !(playmatch[1] in games)) { 384 if (!playmatch[1] || !(playmatch[1] in games)) {