v3.24.0 review: the ARR cache on the startup init path
A card present when the server starts is initialized by the startup
path in __main__.py, which reads EF.ICCID and the network-state files
directly and never runs _apply_equipped_card - the only place the ARR
cache was read. The cache therefore stayed empty for the whole
session (/api/arr {ok: false}) and the file manager showed no access
rules until an explicit Equip.
The startup init now reads the ARR copies in the same CAT-free window
(best effort, right after the netstate read, skipped without a readable
ICCID like the other reads) and stores them as server.arr, with an
INIT: EF.ARR log line. A later equip still refreshes the cache through
_apply_equipped_card.
Test: the startup wiring (the read, the assignment and the import).
869 frontend + 857 Python; sw cache simple-v423.
This commit is contained in:
@@ -18,7 +18,7 @@ from . import presets
|
|||||||
from . import test_scripts
|
from . import test_scripts
|
||||||
from . import test_suites
|
from . import test_suites
|
||||||
from . import testscript
|
from . import testscript
|
||||||
from .server import PysimHandler, StderrApduTracer, _LoggingApduTracer, VERSION, _send_terminal_profile, _DefaultProactiveHandler, _handle_proactive_chain, _send_status, _init_proactive_session, _timing_on, _tlog, _set_menu_timeout, start_card_monitor, set_auto_equip, _read_iccid, _netstate_read, _netstate_install, _LineFilter, _test_command_type, migrate_scripts_to_suites
|
from .server import PysimHandler, StderrApduTracer, _LoggingApduTracer, VERSION, _send_terminal_profile, _DefaultProactiveHandler, _handle_proactive_chain, _send_status, _init_proactive_session, _timing_on, _tlog, _set_menu_timeout, start_card_monitor, set_auto_equip, _read_iccid, _read_arr, _netstate_read, _netstate_install, _LineFilter, _test_command_type, migrate_scripts_to_suites
|
||||||
|
|
||||||
|
|
||||||
_server_start = 0
|
_server_start = 0
|
||||||
@@ -220,6 +220,7 @@ def main():
|
|||||||
fastinit.install(app)
|
fastinit.install(app)
|
||||||
iccid = None
|
iccid = None
|
||||||
netstate_files = None
|
netstate_files = None
|
||||||
|
arr_files = None
|
||||||
if scc and card is not None and hasattr(scc, '_tp'):
|
if scc and card is not None and hasattr(scc, '_tp'):
|
||||||
scc._tp.apdu_tracer = _LoggingApduTracer()
|
scc._tp.apdu_tracer = _LoggingApduTracer()
|
||||||
try:
|
try:
|
||||||
@@ -235,6 +236,13 @@ def main():
|
|||||||
netstate_files = _netstate_read(app)
|
netstate_files = _netstate_read(app)
|
||||||
except Exception:
|
except Exception:
|
||||||
netstate_files = None
|
netstate_files = None
|
||||||
|
# EF.ARR (the FCP '8B' references): read here too - a card
|
||||||
|
# present at server start never runs _apply_equipped_card,
|
||||||
|
# which owns this read on a later equip.
|
||||||
|
arr_files = _read_arr(app)
|
||||||
|
if arr_files:
|
||||||
|
sys.stderr.write('INIT: EF.ARR %s\n' % ', '.join(
|
||||||
|
'%s (%d rec)' % (a['fid'], a['num_records']) for a in arr_files))
|
||||||
t_phase = time.time()
|
t_phase = time.time()
|
||||||
sys.stderr.write('INIT: sending TERMINAL PROFILE %s (CLA=%s)\n' % (opts.terminal_profile, scc.cat_cla))
|
sys.stderr.write('INIT: sending TERMINAL PROFILE %s (CLA=%s)\n' % (opts.terminal_profile, scc.cat_cla))
|
||||||
sm, el = _send_terminal_profile(scc, opts.terminal_profile)
|
sm, el = _send_terminal_profile(scc, opts.terminal_profile)
|
||||||
@@ -317,6 +325,9 @@ def main():
|
|||||||
server.card_present = card is not None
|
server.card_present = card is not None
|
||||||
server.card_session = 1 if card is not None else 0
|
server.card_session = 1 if card is not None else 0
|
||||||
server.iccid = iccid
|
server.iccid = iccid
|
||||||
|
# EF.ARR cache (v3.24.0): read by the startup init above (a card present
|
||||||
|
# at server start); a later equip refreshes it in _apply_equipped_card.
|
||||||
|
server.arr = arr_files
|
||||||
# Network state monitor: install the state read during the startup init
|
# Network state monitor: install the state read during the startup init
|
||||||
# (right after the ICCID, before the TERMINAL PROFILE). No readable
|
# (right after the ICCID, before the TERMINAL PROFILE). No readable
|
||||||
# ICCID means the card is considered unusable - give up.
|
# ICCID means the card is considered unusable - give up.
|
||||||
|
|||||||
@@ -147,6 +147,16 @@ class CacheTests(unittest.TestCase):
|
|||||||
seg = SRC[SRC.index("elif self.path == '/api/write':"):SRC.index("elif self.path == '/api/tree':")]
|
seg = SRC[SRC.index("elif self.path == '/api/write':"):SRC.index("elif self.path == '/api/tree':")]
|
||||||
self.assertIn('_arr_refresh_after_write', seg)
|
self.assertIn('_arr_refresh_after_write', seg)
|
||||||
|
|
||||||
|
def test_the_startup_init_reads_the_arr(self):
|
||||||
|
# a card present at server start never runs _apply_equipped_card, so
|
||||||
|
# the startup init reads the ARR in its own CAT-free window (v3.24.0
|
||||||
|
# review - the cache was empty on a startup-equipped card)
|
||||||
|
src = (ROOT / 'pysim_simple_server' / '__main__.py').read_text(encoding='utf-8')
|
||||||
|
self.assertIn('arr_files = _read_arr(app)', src)
|
||||||
|
self.assertIn('server.arr = arr_files', src)
|
||||||
|
imp = src[src.index('from .server import'):]
|
||||||
|
self.assertIn('_read_arr', imp[:imp.index('\n')])
|
||||||
|
|
||||||
|
|
||||||
class ArrRouteTests(unittest.TestCase):
|
class ArrRouteTests(unittest.TestCase):
|
||||||
"""GET /api/arr serves the session cache without touching the card."""
|
"""GET /api/arr serves the session cache without touching the card."""
|
||||||
|
|||||||
Reference in New Issue
Block a user