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 () { |
