diff --git a/README.md b/README.md index 344b478..7581699 100644 --- a/README.md +++ b/README.md @@ -738,9 +738,9 @@ The bundled Python server wraps [pySim](https://osmocom.org/projects/pysim/wiki) ### Prerequisites -- **Python 3.9+** with `pip`, and **Git** +- **Python 3.9+** with `pip`, and **Git** — the app runs on 3.9+, but the **SCP81 TLS-PSK listener needs Python 3.13+** (`ssl`'s PSK callbacks). - **Smart card reader** (PC/SC or serial/FTDI) — PC/SC is preferable (`pcsc-lite` + `ccid` on Linux). `pyscard` has no Linux wheels, so it builds from source: install the PC/SC header package too (`libpcsclite-dev` on Debian/Ubuntu, `pcsc-lite-devel` on Fedora; on Arch `pcsclite` includes them). -- **Windows** — use Python 3.9–3.13 (3.13 recommended): `pyscard` ships precompiled wheels for these versions. On 3.14 it builds from source (needs MSVC C++ Build Tools). The SMPP bridge (`smpp.twisted3`) is intentionally skipped on Windows. +- **Windows** — use **Python 3.13 (strongly recommended)**: `pyscard` has precompiled wheels up to 3.13 and the SCP81 TLS-PSK listener needs 3.13+. On 3.14 `pyscard` and some pysim dependency wheels are not available and build from source (needs MSVC C++ Build Tools). 3.9–3.12 run the app but not the SCP81 PSK listener. The SMPP bridge (`smpp.twisted3`) is intentionally skipped on Windows. ### Scripts diff --git a/README_RUS.md b/README_RUS.md index 69c63ff..29e2211 100644 --- a/README_RUS.md +++ b/README_RUS.md @@ -722,9 +722,9 @@ PWA проверяет версию сервера при подключении ### Требования -- **Python 3.9+** с `pip`, и **Git** +- **Python 3.9+** с `pip`, и **Git** — приложение работает на 3.9+, но **SCP81 TLS-PSK-слушателю нужен Python 3.13+** (PSK-callback'и `ssl`). - **Смарт-картридер** (PC/SC или serial/FTDI) — предпочтителен PC/SC (`pcsc-lite` + `ccid` на Linux). У `pyscard` нет Linux-wheel, поэтому он собирается из исходников: поставьте и пакет с заголовками PC/SC (`libpcsclite-dev` в Debian/Ubuntu, `pcsc-lite-devel` в Fedora; в Arch они входят в `pcsclite`). -- **Windows** — используйте Python 3.9–3.13 (рекомендуется 3.13): у `pyscard` есть готовые wheel. На 3.14 он собирается из исходников (нужны MSVC C++ Build Tools). SMPP-мост (`smpp.twisted3`) в Windows сознательно не ставится. +- **Windows** — используйте **Python 3.13 (настоятельно рекомендуется)**: у `pyscard` есть готовые wheel до 3.13, и SCP81 TLS-PSK-слушателю нужен 3.13+. На 3.14 wheel для `pyscard` и части зависимостей pysim отсутствуют, они собираются из исходников (нужны MSVC C++ Build Tools). 3.9–3.12 запускают приложение, но не SCP81 PSK-слушатель. SMPP-мост (`smpp.twisted3`) в Windows сознательно не ставится. ### Скрипты diff --git a/frontend/index.html b/frontend/index.html index 9821436..1e253a2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1943,7 +1943,7 @@ // ===== Version ===== // Single source of truth for the PWA version: shown in the header and used // by the server version check in pysimConnect(). -const SIMPLE_VERSION = '3.31.1'; +const SIMPLE_VERSION = '3.31.2'; document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION; // ===== view history (the browser Back/Forward buttons) ===== diff --git a/frontend/sw.js b/frontend/sw.js index b797ecb..fabc654 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'simple-v456'; +const CACHE = 'simple-v457'; const URLS = [ 'index.html', 'help.html', diff --git a/pyproject.toml b/pyproject.toml index 73a712f..708ae9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pysim-simple-server" -version = "3.31.1" +version = "3.31.2" description = "HTTP REST server wrapping pysim for the SIMple PWA" license = { text = "GPL-2.0-or-later" } requires-python = ">=3.9" diff --git a/pysim_simple_server/scp81.py b/pysim_simple_server/scp81.py index c031517..9d61798 100644 --- a/pysim_simple_server/scp81.py +++ b/pysim_simple_server/scp81.py @@ -18,6 +18,7 @@ DATA records to it. import socket import ssl +import sys import threading import time @@ -252,6 +253,11 @@ class PskTlsServer: # SSLV3_ALERT_UNEXPECTED_MESSAGE on the post-handshake # NewSessionTicket record (verified live 2026-09-15). ctx.options |= ssl.OP_NO_TICKET + if not hasattr(ctx, 'set_psk_server_callback'): + # ssl's TLS-PSK callbacks exist only since Python 3.13. + raise RuntimeError( + 'TLS-PSK requires Python 3.13+ (ssl.SSLContext.set_psk_server_callback ' + 'is missing in %s)' % sys.version.split()[0]) ctx.set_psk_server_callback(self._psk_cb) return ctx diff --git a/pysim_simple_server/server.py b/pysim_simple_server/server.py index c562f44..a5c8dc6 100644 --- a/pysim_simple_server/server.py +++ b/pysim_simple_server/server.py @@ -37,7 +37,7 @@ from osmocom.tlv import BER_TLV_IE from osmocom.utils import rpad -VERSION = '3.31.1' +VERSION = '3.31.2' MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE diff --git a/setup.bat b/setup.bat index b807ffa..df1ec84 100644 --- a/setup.bat +++ b/setup.bat @@ -44,11 +44,14 @@ call "%VENV_DIR%\Scripts\activate.bat" REM Upgrade pip python -m pip install --upgrade pip -q -REM pyscard has precompiled wheels for Python 3.9-3.13. -REM On Python 3.14 pip builds it from source (requires Microsoft C++ Build Tools). -echo Note: pyscard ships precompiled wheels for Python 3.9-3.13. -echo Python 3.14 will build pyscard from source and require -echo Microsoft C++ Build Tools ("Desktop development with C++"). +REM Python 3.13 is strongly recommended: pyscard ships precompiled wheels up +REM to 3.13, the SCP81 TLS-PSK listener needs 3.13+, and on 3.14 pyscard and +REM some pysim dependency wheels are unavailable (source builds need MSVC). +echo Note: Python 3.13 is strongly recommended. +echo pyscard has precompiled wheels up to 3.13 and the SCP81 TLS-PSK +echo listener needs 3.13+. On Python 3.14 pyscard and some pysim +echo dependency wheels are unavailable; those build from source and +echo require Microsoft C++ Build Tools ("Desktop development with C++"). echo. REM Install pysim dependencies first, then pysim itself (without the SMPP diff --git a/setup.sh b/setup.sh index 88e785f..b448c06 100755 --- a/setup.sh +++ b/setup.sh @@ -52,6 +52,14 @@ else echo " Fedora: sudo dnf install pcsc-lite pcsc-lite-ccid pcsc-lite-devel" fi +# The SCP81 TLS-PSK listener uses ssl's PSK callbacks, added in Python 3.13. +PY_MINOR=$(echo "$PY_VER" | cut -d. -f2) +if [ "${PY_VER%.*}" = "3" ] && [ "$PY_MINOR" -lt 13 ]; then + echo "Note: the SCP81 TLS-PSK listener needs Python 3.13+ (this is $PY_VER);" + echo " the rest of the app works normally." + echo "" +fi + echo "" echo "=== Setup complete ===" echo "Run ./start.sh to start the server." \ No newline at end of file diff --git a/tests/test_scp81.py b/tests/test_scp81.py index 18a5b03..7cddda3 100644 --- a/tests/test_scp81.py +++ b/tests/test_scp81.py @@ -5,6 +5,7 @@ terminal's Data available notification (TS 102 223 7.5.10). Synthetic PSK only; no live card data. """ +import inspect import socket import ssl import sys @@ -80,6 +81,18 @@ class HttpParseTest(unittest.TestCase): self.assertTrue(body.startswith(b'64\r\n')) +class PskGuardTest(unittest.TestCase): + """On Python < 3.13 the listener must explain the requirement, not raise + AttributeError (the PSK tests themselves are skipped there).""" + + def test_the_context_names_the_python_requirement(self): + src = inspect.getsource(scp81.PskTlsServer._make_context) + self.assertIn("hasattr(ctx, 'set_psk_server_callback')", src) + self.assertIn('Python 3.13+', src) + + +@unittest.skipUnless(hasattr(ssl.SSLContext, 'set_psk_server_callback'), + 'TLS-PSK requires Python 3.13+') class PskTlsServerTest(unittest.TestCase): def _client_ctx(self, identity=IDENT, psk=PSK): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)