Mercurial > hg > rlgwebd
comparison rlgwebd.js @ 175:4dd87508fc96
Add server-side support for watching dgamelaunch games.
author | John "Elwin" Edwards |
---|---|
date | Tue, 13 Jan 2015 20:30:10 -0500 |
parents | dc12ba30d559 |
children | bf518a00190b |
comparison
equal
deleted
inserted
replaced
174:dc12ba30d559 | 175:4dd87508fc96 |
---|---|
295 } | 295 } |
296 ss.reading = false; | 296 ss.reading = false; |
297 return; | 297 return; |
298 } | 298 } |
299 ss.rpos += 12; | 299 ss.rpos += 12; |
300 /* Update timestamp, to within 1 second. */ | |
301 ss.lasttime = new Date(1000 * buf.readUInt32LE(0)); | |
300 var datalen = buf.readUInt32LE(8); | 302 var datalen = buf.readUInt32LE(8); |
301 //tslog("Allocating %d bytes", datalen); | 303 //tslog("Allocating %d bytes", datalen); |
302 if (datalen > 16384) { | 304 if (datalen > 16384) { |
303 tslog("DGL %s: looking for %d bytes", ss.tag(), datalen); | 305 tslog("DGL %s: looking for %d bytes", ss.tag(), datalen); |
304 } | 306 } |
313 } | 315 } |
314 ss.rpos += n; | 316 ss.rpos += n; |
315 ss.reading = false; | 317 ss.reading = false; |
316 /* Process the data */ | 318 /* Process the data */ |
317 ss.framepush(buf); | 319 ss.framepush(buf); |
320 var wmsg = JSON.stringify({"t": "d", "d": buf.toString("hex")}); | |
321 for (var i = 0; i < ss.watchers.length; i++) { | |
322 if (ss.watchers[i].connected) | |
323 ss.watchers[i].sendUTF(wmsg); | |
324 } | |
318 ss.emit("data", buf); | 325 ss.emit("data", buf); |
319 //tslog("DGL %s: %d bytes", ss.tag(), buf.length); | 326 //tslog("DGL %s: %d bytes", ss.tag(), buf.length); |
320 /* Recurse. */ | 327 /* Recurse. */ |
321 ss.readchunk(); | 328 ss.readchunk(); |
322 }); | 329 }); |
337 else { | 344 else { |
338 ss.fd = fd; | 345 ss.fd = fd; |
339 ss.emit('open', true); | 346 ss.emit('open', true); |
340 tslog("DGL %s: open", ss.tag()); | 347 tslog("DGL %s: open", ss.tag()); |
341 ss.readchunk(); | 348 ss.readchunk(); |
342 ss.watcher = fs.watch(ss.ttyrec, function (ev, finame) { | 349 ss.recwatcher = fs.watch(ss.ttyrec, function (ev, finame) { |
343 if (ev == "change") | 350 if (ev == "change") |
344 ss.readchunk(); | 351 ss.readchunk(); |
345 }); | 352 }); |
346 } | 353 } |
347 }); | 354 }); |
348 }); | 355 }); |
349 this.tag = function () { | 356 this.tag = function () { |
350 return this.gname + "/" + this.pname; | 357 return this.gname + "/" + this.pname; |
351 }; | 358 }; |
352 this.close = function () { | 359 this.close = function () { |
353 this.watcher.close() | 360 this.recwatcher.close() |
354 /* Ensure all data is handled before quitting. */ | 361 /* Ensure all data is handled before quitting. */ |
355 this.readchunk(); | 362 this.readchunk(); |
363 var connlist = this.watchers; | |
364 this.watchers = []; | |
365 for (var i = 0; i < connlist.length; i++) { | |
366 if (connlist[i].connected) | |
367 connlist[i].close(); | |
368 } | |
356 fs.close(this.fd); | 369 fs.close(this.fd); |
357 this.emit("close"); | 370 this.emit("close"); |
358 tslog("DGL %s: closed", ss.tag()); | 371 tslog("DGL %s: closed", ss.tag()); |
359 }; | 372 }; |
373 this.watchers = []; | |
374 /* Attach a watcher. */ | |
375 this.attach = function (wsReq) { | |
376 var conn = wsReq.accept(null, wsReq.origin); | |
377 conn.sendUTF(JSON.stringify({ | |
378 "t": "w", "w": this.w, "h": this.h, "p": this.pname, | |
379 "g": this.gname | |
380 })); | |
381 conn.sendUTF(JSON.stringify({"t": "d", | |
382 "d": this.framebuf.toString("hex", 0, this.frameoff)})); | |
383 conn.on('close', function () { | |
384 /* 'this' is the connection when triggered */ | |
385 var n = ss.watchers.indexOf(this); | |
386 if (n >= 0) { | |
387 ss.watchers.splice(n, 1); | |
388 tslog("A WebSocket watcher has left DGL game %s", ss.tag()); | |
389 } | |
390 }); | |
391 this.watchers.push(conn); | |
392 }; | |
393 this.lasttime = new Date(); | |
360 } | 394 } |
361 DglSession.prototype = new events.EventEmitter(); | 395 DglSession.prototype = new events.EventEmitter(); |
362 | 396 |
363 function wsStartGame(wsReq) { | 397 function wsStartGame(wsReq) { |
364 var playmatch = wsReq.resourceURL.pathname.match(/^\/play\/([^\/]*)$/); | 398 var playmatch = wsReq.resourceURL.pathname.match(/^\/play\/([^\/]*)$/); |
788 for (var tag in sessions) { | 822 for (var tag in sessions) { |
789 var gamedesc = {}; | 823 var gamedesc = {}; |
790 gamedesc["p"] = sessions[tag].pname; | 824 gamedesc["p"] = sessions[tag].pname; |
791 gamedesc["g"] = sessions[tag].game.uname; | 825 gamedesc["g"] = sessions[tag].game.uname; |
792 gamedesc["i"] = now - sessions[tag].lasttime; | 826 gamedesc["i"] = now - sessions[tag].lasttime; |
827 gamedesc["w"] = sessions[tag].watchers.length; | |
793 statusinfo["g"].push(gamedesc); | 828 statusinfo["g"].push(gamedesc); |
794 } | 829 } |
795 statusinfo["dgl"] = []; | 830 statusinfo["dgl"] = []; |
796 for (var tag in dglgames) { | 831 for (var tag in dglgames) { |
797 var dglinfo = {}; | 832 var dglinfo = {}; |
798 var slash = tag.search('/'); | 833 var slash = tag.search('/'); |
799 dglinfo["g"] = tag.slice(0, slash); | 834 dglinfo["g"] = tag.slice(0, slash); |
800 dglinfo["p"] = tag.slice(slash + 1); | 835 dglinfo["p"] = tag.slice(slash + 1); |
801 dglinfo["i"] = -1; | 836 dglinfo["i"] = now - dglgames[tag].lasttime; |
837 dglinfo["w"] = dglgames[tag].watchers.length; | |
802 statusinfo["dgl"].push(dglinfo); | 838 statusinfo["dgl"].push(dglinfo); |
803 } | 839 } |
804 callback(statusinfo); | 840 callback(statusinfo); |
805 } | 841 } |
806 | 842 |
1020 | 1056 |
1021 function wsHandler(wsRequest) { | 1057 function wsHandler(wsRequest) { |
1022 var watchmatch = wsRequest.resource.match(/^\/watch\/(.*)$/); | 1058 var watchmatch = wsRequest.resource.match(/^\/watch\/(.*)$/); |
1023 var playmatch = wsRequest.resource.match(/^\/play\//); | 1059 var playmatch = wsRequest.resource.match(/^\/play\//); |
1024 if (watchmatch !== null) { | 1060 if (watchmatch !== null) { |
1025 if (!(watchmatch[1] in sessions)) { | 1061 if (watchmatch[1] in sessions) { |
1062 var tsession = sessions[watchmatch[1]]; | |
1063 tsession.attach(wsRequest); | |
1064 tslog("Game %s is being watched via WebSockets", tsession.tag()); | |
1065 } | |
1066 else if (watchmatch[1] in dglgames) { | |
1067 var dsession = dglgames[watchmatch[1]]; | |
1068 dsession.attach(wsRequest); | |
1069 tslog("DGL game %s is being watched via WebSockets", dsession.tag()); | |
1070 } | |
1071 else { | |
1026 wsRequest.reject(404, errorcodes[7]); | 1072 wsRequest.reject(404, errorcodes[7]); |
1027 return; | 1073 return; |
1028 } | 1074 } |
1029 var tsession = sessions[watchmatch[1]]; | |
1030 tsession.attach(wsRequest); | |
1031 tslog("Game %s is being watched via WebSockets", tsession.tag()); | |
1032 } | 1075 } |
1033 else if (playmatch !== null) { | 1076 else if (playmatch !== null) { |
1034 wsStartGame(wsRequest); | 1077 wsStartGame(wsRequest); |
1035 } | 1078 } |
1036 else if (wsRequest.resourceURL.pathname == "/status") { | 1079 else if (wsRequest.resourceURL.pathname == "/status") { |
1075 if (delta < 60000) { | 1118 if (delta < 60000) { |
1076 var gamedesc = {}; | 1119 var gamedesc = {}; |
1077 gamedesc["p"] = sessions[tag].pname; | 1120 gamedesc["p"] = sessions[tag].pname; |
1078 gamedesc["g"] = sessions[tag].game.uname; | 1121 gamedesc["g"] = sessions[tag].game.uname; |
1079 gamedesc["i"] = delta; | 1122 gamedesc["i"] = delta; |
1123 gamedesc["w"] = sessions[tag].watchers.length; | |
1080 statusinfo["g"].push(gamedesc); | 1124 statusinfo["g"].push(gamedesc); |
1081 } | 1125 } |
1082 } | 1126 } |
1083 for (var tag in dglgames) { | 1127 for (var tag in dglgames) { |
1084 var dglinfo = {}; | 1128 var delta = now - dglgames[tag].lasttime; |
1085 var slash = tag.search('/'); | 1129 if (delta < 60000) { |
1086 dglinfo["g"] = tag.slice(0, slash); | 1130 var dglinfo = {}; |
1087 dglinfo["p"] = tag.slice(slash + 1); | 1131 var slash = tag.search('/'); |
1088 dglinfo["i"] = -1; | 1132 dglinfo["g"] = tag.slice(0, slash); |
1089 statusinfo["dgl"].push(dglinfo); | 1133 dglinfo["p"] = tag.slice(slash + 1); |
1134 dglinfo["i"] = delta; | |
1135 dglinfo["w"] = dglgames[tag].watchers.length; | |
1136 statusinfo["dgl"].push(dglinfo); | |
1137 } | |
1090 } | 1138 } |
1091 gamemux.emit('list', statusinfo); | 1139 gamemux.emit('list', statusinfo); |
1092 } | 1140 } |
1093 | 1141 |
1094 function shutdown () { | 1142 function shutdown () { |