mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-19 08:33:56 -06:00
brightsign: read the server flag as an integer, not a Boolean
`if serverEnabled then` demands a genuine Boolean in BrightScript. ServerEnabled()
was declared As Boolean but branched on type() over ParseJSON output - "Boolean",
"Integer", "roInt", "String" - and none of those reliably produced one for a JSON 1.
The device took the whole file down with it:
Script runtime error: Type Mismatch. (runtime error &h18) in SSD:/autorun.brs(63)
Load or runtime error in autorun. Forcing recovery.
...and then looped through recovery, re-fetching autorun.zip - which contained the
same broken file, so recovery could not recover.
ServerEnabledFlag() returns 0 or 1 and the call sites compare explicitly. It finds
the setting by substring rather than by parsing, which is cruder and can be fooled
by a "server" key inside another string, but cannot mismatch a type. There is no
BrightScript interpreter on the machine this is written on, so every type guess
costs a boot cycle plus a recovery loop; a config file we write ourselves does not
justify that risk. Anything short of a clear yes stays a player.
Verified on XT245 URD3C6000823: clean boot, no runtime error, server up on :8181
45s after reboot, diagnostics screen showing the setup address.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014kfhrUPit5MCqxeTQyqr56
This commit is contained in:
parent
0b063cd415
commit
350cd31414
|
|
@ -53,14 +53,14 @@ Sub Main()
|
||||||
' server. Defaulting to on would mean every player that ever received this package started
|
' server. Defaulting to on would mean every player that ever received this package started
|
||||||
' listening on 8181, and the mistake would be invisible until two of them fought over the same
|
' listening on 8181, and the mistake would be invisible until two of them fought over the same
|
||||||
' displays. A device with no config file, an unreadable one, or one that says 0 stays a player.
|
' displays. A device with no config file, an unreadable one, or one that says 0 stays a player.
|
||||||
serverEnabled = ServerEnabled(root$)
|
serverFlag% = ServerEnabledFlag(root$)
|
||||||
print "[st-server] local server enabled: "; serverEnabled
|
print "[st-server] local server flag: "; serverFlag%
|
||||||
' Only three keys exist here: message_port, node_arguments, arguments. An invented `env:` key is
|
' Only three keys exist here: message_port, node_arguments, arguments. An invented `env:` key is
|
||||||
' what killed the first attempt at this file, with nothing but "Load or runtime error in
|
' what killed the first attempt at this file, with nothing but "Load or runtime error in
|
||||||
' autorun. Forcing recovery." to go on - and it sent me to the widget for the wrong reason.
|
' autorun. Forcing recovery." to go on - and it sent me to the widget for the wrong reason.
|
||||||
' Anything the server needs to be told goes in DATA_DIR/server.env, which it reads itself.
|
' Anything the server needs to be told goes in DATA_DIR/server.env, which it reads itself.
|
||||||
node = invalid
|
node = invalid
|
||||||
if serverEnabled then
|
if serverFlag% = 1 then
|
||||||
node = CreateObject("roNodeJs", "bs-server-boot.js", { message_port: msgPort })
|
node = CreateObject("roNodeJs", "bs-server-boot.js", { message_port: msgPort })
|
||||||
if node = invalid then
|
if node = invalid then
|
||||||
print "[st-server] FAILED: could not launch the node process"
|
print "[st-server] FAILED: could not launch the node process"
|
||||||
|
|
@ -84,7 +84,7 @@ Sub Main()
|
||||||
' Spelled out rather than casting the boolean: this file cannot be run anywhere but on the
|
' Spelled out rather than casting the boolean: this file cannot be run anywhere but on the
|
||||||
' player, so it is not the place for a clever conversion nobody can check.
|
' player, so it is not the place for a clever conversion nobody can check.
|
||||||
serverParam$ = "0"
|
serverParam$ = "0"
|
||||||
if serverEnabled then serverParam$ = "1"
|
if serverFlag% = 1 then serverParam$ = "1"
|
||||||
|
|
||||||
' NOTE what is NOT here: nodejs_enabled. The page no longer requires anything - it polls the
|
' NOTE what is NOT here: nodejs_enabled. The page no longer requires anything - it polls the
|
||||||
' server process over HTTP - so it can be an ordinary browser page. One less hybrid context.
|
' server process over HTTP - so it can be an ordinary browser page. One less hybrid context.
|
||||||
|
|
@ -133,38 +133,40 @@ End Sub
|
||||||
|
|
||||||
|
|
||||||
'*******************************************************************************************
|
'*******************************************************************************************
|
||||||
Function ServerEnabled(root$ As String) As Boolean
|
Function ServerEnabledFlag(root$ As String) As Integer
|
||||||
'*******************************************************************************************
|
'*******************************************************************************************
|
||||||
' st-config.json on the storage root, e.g. {"server": 1}
|
' Does st-config.json on the storage root say this device should host a server?
|
||||||
'
|
'
|
||||||
' Deliberately at the root rather than inside data/: it is what an operator drops in over the
|
' ⚠️ DELIBERATELY CRUDE, AND RETURNING AN INTEGER RATHER THAN A BOOLEAN.
|
||||||
' DWS, and autozip never writes it, so a re-provision cannot silently switch a site's server
|
|
||||||
' off - or on.
|
|
||||||
'
|
'
|
||||||
' Absent, unparseable, or anything other than an affirmative value means DISABLED. There is no
|
' The first version parsed the file with ParseJSON and branched on type(): "Boolean",
|
||||||
' reading of a broken config file that should end with a device deciding to host a server.
|
' "Integer", "roInt", "String". It cost a device a recovery loop -
|
||||||
txt$ = ReadAsciiFile(root$ + "/st-config.json")
|
'
|
||||||
if txt$ = "" then return false
|
' Script runtime error: Type Mismatch. (runtime error &h18) in SSD:/autorun.brs(63)
|
||||||
|
' Load or runtime error in autorun. Forcing recovery.
|
||||||
|
'
|
||||||
|
' - because `if x then` demands a genuine Boolean and none of those branches reliably produced
|
||||||
|
' one for a JSON 1. There is no BrightScript interpreter on the machine this was written on, so
|
||||||
|
' every guess about types costs a boot cycle AND leaves the device looping through recovery.
|
||||||
|
'
|
||||||
|
' A substring search cannot mismatch a type. It is less precise than a parser - a "server" key
|
||||||
|
' inside some other string would fool it - but this file has exactly one job, the file it reads
|
||||||
|
' is two lines long and written by us, and being unable to boot is far worse than being
|
||||||
|
' imprecise about a malformed config.
|
||||||
|
'
|
||||||
|
' Anything other than a clear yes returns 0. There is no reading of a broken config file that
|
||||||
|
' should end with a device deciding to host a server.
|
||||||
|
t = ReadAsciiFile(root$ + "/st-config.json")
|
||||||
|
if type(t) <> "String" and type(t) <> "roString" then return 0
|
||||||
|
|
||||||
cfg = ParseJSON(txt$)
|
low$ = LCase(t)
|
||||||
if cfg = invalid then
|
if Len(low$) = 0 then return 0
|
||||||
print "[st-server] st-config.json is not valid JSON - server stays disabled"
|
if Instr(1, low$, Chr(34) + "server" + Chr(34)) = 0 then return 0
|
||||||
return false
|
|
||||||
end if
|
|
||||||
if type(cfg) <> "roAssociativeArray" then return false
|
|
||||||
|
|
||||||
v = cfg.server
|
if Instr(1, low$, "true") > 0 then return 1
|
||||||
if v = invalid then return false
|
if Instr(1, low$, ": 1") > 0 then return 1
|
||||||
|
if Instr(1, low$, ":1") > 0 then return 1
|
||||||
' Accept the shapes a human actually writes: 1, true, "1", "true", "yes", "on".
|
return 0
|
||||||
if type(v) = "Boolean" then return v
|
|
||||||
if type(v) = "Integer" then return v <> 0
|
|
||||||
if type(v) = "roInt" then return v <> 0
|
|
||||||
if type(v) = "String" or type(v) = "roString" then
|
|
||||||
low$ = LCase(v)
|
|
||||||
return low$ = "1" or low$ = "true" or low$ = "yes" or low$ = "on"
|
|
||||||
end if
|
|
||||||
return false
|
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
'*******************************************************************************************
|
'*******************************************************************************************
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue