From ad16a04c55eaf97e70559d247f1dc6d37ff98c01 Mon Sep 17 00:00:00 2001 From: zefie Date: Fri, 6 Aug 2021 12:18:30 -0400 Subject: [PATCH] update: do not delete WTVSec on last socket, instead recreate on prereg update: clean up SSID session data only if client is not seen for 3 minutes update: add shouldWeCompress() function update: tweak lzpf (still corrupted) update: rename wtv-setup:/get to wtv-setup:/get-settings update: add additional headers to wtv-setup:/get-settings update: add initial blank wtv-music:/get-playlist --- .../ServiceVault/wtv-1800/preregister.js | 7 +- .../wtv-head-waiter/login-stage-two.js | 13 ++- .../ServiceVault/wtv-head-waiter/login.js | 79 ++++++++----------- .../ServiceVault/wtv-music/get-playlist.js | 4 + .../wtv-setup/{get.js => get-settings.js} | 5 ++ zefie_wtvp_minisrv/WTVClientSessionData.js | 9 +++ zefie_wtvp_minisrv/WTVLzpf.js | 31 +++++--- zefie_wtvp_minisrv/app.js | 70 +++++++++++----- zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj | 5 +- 9 files changed, 137 insertions(+), 86 deletions(-) create mode 100644 zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js rename zefie_wtvp_minisrv/ServiceVault/wtv-setup/{get.js => get-settings.js} (82%) diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js index 4a9518e3..9956c53d 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-1800/preregister.js @@ -18,16 +18,17 @@ if (socket.ssid) { if (i > 0 && zdebug) console.log(" # Closed", i, "previous sockets for", filterSSID(socket.ssid)); } } - if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { + if (zdebug) console.log(" # Recreating primary WTVSec login instance for", filterSSID(socket.ssid)); delete ssid_sessions[socket.ssid].data_store.wtvsec_login; } ssid_sessions[socket.ssid].data_store.wtvsec_login = new WTVSec(); ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); - ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(request_headers["wtv-incarnation"]); + ssid_sessions[socket.ssid].data_store.wtvsec_login.set_incarnation(request_headers["wtv-incarnation"] || 1); } else { console.log(" * Something bad happened (we don't know the client ssid???)"); - var errpage = doErrorCode(400) + var errpage = doErrorPage(400) headers = errpage[0]; data = errpage[1]; } diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js index 6f587ad3..d6d9ca61 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login-stage-two.js @@ -79,7 +79,11 @@ wtv-service: reset wtv-boot-url: wtv-1800:/preregister?relogin=true wtv-human-name: ${nickname} ${ssid_sessions[socket.ssid].setIRCNick(nickname)} -wtv-home-url: wtv-home:/home? +wtv-home-url: wtv-home:/home?` + if (ssid_sessions[socket.ssid].get('wtv-need-upgrade') != 'true' && !request_headers.query.reconnect) { + headers += "\nwtv-settings-url: wtv-setup:/get-settings"; + } +headers += ` wtv-domain: wtv.zefie.com wtv-inactive-timeout: 0 wtv-connection-timeout: 90 @@ -94,11 +98,6 @@ wtv-log-url: wtv-log:/log wtv-demo-mode: 0 wtv-wink-deferrer-retries: 3 wtv-offline-mail-enable: false -wtv-name-server: 8.8.8.8 -`; - if (ssid_sessions[socket.ssid].get('wtv-need-upgrade') != 'true' && !request_headers.query.reconnect) { - headers += "wtv-settings-url: wtv-setup:/get\n"; - } - headers += `wtv-visit: wtv-home:/splash? +wtv-visit: wtv-home:/splash? Content-Type: text/html`; } \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js index df2b929c..d8e7768e 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/login.js @@ -1,72 +1,59 @@ -var challenge_response, challenge_header = ''; +var challenge_response, challenge_header = ""; var gourl = "wtv-head-waiter:/login-stage-two?"; if (request_headers.query.relogin) gourl += "relogin=true"; if (request_headers.query.reconnect) gourl += "reconnect=true"; +var send_to_relogin = true; -if (socket.ssid !== null) { - var wtvsec_login = ssid_sessions[socket.ssid].get("wtvsec_login"); - if (request_headers["wtv-ticket"]) { - if (wtvsec_login.ticket_b64 == null) { - if (request_headers["wtv-ticket"].length > 8) { - wtvsec_login.DecodeTicket(request_headers["wtv-ticket"]); - wtvsec_login.ticket_b64 = request_headers["wtv-ticket"]; - } - } - } else { - if (wtvsec_login) { - challenge_response = wtvsec_login.challenge_response; - var client_challenge_response = request_headers["wtv-challenge-response"] || null; - if (challenge_response && client_challenge_response) { - if (challenge_response.toString(CryptoJS.enc.Base64).substring(0, 85) == client_challenge_response.substring(0, 85)) { - console.log(" * wtv-challenge-response success for " + socket.ssid); - wtvsec_login.PrepareTicket(); - } else { - challenge_header = "wtv-challenge: " + wtvsec_login.IssueChallenge(); +if (socket.ssid) { + if (ssid_sessions[socket.ssid]) { + if (request_headers["wtv-ticket"]) { + if (ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 == null) { + if (request_headers["wtv-ticket"].length > 8) { + ssid_sessions[socket.ssid].data_store.wtvsec_login.DecodeTicket(request_headers["wtv-ticket"]); + ssid_sessions[socket.ssid].data_store.wtvsec_login.ticket_b64 = request_headers["wtv-ticket"]; + send_to_relogin = false; } - } else { - challenge_header = "wtv-challenge: " + wtvsec_login.IssueChallenge(); } } else { - wtvsec_login = new WTVSec(); - - } + if (ssid_sessions[socket.ssid].data_store.wtvsec_login) { + var client_challenge_response = request_headers["wtv-challenge-response"] || null; + if (challenge_response && client_challenge_response) { + if (challenge_response.toString(CryptoJS.enc.Base64).substring(0, 85) == client_challenge_response.substring(0, 85)) { + console.log(" * wtv-challenge-response success for " + socket.ssid); + ssid_sessions[socket.ssid].data_store.wtvsec_login.PrepareTicket(); + send_to_relogin = false; + } else { + challenge_header = "wtv-challenge: " + ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); + send_to_relogin = false; + } + } else { + challenge_header = "wtv-challenge: " + ssid_sessions[socket.ssid].data_store.wtvsec_login.IssueChallenge(); + send_to_relogin = false; + } + } + } } } -/* -if (request_headers) { - var cookiedata = {}; - Object.keys(request_headers).forEach(function (k) { - switch (k) { - case "wtv-capability-flags": - case "wtv-system-version": - case "wtv-client-rom-type": - case "wtv-client-bootrom-version": - case "wtv-system-chipversion": - case "wtv-system-sysconfig": - case "wtv-system-cpuspeed": - cookiedata[k] = request_headers[k]; - break; - } - }); -} -*/ +if (!send_to_relogin) { -if (challenge_header != '') { headers = `200 OK Connection: Keep-Alive Expires: Wed, 09 Oct 1991 22:00:00 GMT wtv-expire-all: wtv-head-waiter: `+ getServiceString('wtv-log') + ` -wtv-log-url: wtv-log:/log -${challenge_header} +wtv-log-url: wtv-log:/log`; + if (challenge_header != "") headers += "\n" + challenge_header; + headers += ` wtv-relogin-url: wtv-1800:/preregister?relogin=true wtv-reconnect-url: wtv-1800:/preregister?reconnect=true wtv-visit: ${gourl} Content-type: text/html`; data = ''; + } else { + headers = `200 OK Connection: Keep-Alive Expires: Wed, 09 Oct 1991 22:00:00 GMT diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js b/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js new file mode 100644 index 00000000..e42519c9 --- /dev/null +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-music/get-playlist.js @@ -0,0 +1,4 @@ +headers = `200 OK +Content-Type: text/html`; + +data = ''; \ No newline at end of file diff --git a/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get.js b/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js similarity index 82% rename from zefie_wtvp_minisrv/ServiceVault/wtv-setup/get.js rename to zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js index 827bd585..87468535 100644 --- a/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get.js +++ b/zefie_wtvp_minisrv/ServiceVault/wtv-setup/get-settings.js @@ -1,4 +1,9 @@ headers = `200 OK +wtv-backgroundmusic-load-playlist: wtv-music:/get-playlist +wtv-printer-model: -1,-1 +wtv-printer-pen: 0,0,1,0 +wtv-printer-setup: 0,0,1,0 +wtv-language-header: en-US,en Content-Type: text/html` var settings_obj = new Array(); diff --git a/zefie_wtvp_minisrv/WTVClientSessionData.js b/zefie_wtvp_minisrv/WTVClientSessionData.js index ba7b5dbf..65d6f94e 100644 --- a/zefie_wtvp_minisrv/WTVClientSessionData.js +++ b/zefie_wtvp_minisrv/WTVClientSessionData.js @@ -51,6 +51,15 @@ class WTVClientSessionData { return false; } + currentConnections() { + if (this.data_store) { + if (this.data_store.sockets) { + return this.data_store.sockets.size; + } + } + return 0; + } + get(key = null) { if (typeof (this.data_store) === 'undefined') return null; else if (key === null) return this.data_store; diff --git a/zefie_wtvp_minisrv/WTVLzpf.js b/zefie_wtvp_minisrv/WTVLzpf.js index 1c95cd51..380354a6 100644 --- a/zefie_wtvp_minisrv/WTVLzpf.js +++ b/zefie_wtvp_minisrv/WTVLzpf.js @@ -12,8 +12,9 @@ class WTVLzpf { current_length = 0 current_literal = 0 + compressed_offset = 0 flag_table = new Uint16Array(0x1000) - compressed_data = [] + compressed_data = null; nomatchEncode = [ [0x0000, 0x10], [0x0001, 0x10], [0x0002, 0x10], @@ -274,8 +275,9 @@ class WTVLzpf { clear() { this.current_length = 0; this.current_literal = 0; + this.compressed_offset = 0; this.flag_table.fill(0xFFFF, 0, 0x1000); - this.compressed_data = []; + this.compressed_data = null; } /** @@ -294,7 +296,7 @@ class WTVLzpf { while (this.current_length > 7) { //console.log("add", this.current_literal >>> 0, code >>> 0, byte, type) - this.compressed_data.push((this.current_literal >>> 0x18) & 0xFF); + this.compressed_offset = this.compressed_data.writeUInt8((this.current_literal >>> 0x18) & 0xFF, this.compressed_offset); this.current_length -= 8; this.current_literal = (this.current_literal << 8) & 0xFFFFFFFF; @@ -312,12 +314,19 @@ class WTVLzpf { this.clear(); if (uncompressed_data.words) { - uncompressed_data = new Buffer.from(this.wordArrayToUint8Array(uncompressed_data)); - } else { + // if its a wordArray convert it to a Buffer + + // Barrow function from WTVSec class + const WTVSec = require("./WTVSec.js"); + var wtvsec = new WTVSec(); + uncompressed_data = new Buffer.from(wtvsec.wordArrayToUint8Array(uncompressed_data)); + } else if (!uncompressed_data.byteLength) { + // otherwise if its not already a Buffer, convert it to one uncompressed_data = new Buffer.from(uncompressed_data); } - var uncompressed_len = uncompressed_data.length; + var uncompressed_len = uncompressed_data.byteLength; + this.compressed_data = new Buffer.alloc(uncompressed_len); var i = 0; var sum = 0; @@ -403,10 +412,14 @@ class WTVLzpf { this.EncodeLiteral(0x08, (sum << 0x18) & 0xFFFFFFFF); // End - this.compressed_data.push(this.current_literal >>> 0x18); - this.compressed_data.push(0x20); + this.compressed_offset = this.compressed_data.writeUInt8(this.current_literal >>> 0x18, this.compressed_offset); + this.compressed_offset = this.compressed_data.writeUInt8(0x20, this.compressed_offset); - return new Buffer.from(this.compressed_data); + var output_buffer = new Buffer.alloc(this.compressed_offset); + this.compressed_data.copy(output_buffer, 0, 0, this.compressed_offset) + this.compressed_data = null; + + return output_buffer; } } diff --git a/zefie_wtvp_minisrv/app.js b/zefie_wtvp_minisrv/app.js index 042c9b65..9368b09b 100644 --- a/zefie_wtvp_minisrv/app.js +++ b/zefie_wtvp_minisrv/app.js @@ -448,7 +448,7 @@ async function sendToClient(socket, headers_obj, data, compress_data = false) { return; } var wtv_connection_close = headers_obj["wtv-connection-close"]; - if (typeof(headers_obj["wtv-connection-close"]) != 'undefined') delete headers_obj["wtv-connection-close"]; + if (typeof (headers_obj["wtv-connection-close"]) != 'undefined') delete headers_obj["wtv-connection-close"]; // add Connection header if missing, default to Keep-Alive if (!headers_obj.Connection) { @@ -468,12 +468,27 @@ async function sendToClient(socket, headers_obj, data, compress_data = false) { compress_data = true; } + // fix captialization + if (headers_obj["Content-type"]) { + headers_obj["Content-Type"] = headers_obj["Content-type"]; + delete headers_obj["Content-type"]; + } + + + // if box can do compression, see if its worth enabling + if (ssid_sessions[socket.ssid].capabilities) { + if (ssid_sessions[socket.ssid].capabilities['client-can-receive-compressed-data']) { + compress_data = shouldWeCompress(headers_obj["Content-Type"]); + } + } + // compress if needed if (compress_data && clen > 0) { - headers_obj["wtv-lzpf"] = "0"; - - var lzpf = new WTVLzpf(); - data = lzpf.Compress(data); + headers_obj["wtv-lzpf"] = 0; + var wtvcomp = new WTVLzpf(); + var uncomp_data = data; + data = wtvcomp.Compress(uncomp_data); + uncomp_data, wtvcomp = null; } // encrypt if needed @@ -487,17 +502,11 @@ async function sendToClient(socket, headers_obj, data, compress_data = false) { } } - // fix captialization - if (headers_obj["Content-length"]) { - delete headers_obj["Content-length"]; - } - - if (headers_obj["Content-type"]) { - headers_obj["Content-Type"] = headers_obj["Content-type"]; - delete headers_obj["Content-type"]; - } - // calculate content length + // make sure we are using our Content-length and not one set in a script. + if (headers_obj["Content-Length"]) delete headers_obj["Content-Length"]; + if (headers_obj["Content-length"]) delete headers_obj["Content-length"]; + // On the WNI server this is the length before compression but we're using the length after compression. // It matches the HTTP spec anyway so leaving. if (typeof data.length !== 'undefined') { @@ -575,6 +584,19 @@ async function sendToClient(socket, headers_obj, data, compress_data = false) { } } +function shouldWeCompress(content_type) { + if (typeof (content_type) != 'undefined') { + if ((content_type.match(/^text\//) && content_type != "text/tellyscript") || + content_type.match(/^application\/(x-?)javascript$/) || + content_type.match(/^audio\/(x-)?midi/) || + content_type.match(/^audio\/(x-)?wav/) || + content_type == "application/json") { + return true; + } + } + return false; +} + function concatArrayBuffer(buffer1, buffer2) { var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); tmp.set(new Uint8Array(buffer1), 0); @@ -1091,14 +1113,22 @@ async function cleanupSocket(socket) { if (socket.ssid) { ssid_sessions[socket.ssid].data_store.sockets.delete(socket); - if (ssid_sessions[socket.ssid].data_store.sockets.size === 0 && ssid_sessions[socket.ssid].data_store.wtvsec_login) { - // if last socket for SSID disconnected, destroy login session - if (!zquiet) console.log(" * Last socket from WebTV SSID", filterSSID(socket.ssid),"disconnected, cleaning up primary WTVSec instance for this SSID"); - ssid_sessions[socket.ssid].delete("wtvsec_login"); - + if (ssid_sessions[socket.ssid].currentConnections() === 0) { // clean up possible minibrowser session data if (ssid_sessions[socket.ssid].get("wtv-needs-upgrade")) ssid_sessions[socket.ssid].delete("wtv-needs-upgrade"); if (ssid_sessions[socket.ssid].get("wtv-used-8675309")) ssid_sessions[socket.ssid].delete("wtv-used-8675309"); + + // set timer to destroy entirety of session data if client does not return in X time + var timeout = 180000; // timeout is in milliseconds, default 180000 (3 min) .. be sure to allow time for dialup reconnections + + if (!ssid_sessions[socket.ssid].data_store.socket_check) { + ssid_sessions[socket.ssid].data_store.socket_check = setTimeout(function (ssid) { + if (ssid_sessions[ssid].currentConnections() === 0) { + if (!zquiet) console.log(" * WebTV SSID", filterSSID(ssid), " has not been seen in", (timeout / 1000), "seconds, cleaning up session data for this SSID"); + delete ssid_sessions[ssid]; + } + }, timeout, socket.ssid); + } } } socket.end(); diff --git a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj index d8923f44..eabe471a 100644 --- a/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj +++ b/zefie_wtvp_minisrv/zefie_wtvp_minisrv.njsproj @@ -186,7 +186,10 @@ - + + Code + + Code