From c57568f8d2ec04bd4eb21224f97171b0db3680d6 Mon Sep 17 00:00:00 2001 From: zefie Date: Thu, 20 Feb 2025 16:51:30 -0500 Subject: [PATCH] generate lc2 prereg tellyscript on the fly --- .../tellyscripts/LC2/LC2.prereg.template.txt | 468 ++++++++++++++++++ .../ServiceVault/wtv-1800/preregister.js | 17 +- .../includes/classes/WTVTellyScript.js | 25 + zefie_wtvp_minisrv/includes/config.json | 8 +- zefie_wtvp_minisrv/test_prereg.js | 75 +++ 5 files changed, 591 insertions(+), 2 deletions(-) create mode 100644 zefie_wtvp_minisrv/includes/ServiceDeps/wtv-1800/tellyscripts/LC2/LC2.prereg.template.txt create mode 100644 zefie_wtvp_minisrv/test_prereg.js diff --git a/zefie_wtvp_minisrv/includes/ServiceDeps/wtv-1800/tellyscripts/LC2/LC2.prereg.template.txt b/zefie_wtvp_minisrv/includes/ServiceDeps/wtv-1800/tellyscripts/LC2/LC2.prereg.template.txt new file mode 100644 index 00000000..9a68faa9 --- /dev/null +++ b/zefie_wtvp_minisrv/includes/ServiceDeps/wtv-1800/tellyscripts/LC2/LC2.prereg.template.txt @@ -0,0 +1,468 @@ + + + + + + + + + +int dterate; +int dcerate; +int protocol; +int compression; +int connected; + + + + + + +parseResult(int result) +{ + int retcode = 0; + char *comment = ""; + + if (result == 0) + { + comment = " OK"; + retcode = 1; + } + else if (result == 3) + { + comment = "NO CARRIER"; + retcode = 12; + } + else if (result == 6) + { + comment = "NO DIALTONE"; + retcode = 5; + } + else if (result == 7) + { + comment = "BUSY"; + retcode = 7; + } + else if (result == 8) + { + comment = "NO ANSWER"; + retcode = 6; + } + else if (result == 18) + { + comment = "Connected!"; + dterate = 0xe100; + connected = 1; + } + else if (result == 19) + { + comment = "Connected!"; + dterate = 0x1c200; + connected = 1; + } + else if (result == 20) + { + comment = "Connected!"; + dterate = 0x39210; + connected = 1; + } + else if (result == 46) + { + dcerate = 0x4b0; + } + else if (result == 47) + { + dcerate = 0x960; + } + else if (result == 48) + { + dcerate = 0x12c0; + } + else if (result == 49) + { + dcerate = 0x1c20; + } + else if (result == 50) + { + dcerate = 0x2580; + } + else if (result == 51) + { + dcerate = 0x2ee0; + } + else if (result == 52) + { + dcerate = 0x3840; + } + else if (result == 53) + { + dcerate = 0x41a0; + } + else if (result == 54) + { + dcerate = 0x4b00; + } + else if (result == 55) + { + dcerate = 0x5460; + } + else if (result == 56) + { + dcerate = 0x5dc0; + } + else if (result == 57) + { + dcerate = 0x6720; + } + else if (result == 58) + { + dcerate = 0x7080; + } + else if (result == 66) + { + compression = 1; + } + else if (result == 67) + { + compression = 2; + } + else if (result == 69) + { + compression = 0; + } + else if (result == 76) + { + protocol = 0; + } + else if (result == 77) + { + protocol = 1; + } + else if (result == 78 || result == 60) + { + dcerate = 0x79e0; + } + else if (result == 79 || result == 65) + { + dcerate = 0x8340; + } + else if (result == 80) + { + protocol = 2; + } + else if (result == 81) + { + protocol = 3; + } + else + { + printf("TellyScript: ParseResult -- %d unknown", result); + retcode = 9; + } + + printf("TellyScript: ParseResult -- %d %s (retcode=%d)", result, + comment, retcode); + return retcode; +} + +ConfigureModem(char *cmd, char *response) +{ + int retries; + int len = strlen(response); + + retries = 0; + while (retries++ <= 3) + { + flush(); + + sendstr(cmd); + if (waitfor(response, len, 120)) + { + printf("TellyScript: Configured modem."); + break; + } + else + { + printf("TellyScript: TIMEOUT waiting for OK"); + builtin_winkdtr(); + } + } + + if (retries > 3) + { + return 0; + } + else + { + return 1; + } +} + +main() +{ + int count, i, result; + int start = ticks(); + int end; + char *number; + char buffer[32]; + char *settings = getphonesettings(); + char *accessNumber = &settings[108]; + char *dialOutsidePrefix = &settings[32]; + char *dialLDPrefix = &settings[140]; + char *callWaitingPrefix = &settings[0]; + char usePulseDialing = settings[96]; + char audibleDialing = settings[97]; + char disableCallWaiting = settings[98]; + char dialOutsideLine = settings[99]; + char changedCity = settings[100]; + char waitForTone = settings[101]; + char hasCallWaiting = settings[102]; + char useCallWaitingHack = settings[103]; + char dialSpeed = settings[104]; + char brokenPBX = settings[106]; + char numberToDial[32]; + char secondConfigCommand[80]; + char dialCommand[80]; + char *configurationCommand = "ATS38=0S30=180S95=36S11=60&D2V1E0L3&Q5&K3\r"; + char *defaultNumber = "%DialinNumber%"; + char *nvOverRide = getpreregnumber(); + char *secret = getsecret(); + char *serial_number = getserialnumber(); + char username[32]; + char password[32]; + + printf("TellyScript: 800 Registration Script 4.1-zefie"); + setprogressmode(1); + setprogresstext("Preparing to call"); + setprogresspercentage(16); + setprogressdirty(1); + + + + + if (nvOverRide != 0) + { + defaultNumber = nvOverRide; + printf("TellyScript: Over-riding default preregistration number with %s from NVRAM", nvOverRide); + } + + + + if (accessNumber[0]) + strcpy(numberToDial, accessNumber); + else + strcpy(numberToDial, defaultNumber); + + + + if (brokenPBX) + if (numberToDial[0] == 49) + strcpy(numberToDial, &numberToDial[1]); + + + + strcpy(secondConfigCommand, "ATV0"); + + + + if (audibleDialing) + strcat(secondConfigCommand, "M1"); + else + strcat(secondConfigCommand, "M0"); + + + + if (waitForTone) + strcat(secondConfigCommand, "S6=10X4"); + else + strcat(secondConfigCommand, "S6=4X3"); + + + + strcat(secondConfigCommand, "S10=14"); + + + + if (dialSpeed == 0) + strcat(secondConfigCommand, "S11=200"); + else if (dialSpeed == 1) + strcat(secondConfigCommand, "S11=110"); + else if (dialSpeed == 2) + strcat(secondConfigCommand, "S11=60"); + else if (dialSpeed == 3) + strcat(secondConfigCommand, "S11=1"); + + strcat(secondConfigCommand, "\r"); + + + + if (usePulseDialing) + strcpy(dialCommand, "ATDP"); + else + strcpy(dialCommand, "ATDT"); + + + + if (disableCallWaiting) + { + strcat(dialCommand, callWaitingPrefix); + } + + + + if (strlen(dialLDPrefix) > 0) + { + strcat(dialCommand, dialLDPrefix); + strcat(dialCommand, ","); + } + else + if (dialOutsideLine) + { + strcat(dialCommand, dialOutsidePrefix); + strcat(dialCommand, ","); + } + + + + setwindowsize(3); + printf("TellyScript: TCP Window Size set to 3 (USR)."); + + enablemodem(); + + builtin_winkdtr(); + setflowcontrol(3); + setbaud(0xe100); + + if (!ConfigureModem(configurationCommand, "OK")) + { + printf("TellyScript: Couldn't get OK from modem during first config cmd"); + setdtr(0); + return 3; + } + + flush(); + + if (!ConfigureModem(secondConfigCommand, "0")) + { + printf("TellyScript: Couldn't get OK from modem during second config cmd"); + setdtr(0); + return 3; + } + + flush(); + + setprogresstext("Dialing %ServiceName%..."); + setprogresspercentage(32); + setprogressdirty(1); + + printf("TellyScript: Overriding exclusion circuit..."); + setforcehook(1); + + printf("TellyScript: Dialing %s...", numberToDial); + if ((numberToDial[0] != 65) && (numberToDial[0] != 97)) + sendstr(dialCommand); + sendstr(numberToDial); + + sendstr(";\r"); + + + + + + + + sprintf(buffer, "prereg: %s", numberToDial); + setworkingnumber(buffer); + + flush(); + + i = 0; + connected = 0; + while (!connected && i < 6) { + count = getline(buffer, 31, 0x1068); + i++; + + if (count == 0) { + printf("TellyScript: TIMEOUT waiting for dial result."); + setdtr(0); + if (i == 1) + return 4; + else + return 8; + } + + result = parseResult(atoi(buffer)); + if (result == 1) { + if (i == 1) { + setprogresstext("Waiting for answer..."); + setprogresspercentage(48); + setprogressdirty(1); + sendstr("ATD\r"); + result = 0; + } else { + + setdtr(0); + printf("TellyScript: got '%s' at odd time", buffer); + return 8; + } + } + + if (result != 0) { + setdtr(0); + if (result == 12 && i > 2) { + + return 8; + } + return result; + } else { + if (i > 1) { + setprogresstext("%ServiceName% answered..."); + setprogresspercentage(64); + setprogressdirty(1); + } + } + } + + printf("TellyScript: Setting NameServers: %DNSIP1%, %DNSIP2%"); + setnameservice(%DNS1%, %DNS2%); + + printf("TellyScript: dterate = %d, dcerate = %d, protocol = %d, compression = %d", + dterate, dcerate, protocol, compression); + setconnectionstats(dterate, dcerate, protocol, compression); + + setprogresstext("Starting communication..."); + setprogresspercentage(80); + setprogressdirty(1); + + sprintf(username, "wtv_%s", serial_number); + sprintf(password, "%d", computefcs(serial_number)); + + printf("TellyScript: Using '%s' for username", username); + printf("TellyScript: Using '%s' for password", password); + + setusername(username); + setpassword(password); + setpapmode(1); + + if (!startppp()) + { + setdtr(0); + if (getpppresult() == 3) + { + printf("TellyScript: PAP authentification failure"); + return 10; + } + + printf("TellyScript: PPP negotiation failed"); + return 11; + } + + setprogresstext("Connected to %ServiceName%"); + setprogresspercentage(100); + setprogressdirty(1); + + printf("TellyScript: Link connected."); + printf("TellyScript: total time = %d (seconds)", (ticks() - start) / 60); + + return 2; +} diff --git a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js index 40b7c251..b22884e4 100644 --- a/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js +++ b/zefie_wtvp_minisrv/includes/ServiceVault/wtv-1800/preregister.js @@ -86,7 +86,8 @@ if (session_data.data_store.wtvsec_login) { prereg_contype = "text/tellyscript"; // if wtv-open-access: true then client expects OpenISP if (session_data.get("wtv-open-access")) file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/LC2/LC2_OpenISP_56k.tok", true); - else file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/LC2/LC2_WTV_18006138199.tok", true); + else template_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/LC2/LC2.prereg.template.txt", true); + //else file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/LC2/LC2_WTV_18006138199.tok", true); break; case "US-DTV-disk-0MB-32MB-softmodem-CPU5230": @@ -196,6 +197,20 @@ if (session_data.data_store.wtvsec_login) { } sendToClient(socket, headers, file_read_data); }); + } else if (template_path) { + request_is_async = true; + fs.readFile(template_path, null, function (err, file_read_data) { + if (err) { + var errmsg = wtvshared.doErrorPage(400); + headers = errmsg[0]; + file_read_data = errmsg[1] + "\n" + err.toString(); + } + telly = new WTVTellyScript(file_read_data, 2); // 2 = Untokenized + telly.setTemplateVars(minisrv_config.config.service_name, minisrv_config.services[service_name].dialin_number, minisrv_config.services[service_name].dns1ip, minisrv_config.services[service_name].dns2ip); + telly.tokenize(); + telly.pack(); + sendToClient(socket, headers, telly.packed_data); + }); } } else { var errpage = wtvshared.doErrorPage(400); diff --git a/zefie_wtvp_minisrv/includes/classes/WTVTellyScript.js b/zefie_wtvp_minisrv/includes/classes/WTVTellyScript.js index b3f19088..bd6f8a1e 100644 --- a/zefie_wtvp_minisrv/includes/classes/WTVTellyScript.js +++ b/zefie_wtvp_minisrv/includes/classes/WTVTellyScript.js @@ -921,6 +921,31 @@ class WTVTellyScript { this.process(data, dataState); } + ipToHex(ip) { + const parts = ip.split('.'); + if (parts.length !== 4) { + throw new Error('Invalid IP address'); + } + let num = 0; + for (let i = 0; i < 4; i++) { + const part = parseInt(parts[i], 10); + if (part < 0 || part > 255) { + throw new Error('Invalid IP address'); + } + num = (num << 8) | part; + } + return "0x" + num.toString(16).toUpperCase(); + } + + setTemplateVars(service_name, dialin_number, DNS1IP, DNS2IP) { + this.raw_data = this.raw_data.replaceAll("%ServiceName%", service_name); + this.raw_data = this.raw_data.replaceAll("%DialinNumber%", dialin_number); + this.raw_data = this.raw_data.replaceAll("%DNSIP1%", DNS1IP); + this.raw_data = this.raw_data.replaceAll("%DNSIP2%", DNS2IP); + this.raw_data = this.raw_data.replaceAll("%DNS1%", this.ipToHex(DNS1IP)); + this.raw_data = this.raw_data.replaceAll("%DNS2%", this.ipToHex(DNS2IP)); + } + // --- Big Endian Converter Helpers --- toUint32(bytes, offset) { diff --git a/zefie_wtvp_minisrv/includes/config.json b/zefie_wtvp_minisrv/includes/config.json index fd483e78..bdcb123c 100644 --- a/zefie_wtvp_minisrv/includes/config.json +++ b/zefie_wtvp_minisrv/includes/config.json @@ -192,7 +192,13 @@ "connections": 1, "flags": "0x00000001", "privileged": true, - "send_tellyscripts": true // Best left untouched + "send_tellyscripts": true, // Best left untouched + "dialin_number": 18006138199, + "dns1ip": "10.0.0.50", + "dns2ip": "8.8.8.8", + "modules": [ + "WTVTellyScript" + ] }, "wtv-flashrom": { // wtv-flashrom diff --git a/zefie_wtvp_minisrv/test_prereg.js b/zefie_wtvp_minisrv/test_prereg.js new file mode 100644 index 00000000..8bf4258a --- /dev/null +++ b/zefie_wtvp_minisrv/test_prereg.js @@ -0,0 +1,75 @@ +const headerDelimiter = Buffer.from('\n\n'); +let accumulatedBuffer = Buffer.alloc(0); +const process = require('process'); +const fs = require('fs'); +const path = require('path'); +const classPath = path.resolve(__dirname + path.sep + "includes" + path.sep + "classes" + path.sep) + path.sep; +const { WTVShared, clientShowAlert } = require(classPath + "/WTVShared.js"); +const WTVTellyScript = require(classPath + "/WTVTellyScript.js") + +headers = `GET wtv-1800:/preregister +wtv-client-serial-number: 9111111111111111 +wtv-client-rom-type: US-LC2-disk-0MB-8MB +wtv-show-time-record: 1 +wtv-request-type: primary +wtv-system-cpuspeed: 166187148 +wtv-system-sysconfig: 4163328 +wtv-disk-size: 8006 +wtv-viewer: WebTVIntel--2.5-HE +wtv-incarnation: 1 +Accept-Language: en +wtv-connect-session-id: 7b662075 +wtv-system-version: 7181 +wtv-capability-flags: 10935ffc8f +wtv-client-bootrom-version: 2046 +wtv-client-rom-type: US-LC2-disk-0MB-8MB +wtv-system-chipversion: 51511296 +User-Agent: Mozilla/4.0 WebTV/2.2.6.1 (compatible; MSIE 4.0) +wtv-encryption: true +wtv-script-id: 0 +wtv-script-mod: 0 + +` + +const net = require('net'); + +// Create a socket connection to localhost on port 1615 +const client = net.connect({ port: 1615, host: '127.0.0.1' }, () => { + console.log('Connected to localhost:1615'); + // Optionally, write data to the server + client.write(headers); +}); + +// Handle incoming data from the server +client.on('data', (chunk) => { + accumulatedBuffer = Buffer.concat([accumulatedBuffer, chunk]); + + // Look for the header delimiter in the accumulated buffer + const headerEndIndex = accumulatedBuffer.indexOf(headerDelimiter); + + if (headerEndIndex !== -1) { + // Split the buffer into headers and body + const headersBuffer = accumulatedBuffer.slice(0, headerEndIndex); + const bodyBuffer = accumulatedBuffer.slice(headerEndIndex + headerDelimiter.length); + + // Optionally, if you expect more body data in subsequent chunks, + // you can reset the accumulatedBuffer to only hold the current body + accumulatedBuffer = bodyBuffer; + } + + telly = new WTVTellyScript(accumulatedBuffer) + console.log(telly.packed_header) + console.log(telly.raw_data) + // Optionally, close the connection after receiving data + client.end(); +}); + +// Handle the connection close event +client.on('end', () => { + console.log('Disconnected from server'); +}); + +// Handle errors +client.on('error', (err) => { + console.error('Socket error:', err); +});