71 lines
3.5 KiB
Markdown
71 lines
3.5 KiB
Markdown
# Backend architecture
|
|
|
|
## Process model
|
|
|
|
`src.main` constructs one FastAPI application with `root_path="/api"`. During
|
|
startup it stores the running asyncio loop in `src.shared_objects`, creates an
|
|
asyncpg `DatabasePool`, attaches a packet broadcaster to it, creates a second
|
|
network-state broadcaster, and drains any capture records buffered before the DB
|
|
became available. Shutdown stops capture, network resources, telemetry, tshark,
|
|
and the packet tracker; then closes WebSocket broadcasters and the DB pool.
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
UI[Frontend/client] --> API[FastAPI /api]
|
|
API --> NET[Network and bridge API]
|
|
API --> CAP[Sniffer API]
|
|
API --> FW[Firewall API]
|
|
API --> SCR[Script API]
|
|
CAP --> NS[network_sniffer]
|
|
NS --> PT[PacketTracker]
|
|
EBPF[tc/eBPF telemetry process] --> PT
|
|
NS <--> TS[tshark workers]
|
|
PT --> DB[(PostgreSQL packets)]
|
|
DB --> PB[PacketBroadcaster]
|
|
PB --> WS1[Packet WebSocket]
|
|
NET --> NB[Network broadcaster]
|
|
NB --> WS2[Network WebSocket]
|
|
API --> DB
|
|
```
|
|
|
|
## Component boundaries
|
|
|
|
| Component | Responsibility | Persistent state | Important side effects |
|
|
| --- | --- | --- | --- |
|
|
| `main.py` | app construction and lifecycle wiring | shared object references | starts/stops resources |
|
|
| `api/` | validates requests and presents HTTP/WebSocket contracts | none by default | may alter Linux networking, nftables, or services |
|
|
| `network_sniffer.py` | owns capture sessions and AF_PACKET sockets | in-process session map and pre-DB buffer | raw sockets, reader threads |
|
|
| `packet_tracker.py` | merges capture and telemetry observations | bounded in-memory pending entries | asynchronous database persistence |
|
|
| `database.py` | packet upsert/retrieval and SQL analysis | PostgreSQL `packets` table | WebSocket publication after single-row upserts |
|
|
| `tshark_manager.py` | optional application-protocol enrichment | worker and metadata caches | `tshark` subprocesses/threads |
|
|
| `bridge_telemetry.py` and `ebpf_bridge_events.py` | bridge tc/eBPF event collection | subprocess state and event queue | compiles/attaches tc programs |
|
|
| `bridge_link_state_manager.py` | optionally propagates member failure/recovery state | watcher registry | link and Ethernet-profile changes |
|
|
|
|
## Shared runtime state
|
|
|
|
`shared_objects.py` intentionally holds process-wide references rather than using
|
|
request-scoped dependency injection:
|
|
|
|
- `db`: initialized `DatabasePool`, or `None` after shutdown.
|
|
- `web_loop`: FastAPI event loop used when worker threads need to schedule work.
|
|
- `broadcaster`: packet update broadcaster.
|
|
- `network_broadcaster`: network-state update broadcaster.
|
|
|
|
Endpoints that require the database return HTTP 503 when `shared_objects.db` is
|
|
unavailable. Worker components should tolerate the DB not being ready by buffering
|
|
or logging failure, rather than assuming the application has fully started.
|
|
|
|
## Router mounting
|
|
|
|
| Router module | Prefix added by `main.py` | Router-local prefix | Result |
|
|
| --- | --- | --- | --- |
|
|
| `network_api` | `/network` | none | `/api/network/...` |
|
|
| `sniffer_api` | `/sniffer` | none | `/api/sniffer/...` |
|
|
| `packet_api` | `/packets` | none | `/api/packets/...` |
|
|
| `analysis_api` | `/analysis` | none | `/api/analysis/...` |
|
|
| `nft_manager` | none | `/firewall` | `/api/firewall/...` |
|
|
| `packet_scripting_api` | `/scripts` | `/scripts` | `/api/scripts/scripts/...` |
|
|
|
|
The last row reflects the current code exactly. It is worth preserving this fact in
|
|
examples until the duplicated prefix is deliberately changed.
|