4 Commits
Author SHA1 Message Date
catarrh 50dba20f04 README: add SIMple as a GSMTAP-SIM source to the diagram
SIMple can stream its own ISO 7816 APDUs as GSMTAP-SIM packets (its --gsmtap
option), so it belongs beside the sniffers and the sigrok decoder.  The
diagrams get a compact SIMple block between the SIMtrace2 sniffers and the
sigrok_iso7816_stream boxes (they do not move): title SIMple, subtitle
"APDU -> GSMTAP", and its own arrow into the UDP :4729 listener.  It is
deliberately smaller than the primary sniffers, matching its role as a
secondary source.

The README alt text and the gsmtap capture-mode bullet/comment now list SIMple
as a source too (linked to its repository in the bullet).

Both languages; 558 Python + 80 Node tests; runtime zip rebuilt with the
updated diagrams.
2026-10-28 12:36:38 +03:00
catarrh f492f29ea6 README: correct the architecture diagram's capture paths
The diagrams conflated the SIMtrace2 hardware with the sniffer that reads it
and omitted the original Osmocom simtrace2-sniff: they showed
simtrace2-pysniff feeding the GSMTAP listener with the hardware only as its
subtitle, and a second, unexplained "SIMtrace2 hardware / direct USB" box.

The diagrams now show the device -> sniffer -> GSMTAP relationship explicitly:
SIMtrace2 hardware is read either by simtrace2-pysniff or by the original
simtrace2-sniff, and FX2 hardware by the sigrok_iso7816_stream decoder; the
sniffers/decoder stream GSMTAP-SIM to the UDP :4729 listener.  The direct USB
path is drawn separately from the device to the server and is labelled
"pysniff code in-process": --capture direct uses the bundled
simtrace2_pysniff package (DirectSniffer -> SniffSession) inside the server
process, not the simtrace2-pysniff CLI, and bypasses GSMTAP.  PCAP/COMPRION
import, SQLite and the browser UI keep their places.

The READMEs' alt text, the first-run capture-mode notes and the Usage command
comments now name the original simtrace2-sniff as a GSMTAP source and say the
direct mode runs the bundled sniffer code inside the server.

Both languages; 558 Python + 80 Node tests; runtime zip still carries both
diagrams and the README image guard passes.
2026-10-28 01:46:13 +03:00
catarrh 2b83d21e64 README: add architecture diagrams (EN/RU)
Both READMEs gain a capture-and-analysis diagram right under the screenshot:
simtrace2-pysniff and sigrok_iso7816_stream feed the GSMTAP UDP :4729
listener, SIMtrace2 hardware can be read directly over USB, PCAP/COMPRION
traces come from files, and simtrace-analyser-server decodes/stores into
SQLite and serves the web UI.  The SVGs carry title/desc and role=img, use
only inline presentation attributes (no scripts, no external refs) and render
without clipped text; the RU text matches the EN layout.

The runtime zip includes both diagrams so the embedded READMEs keep working,
and a new drift guard checks that every image a README references is present
in the archive.  RU wording: "устанавливаемое PWA" (neuter agreement).

558 Python + 80 Node tests.
2026-10-28 00:36:26 +03:00
catarrh 9a661f5ab2 README: expand the title, move the news line up, update Related tools
The heading now names the tool and what it analyses instead of just the
product name, and the news/website line sits right under the language switch
so it is visible before the description.

The Related section became "Related tools" with the same family block the
sibling projects use (SIMple, SIMtrace Analyser, sigrok_iso7816_stream on one
website and news channel), and simtrace2 is mentioned as the upstream
hardware/firmware the bundled capture utility sniffs from.  One wording tweak:
the capture-liveness paragraph states the current behaviour ("does not
pollute") instead of describing it as a change ("no longer pollutes").

Both languages; docs only, 557 Python + 80 Node tests.
2026-10-27 23:38:43 +03:00
6 changed files with 233 additions and 29 deletions

No files matched your search

+30 -14
View File
@@ -1,7 +1,9 @@
# SIMtrace Analyser
# SIMtrace Analyser — an APDU trace analyser for GSMTAP-SIM captures
English | [Русский](README_RUS.md)
📢 Project news and updates: [website](https://atroshin.ru) · [Telegram channel](https://t.me/youeyeseesee)
APDU trace analyser for the GSMTAP-SIM format — captures SIM/UICC
communication from a UDP GSMTAP stream (or imports PCAP/PCAPNG files),
decodes it, and serves an installable web app for browsing. The repository
@@ -9,10 +11,10 @@ also bundles **simtrace2-pysniff**, a Python replacement for
`simtrace2-sniff` that captures from Osmocom SIMtrace2 hardware and can feed
GSMTAP into this analyser.
📢 Project news and updates: [atroshin.ru](https://atroshin.ru) | [Telegram channel](https://t.me/youeyeseesee)
![SIMtrace Analyser UI](frontend.png)
![Capture and analysis: SIMtrace2 hardware is read by simtrace2-pysniff or the original simtrace2-sniff, and FX2 hardware by the sigrok_iso7816_stream decoder; the sniffers, the decoder and SIMple stream GSMTAP-SIM to the UDP :4729 listener. The server can also read SIMtrace2 hardware directly over USB with the bundled pysniff code in-process, and imports PCAP/COMPRION traces from files. simtrace-analyser-server decodes and stores the traffic in SQLite and serves the web UI](architecture_en.svg)
## Prerequisites
**Required**
@@ -113,9 +115,11 @@ simtrace-analyser-server --capture gsmtap
Open **http://127.0.0.1:8081/** in a browser. `Ctrl+C` stops the server.
- `--capture gsmtap` (default) — listen for GSMTAP-SIM on UDP 4729, e.g. from
`simtrace2-pysniff` or `sigrok_iso7816_stream`;
- `--capture direct` — read SIMtrace2 hardware directly (needs PyUSB; Windows
also needs the driver swap, see [USB Device Access](#usb-device-access));
`simtrace2-pysniff`, the original `simtrace2-sniff`,
`sigrok_iso7816_stream` or [SIMple](https://github.com/anttro/simple);
- `--capture direct` — read SIMtrace2 hardware directly (the bundled sniffer
code runs inside the server and talks to the device over USB; needs PyUSB;
Windows also needs the driver swap, see [USB Device Access](#usb-device-access));
- `--capture disabled` — only browse stored captures.
The full runtime guide (server options, the UI views, the capture utility) is
@@ -131,10 +135,12 @@ bundled into the package on install) on the same origin. Three capture
modes:
```sh
# Listen for GSMTAP from simtrace2-pysniff (or original simtrace2-sniff):
# Listen for GSMTAP from simtrace2-pysniff, the original simtrace2-sniff,
# sigrok_iso7816_stream or SIMple:
simtrace-analyser-server --capture gsmtap
# Capture directly from SIMtrace2 hardware (no external tool needed):
# Capture directly from SIMtrace2 hardware (the bundled sniffer code reads the
# device; no external tool, no GSMTAP):
simtrace-analyser-server --capture direct
# Browse/analyse existing captures without a capture backend:
@@ -171,7 +177,7 @@ datagram is dropped and counted (`dropped`) rather than silently
killing the capture; a `tpdu` packet that is not APDU-shaped at all
(shorter than the header, the invalid CLA `FF` or an ISO-reserved class)
is skipped and counted (`skipped`) — a character-level or mis-sampled
stream no longer pollutes the decode. The heartbeat interval defaults to 60 s and is
stream does not pollute the decode. The heartbeat interval defaults to 60 s and is
tunable via `--log-interval SECONDS`.
The GSMTAP listener also accepts the **sigrok-iso7816-stream** decoder
@@ -553,13 +559,23 @@ prompt).
- Installable **PWA** (progressive web app: installs to the desktop or home
screen and works offline), dark theme, English/Russian UI
## Related
## Related tools
- **[simtrace2](https://gitea.osmocom.org/sim-card/simtrace2)** — the upstream
SIMtrace2 hardware/firmware project that the capture utility sniffs from.
SIMple, SIMtrace Analyser and sigrok_iso7816_stream are three standalone
tools for working with SIM/UICC cards, published together on the same
[website](https://atroshin.ru) and [news channel](https://t.me/youeyeseesee).
Each one is fully independent — install only the tools you need:
- **[SIMple](https://github.com/anttro/simple)** — a UICC workbench: APDU
construction, SCP80/SCP81 OTA, SIM Toolkit simulation and card profiling.
- **[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser)** — an
APDU trace analyser for GSMTAP-SIM captures.
- **[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)** —
FX2LP-based passive ISO 7816 sniffer that emits the same GSMTAP-SIM stream
on UDP 4729 (accepted by this project's GSMTAP listener).
a passive ISO 7816 sniffer built on a cheap FX2 logic analyser.
The bundled capture utility also sniffs from the upstream
[simtrace2](https://gitea.osmocom.org/sim-card/simtrace2) hardware/firmware
project.
## License
+30 -15
View File
@@ -1,7 +1,9 @@
# SIMtrace Analyser
# SIMtrace Analyser — анализатор APDU-трассировок GSMTAP-SIM
[English](README.md) | Русский
📢 Новости и обновления проекта: [сайт](https://atroshin.ru) · [Telegram-канал](https://t.me/youeyeseesee)
Анализатор APDU-трассировок в формате GSMTAP-SIM — захватывает обмен с
SIM/UICC из UDP-потока GSMTAP (или импортирует файлы PCAP/PCAPNG),
декодирует его и отдаёт устанавливаемое веб-приложение для просмотра.
@@ -9,10 +11,10 @@ SIM/UICC из UDP-потока GSMTAP (или импортирует файлы
на Python, которая захватывает трафик с оборудования Osmocom SIMtrace2
и может передавать GSMTAP этому анализатору.
📢 Новости и обновления проекта: [atroshin.ru](https://atroshin.ru) | [Telegram-канал](https://t.me/youeyeseesee)
![Интерфейс SIMtrace Analyser](frontend.png)
![Захват и анализ: оборудование SIMtrace2 читает simtrace2-pysniff или оригинальный simtrace2-sniff, а оборудование FX2 — декодер sigrok_iso7816_stream; они и SIMple передают GSMTAP-SIM слушателю UDP :4729. Сервер также может читать оборудование SIMtrace2 напрямую по USB встроенным кодом pysniff внутри сервера и импортирует трассы PCAP/COMPRION из файлов. simtrace-analyser-server декодирует и сохраняет трафик в SQLite и раздаёт веб-интерфейс](architecture_ru.svg)
## Требования
**Обязательно**
@@ -115,9 +117,11 @@ simtrace-analyser-server --capture gsmtap
сервер.
- `--capture gsmtap` (по умолчанию) — слушать GSMTAP-SIM на UDP 4729,
например от `simtrace2-pysniff` или `sigrok_iso7816_stream`;
- `--capture direct` — читать оборудование SIMtrace2 напрямую (нужен PyUSB; в
Windows также нужна замена драйвера, см.
например от `simtrace2-pysniff`, оригинального `simtrace2-sniff`,
`sigrok_iso7816_stream` или [SIMple](https://github.com/anttro/simple);
- `--capture direct` — читать оборудование SIMtrace2 напрямую (встроенный код
сниффера работает внутри сервера и обращается к устройству по USB; нужен
PyUSB; в Windows также нужна замена драйвера, см.
[Доступ к USB-устройству](#доступ-к-usb-устройству));
- `--capture disabled` — только просмотр сохранённых захватов.
@@ -134,10 +138,12 @@ simtrace-analyser-server --capture gsmtap
Три режима захвата:
```sh
# Слушать GSMTAP от simtrace2-pysniff (или оригинального simtrace2-sniff):
# Слушать GSMTAP от simtrace2-pysniff, оригинального simtrace2-sniff,
# sigrok_iso7816_stream или SIMple:
simtrace-analyser-server --capture gsmtap
# Захват напрямую с оборудования SIMtrace2 (внешний инструмент не нужен):
# Захват напрямую с оборудования SIMtrace2 (встроенный код сниффера читает
# устройство; внешний инструмент и GSMTAP не нужны):
simtrace-analyser-server --capture direct
# Просмотр/анализ существующих записей без бэкенда захвата:
@@ -174,7 +180,7 @@ heartbeat `Capture alive: session=N messages=M bytes=B dropped=D skipped=S`
убивают захват; `tpdu`-пакет, вовсе не похожий на APDU (короче заголовка,
недопустимый CLA `FF` или зарезервированный ISO класс `001x`),
пропускается и считается (`skipped`) — посимвольный или миссемплированный
поток больше не засоряет декодирование. Интервал heartbeat по умолчанию
поток не засоряет декодирование. Интервал heartbeat по умолчанию
60 с, настраивается через `--log-interval SECONDS`.
GSMTAP-листенер также принимает декодер **sigrok-iso7816-stream**
@@ -568,14 +574,23 @@ Python 3 должен быть в `PATH` (проверьте `python --version`
- **PWA** (progressive web app): устанавливается на рабочий стол или домашний
экран и работает офлайн; тёмная тема, интерфейс на английском/русском
## Связанные проекты
## Связанные инструменты
- **[simtrace2](https://gitea.osmocom.org/sim-card/simtrace2)** — вышестоящий
проект оборудования/прошивки SIMtrace2, с которого утилита захвата
снимает трафик.
SIMple, SIMtrace Analyser и sigrok_iso7816_stream — три автономных
инструмента для работы с SIM/UICC-картами, представленные на одном
[сайте](https://atroshin.ru) и в одном [Telegram-канале](https://t.me/youeyeseesee).
Каждый полностью независим — устанавливайте только нужные вам:
- **[SIMple](https://github.com/anttro/simple)** — мастерская для UICC/SIM:
конструкторы APDU, OTA SCP80/SCP81, симуляция SIM Toolkit и профилирование
карт.
- **[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser)** —
анализатор APDU-трассировок GSMTAP-SIM.
- **[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)** —
пассивный ISO 7816 сниффер на базе FX2LP, выдающий такой же поток
GSMTAP-SIM на UDP 4729 (принимается GSMTAP-листенером этого проекта).
пассивный ISO 7816-сниффер на дешёвом логическом анализаторе FX2.
Встроенная утилита захвата также снимает трафик с вышестоящего проекта
оборудования/прошивки [simtrace2](https://gitea.osmocom.org/sim-card/simtrace2).
## Лицензия
+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="640" viewBox="0 0 960 640" role="img" aria-labelledby="diagram-title diagram-desc" font-family="'Segoe UI', 'Helvetica Neue', Arial, 'DejaVu Sans', sans-serif">
<title id="diagram-title">SIMtrace Analyser: capture and analysis</title>
<desc id="diagram-desc">SIMtrace2 hardware is read by simtrace2-pysniff (bundled) or the original simtrace2-sniff, and FX2 hardware by the sigrok_iso7816_stream decoder; the sniffers, the decoder and SIMple stream GSMTAP-SIM to the listener on UDP :4729. The server can also read SIMtrace2 hardware directly over USB with the bundled sniffer code, and imports PCAP/COMPRION traces from files. simtrace-analyser-server decodes and stores the traffic in SQLite and serves the web UI.</desc>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 Z" fill="#64748b"/>
</marker>
</defs>
<rect x="1" y="1" width="958" height="638" rx="18" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.5"/>
<text x="480" y="30" text-anchor="middle" font-size="14" fill="#475569">capture → analyse</text>
<!-- capture devices -->
<rect x="100" y="48" width="250" height="64" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="225" y="74" text-anchor="middle" font-size="15" font-weight="600" fill="#0f172a">SIMtrace2 hardware</text>
<text x="225" y="94" text-anchor="middle" font-size="12" fill="#475569">Osmocom USB sniffer</text>
<rect x="610" y="48" width="250" height="64" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="735" y="74" text-anchor="middle" font-size="15" font-weight="600" fill="#0f172a">FX2 logic analyzer</text>
<text x="735" y="94" text-anchor="middle" font-size="12" fill="#475569">Saleae clone</text>
<line x1="225" y1="112" x2="225" y2="148" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="735" y1="112" x2="735" y2="148" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- sniffers -->
<rect x="100" y="150" width="250" height="96" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
<text x="225" y="176" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a">SIMtrace2 sniffers</text>
<text x="225" y="202" text-anchor="middle" font-size="13" fill="#334155" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace2-pysniff</text>
<text x="225" y="224" text-anchor="middle" font-size="13" fill="#334155" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace2-sniff (Osmocom)</text>
<rect x="610" y="150" width="250" height="96" rx="12" fill="#f5f3ff" stroke="#c4b5fd" stroke-width="1.5"/>
<text x="735" y="190" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">sigrok_iso7816_stream</text>
<text x="735" y="212" text-anchor="middle" font-size="13" fill="#475569">decoder</text>
<!-- a secondary GSMTAP-SIM source: SIMple can stream its APDUs -->
<rect x="395" y="166" width="170" height="64" rx="12" fill="#ecfeff" stroke="#a5f3fc" stroke-width="1.5"/>
<text x="480" y="192" text-anchor="middle" font-size="16" font-weight="600" fill="#0f172a">SIMple</text>
<text x="480" y="212" text-anchor="middle" font-size="12" fill="#475569">APDU → GSMTAP</text>
<line x1="225" y1="246" x2="425" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="480" y1="230" x2="480" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="735" y1="246" x2="535" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- GSMTAP listener -->
<rect x="350" y="280" width="260" height="72" rx="12" fill="#fffbeb" stroke="#fcd34d" stroke-width="1.5"/>
<text x="480" y="310" text-anchor="middle" font-size="16" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">GSMTAP UDP :4729</text>
<text x="480" y="332" text-anchor="middle" font-size="13" fill="#475569">listener</text>
<!-- file import -->
<rect x="650" y="280" width="240" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="770" y="310" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a">PCAP / COMPRION</text>
<text x="770" y="332" text-anchor="middle" font-size="13" fill="#475569">import from files</text>
<line x1="480" y1="352" x2="480" y2="390" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="770" y1="352" x2="635" y2="390" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- the direct USB path bypasses the sniffers and GSMTAP -->
<path d="M100 84 H52 V448 H258" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
<text x="64" y="418" font-size="12" font-weight="600" fill="#475569">direct USB</text>
<text x="64" y="436" font-size="12" fill="#475569">pysniff code in-process</text>
<!-- analysis server -->
<rect x="260" y="392" width="440" height="84" rx="12" fill="#ecfdf5" stroke="#6ee7b7" stroke-width="1.5"/>
<text x="480" y="427" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace-analyser-server</text>
<text x="480" y="451" text-anchor="middle" font-size="13" fill="#475569">decodes · stores</text>
<line x1="400" y1="476" x2="250" y2="514" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="560" y1="476" x2="710" y2="514" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- storage and UI -->
<rect x="110" y="516" width="280" height="76" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="250" y="548" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">SQLite</text>
<text x="250" y="570" text-anchor="middle" font-size="13" fill="#475569">sessions.db</text>
<rect x="570" y="516" width="280" height="76" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="710" y="548" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">Browser (web UI)</text>
<text x="710" y="570" text-anchor="middle" font-size="13" fill="#475569">installable PWA</text>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="640" viewBox="0 0 960 640" role="img" aria-labelledby="diagram-title diagram-desc" font-family="'Segoe UI', 'Helvetica Neue', Arial, 'DejaVu Sans', sans-serif">
<title id="diagram-title">SIMtrace Analyser: захват и анализ</title>
<desc id="diagram-desc">Оборудование SIMtrace2 читает simtrace2-pysniff (входит в комплект) или оригинальный simtrace2-sniff, а оборудование FX2 — декодер sigrok_iso7816_stream; они и SIMple передают GSMTAP-SIM слушателю UDP :4729. Сервер также может читать оборудование SIMtrace2 напрямую по USB встроенным кодом сниффера и импортирует трассы PCAP/COMPRION из файлов. simtrace-analyser-server декодирует и сохраняет трафик в SQLite и раздаёт веб-интерфейс.</desc>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 Z" fill="#64748b"/>
</marker>
</defs>
<rect x="1" y="1" width="958" height="638" rx="18" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.5"/>
<text x="480" y="30" text-anchor="middle" font-size="14" fill="#475569">захват → анализ</text>
<!-- устройства захвата -->
<rect x="100" y="48" width="250" height="64" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="225" y="74" text-anchor="middle" font-size="15" font-weight="600" fill="#0f172a">Оборудование SIMtrace2</text>
<text x="225" y="94" text-anchor="middle" font-size="12" fill="#475569">USB-сниффер Osmocom</text>
<rect x="610" y="48" width="250" height="64" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="735" y="74" text-anchor="middle" font-size="15" font-weight="600" fill="#0f172a">Логический анализатор FX2</text>
<text x="735" y="94" text-anchor="middle" font-size="12" fill="#475569">клон Saleae</text>
<line x1="225" y1="112" x2="225" y2="148" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="735" y1="112" x2="735" y2="148" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- снифферы -->
<rect x="100" y="150" width="250" height="96" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
<text x="225" y="176" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a">Снифферы SIMtrace2</text>
<text x="225" y="202" text-anchor="middle" font-size="13" fill="#334155" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace2-pysniff</text>
<text x="225" y="224" text-anchor="middle" font-size="13" fill="#334155" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace2-sniff (Osmocom)</text>
<rect x="610" y="150" width="250" height="96" rx="12" fill="#f5f3ff" stroke="#c4b5fd" stroke-width="1.5"/>
<text x="735" y="190" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">sigrok_iso7816_stream</text>
<text x="735" y="212" text-anchor="middle" font-size="13" fill="#475569">декодер</text>
<!-- второй источник GSMTAP-SIM: SIMple умеет отдавать свои APDU -->
<rect x="395" y="166" width="170" height="64" rx="12" fill="#ecfeff" stroke="#a5f3fc" stroke-width="1.5"/>
<text x="480" y="192" text-anchor="middle" font-size="16" font-weight="600" fill="#0f172a">SIMple</text>
<text x="480" y="212" text-anchor="middle" font-size="12" fill="#475569">APDU → GSMTAP</text>
<line x1="225" y1="246" x2="425" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="480" y1="230" x2="480" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="735" y1="246" x2="535" y2="278" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- слушатель GSMTAP -->
<rect x="350" y="280" width="260" height="72" rx="12" fill="#fffbeb" stroke="#fcd34d" stroke-width="1.5"/>
<text x="480" y="310" text-anchor="middle" font-size="16" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">GSMTAP UDP :4729</text>
<text x="480" y="332" text-anchor="middle" font-size="13" fill="#475569">слушатель</text>
<!-- импорт файлов -->
<rect x="650" y="280" width="240" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="770" y="310" text-anchor="middle" font-size="14" font-weight="600" fill="#0f172a">Импорт PCAP / COMPRION</text>
<text x="770" y="332" text-anchor="middle" font-size="13" fill="#475569">из файлов</text>
<line x1="480" y1="352" x2="480" y2="390" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="770" y1="352" x2="635" y2="390" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- прямой USB-путь минует снифферы и GSMTAP -->
<path d="M100 84 H52 V448 H258" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
<text x="64" y="418" font-size="12" font-weight="600" fill="#475569">прямой USB</text>
<text x="64" y="436" font-size="12" fill="#475569">код pysniff внутри сервера</text>
<!-- анализирующий сервер -->
<rect x="260" y="392" width="440" height="84" rx="12" fill="#ecfdf5" stroke="#6ee7b7" stroke-width="1.5"/>
<text x="480" y="427" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">simtrace-analyser-server</text>
<text x="480" y="451" text-anchor="middle" font-size="13" fill="#475569">декодирует · сохраняет</text>
<line x1="400" y1="476" x2="250" y2="514" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="560" y1="476" x2="710" y2="514" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
<!-- хранилище и интерфейс -->
<rect x="110" y="516" width="280" height="76" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="250" y="548" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">SQLite</text>
<text x="250" y="570" text-anchor="middle" font-size="13" fill="#475569">sessions.db</text>
<rect x="570" y="516" width="280" height="76" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
<text x="710" y="548" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">Браузер (веб-интерфейс)</text>
<text x="710" y="570" text-anchor="middle" font-size="13" fill="#475569">устанавливаемое PWA</text>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

+2
View File
@@ -40,6 +40,8 @@ ROOT_FILES = (
'README.md',
'README_RUS.md',
'frontend.png',
'architecture_en.svg',
'architecture_ru.svg',
'LICENSE',
)
+15
View File
@@ -81,6 +81,21 @@ class TestReleaseZip(unittest.TestCase):
self.assertIn('%s/frontend/%s' % (top, asset), self.names,
'precached %s is missing from the zip' % asset)
def test_readme_images_are_in_the_zip(self):
# Drift guard: the runtime tree's READMEs embed the screenshot and the
# architecture diagrams by relative path, so every referenced image
# must travel with the archive.
top = 'simtrace-analyser-%s' % __version__
for readme in ('README.md', 'README_RUS.md'):
text = (REPO / readme).read_text()
images = re.findall(r'!\[[^\]]*\]\(([^)\s]+)\)', text)
self.assertTrue(images, 'no images referenced by %s' % readme)
for image in images:
self.assertNotIn('://', image, image)
self.assertIn('%s/%s' % (top, image), self.names,
'%s references %s, which is missing from the zip'
% (readme, image))
def test_batch_files_use_crlf(self):
with zipfile.ZipFile(self.archive) as zf:
bats = [n for n in self.names if n.endswith('.bat')]