fix: drop stale STK dialogs, finish pending on TP re-send, mute client-gone (v3.6.35)
The live log showed the "stuck" state: after the menu watchdog (60 s)
answered a pending command, the PWA kept the panel; the next click got
{'error': 'no pending command'}, 400 and that reply was fed to the dialog
handler as if it were a card answer. A page reload then cancelled in-flight
polls, flooding the log with BrokenPipeError tracebacks.
- stkMenuRespond detects the already-answered reply (stkNoPendingError) and
closes the panel (stkMenuPanelReset) instead of treating it as an answer;
the 5 s status poll drops the panel whenever the server reports
pending: false, even when the Phone tab is hidden.
- /api/terminal-profile (POST) and /api/rescue finish a pending command
with a cancel TR first, so re-sending the TP can never shadow an
unanswered FETCH.
- _send_json and _serve_static swallow BrokenPipe/ConnectionReset/
ConnectionAborted with one "CLIENT GONE" line (a reload cancels polls);
the handlers' state changes still stand.
Tests: stkNoPendingError + the already-answered respond path; version
3.6.35; sw simple-v308; stylesheet rebuilt.
This commit is contained in:
@@ -31,7 +31,7 @@ from osmocom.tlv import BER_TLV_IE
|
||||
from osmocom.utils import rpad
|
||||
|
||||
|
||||
VERSION = '3.6.34'
|
||||
VERSION = '3.6.35'
|
||||
|
||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||
|
||||
@@ -5033,7 +5033,13 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(data, ensure_ascii=False).encode())
|
||||
try:
|
||||
self.wfile.write(json.dumps(data, ensure_ascii=False).encode())
|
||||
except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError):
|
||||
# The browser navigated away or reloaded while the response was in
|
||||
# flight (a cancelled poll): the request is done and the client is
|
||||
# gone - one line, no traceback (v3.6.35).
|
||||
sys.stderr.write('CLIENT GONE: %s %s\n' % (self.command, self.path))
|
||||
|
||||
def _read_body(self):
|
||||
length = int(self.headers.get('Content-Length', 0))
|
||||
@@ -5104,7 +5110,10 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
if last_modified:
|
||||
self.send_header('Last-Modified', last_modified)
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
try:
|
||||
self.wfile.write(data)
|
||||
except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError):
|
||||
sys.stderr.write('CLIENT GONE: GET %s\n' % rel)
|
||||
|
||||
def do_GET(self):
|
||||
if _test_request_blocked(self.path):
|
||||
@@ -5698,6 +5707,7 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
self._send_json({'error': 'no terminal profile configured'}, 400)
|
||||
self._log_resp({'error': 'no terminal profile configured'})
|
||||
return
|
||||
_finish_pending_menu(self.server, scc)
|
||||
sys.stderr.write('RESCUE: re-sending TERMINAL PROFILE\n')
|
||||
resp = _resend_terminal_profile(self.server, scc)
|
||||
self._send_json(resp)
|
||||
@@ -5722,6 +5732,9 @@ class PysimHandler(BaseHTTPRequestHandler):
|
||||
self._send_json({'error': 'no terminal profile configured'}, 400)
|
||||
self._log_resp({'error': 'no terminal profile configured'})
|
||||
return
|
||||
# Never re-send the TP while a FETCHed command awaits its
|
||||
# TERMINAL RESPONSE: answer it with a cancel TR first (v3.6.35).
|
||||
_finish_pending_menu(self.server, scc)
|
||||
sys.stderr.write('TERMINAL-PROFILE: re-sending %s\n' % self.server.terminal_profile)
|
||||
try:
|
||||
resp = _resend_terminal_profile(self.server, scc)
|
||||
|
||||
Reference in New Issue
Block a user