PLI: return the 7-byte location object, bound every proactive chain
release / release (push) Waiting to run
release / release (push) Waiting to run
The PLI answer used the 5-byte form 13 05 <MCC/MNC> <LAC> with LAC 0000 and no Cell ID. That is the *Network Rejection event download* form (TS 31.111 8.19.1); a PLI location for GERAN is 7 bytes - MCC/MNC, LAC and Cell ID. A card applet that re-reads its location (the Alfa MultiIMSI applet, after a *LOCI status change) treated it as empty and re-requested PLI on every STATUS tick. The default is now 13 07 00F110 0001 0001: PLMN 001/01 (the test network), LAC 0001, Cell ID 0001. _build_tr injects it after the Result; the TR data is pinned by a test. While verifying a live PLI, the manual /api/status-poll chain turned out to be unbounded: it looped on the PLI storm while holding _CARD_LOCK, so the request never returned and every card operation waited. _handle_proactive_chain's max_rounds now defaults to _POLL_CHAIN_MAX (the background poll always passed it; the manual poll, ENVELOPE, menu and TP chains did not), and the manual poll passes it explicitly. A card that re-queues a command can no longer wedge the card lock from any call site. Tests: the PLI default + the built TR, the default chain bound and the manual-poll call pin. 1061 Python + 1069 frontend; sw cache simple-v477.
This commit is contained in:
@@ -3592,9 +3592,12 @@ PLI_QUALIFIER_NAMES = {
|
||||
# specs define no contents for them ("reserved for 3GPP/3GPP2") and a
|
||||
# fabricated object would mislead the application more than no answer.
|
||||
PLI_DEFAULTS = {
|
||||
# Location Information (8.19): PLMN 001/01 (the test network, TS 23.003)
|
||||
# + LAC 0000
|
||||
0x00: '1305' + '00F110' + '0000',
|
||||
# Location Information (TS 31.111 8.19.1, the GERAN form a PLI answer
|
||||
# uses): PLMN 001/01 (the test network, TS 23.003) + LAC 0001 + Cell ID
|
||||
# 0001. Length 05 (no Cell ID) is the *Network Rejection event* form -
|
||||
# a PLI answer must carry the Cell ID (length 07), otherwise the location
|
||||
# reads as empty and a card applet may re-request it forever.
|
||||
0x00: '1307' + '00F110' + '0001' + '0001',
|
||||
# IMEI (8.20): the classic test IMEI 490154203237518, nibble-swapped
|
||||
# BCD with the odd 15th digit padded by F (TS 124 008 Mobile Identity)
|
||||
0x01: '1408' + '94104502237315F8',
|
||||
@@ -6608,15 +6611,18 @@ def _parse_setup_menu_items(raw):
|
||||
return _attach_nai(items, nai)
|
||||
|
||||
|
||||
def _handle_proactive_chain(scc, sw91, on_fetch=None, status_poll=True, max_rounds=None):
|
||||
def _handle_proactive_chain(scc, sw91, on_fetch=None, status_poll=True,
|
||||
max_rounds=_POLL_CHAIN_MAX):
|
||||
"""Run a FETCH/TERMINAL RESPONSE chain; marks the card as busy so that
|
||||
terminal-initiated ENVELOPEs (Data available, Channel status, timers) wait.
|
||||
``status_poll=False`` skips the trailing STATUS (used by the profile
|
||||
switch, where the card is mid-switch and must not be queried further).
|
||||
``max_rounds`` bounds the answers per call (the background poll passes
|
||||
_POLL_CHAIN_MAX so a card that re-queues a command cannot hold the card
|
||||
lock forever); ``_TEST_RUNNING`` aborts the chain before the next FETCH -
|
||||
a test run owns the card and the pending command stays for the script."""
|
||||
``max_rounds`` bounds the answers per call - the default is
|
||||
_POLL_CHAIN_MAX, so a card that re-queues a command (a chatty applet)
|
||||
cannot hold the card lock forever from *any* call site; a caller may pass
|
||||
a different bound. ``_TEST_RUNNING`` aborts the chain before the next
|
||||
FETCH - a test run owns the card and the pending command stays for the
|
||||
script."""
|
||||
global _PROACTIVE_BUSY
|
||||
_PROACTIVE_BUSY = True
|
||||
try:
|
||||
@@ -10032,7 +10038,7 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
sys.stderr.write('STATUS -> %s\n' % st_sw)
|
||||
resp = {'sw': st_sw}
|
||||
if st_sw.startswith('91'):
|
||||
_handle_proactive_chain(scc, st_sw)
|
||||
_handle_proactive_chain(scc, st_sw, max_rounds=_POLL_CHAIN_MAX)
|
||||
resp['proactive'] = True
|
||||
self._send_json(resp)
|
||||
self._log_resp(resp)
|
||||
|
||||
Reference in New Issue
Block a user