Files
simplexmq/spec/modules/Simplex/Messaging/Transport/Server.md
Evgeny @ SimpleX Chat f7be44981a SMP router specs
2026-03-12 18:13:12 +00:00

34 lines
2.2 KiB
Markdown

# Simplex.Messaging.Transport.Server
> TLS listener: socket lifecycle, client acceptance, SNI credential switching, socket leak detection.
**Source**: [`Transport/Server.hs`](../../../../../src/Simplex/Messaging/Transport/Server.hs)
## safeAccept — errno-based retry
`safeAccept` retries `accept()` on specific errno values. The code comment references the POSIX man page: "man accept says: For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying." The retry set: `eCONNABORTED, eAGAIN, eNETDOWN, ePROTO, eNOPROTOOPT, eHOSTDOWN, eNONET, eHOSTUNREACH, eOPNOTSUPP, eNETUNREACH`. Any other error is logged and re-thrown.
## SocketState — leak detection
`SocketState = (TVar Int, TVar Int, TVar (IntMap (Weak ThreadId)))` tracks: accepted count, gracefully-closed count, and active client threads. `getSocketStats` computes `socketsLeaked = socketsAccepted - socketsClosed - socketsActive`.
## closeServer — weak thread references
`closeServer` kills active client threads via `Weak ThreadId`. The code: `readTVarIO clients >>= mapM_ (deRefWeak >=> mapM_ killThread)`. `deRefWeak` returns `Nothing` if the thread has already been garbage collected, so the shutdown does not fail on already-dead threads.
## SNI credential switching
`supportedTLSServerParams` selects TLS credentials based on SNI:
- **No SNI**: uses `credential` (the primary router credential)
- **SNI present**: uses `sniCredential` (when configured)
The `sniCredUsed` TVar records whether SNI triggered credential switching. In the SMP router (`Server.hs`), when `sniUsed` is `True`, the connection is dispatched to the HTTP handler instead of the SMP handler.
## startTCPServer — address resolution
`startTCPServer` resolves the listen address and selects `AF_INET6` first, falling back to `AF_INET`: `select as = fromJust $ family AF_INET6 <|> family AF_INET`.
## Client certificate validation for services
`paramsAskClientCert` enables TLS client certificate requests. In `validateClientCertificate`, an empty chain (`CCEmpty`) returns no error — client certificates are optional, as noted by the code comment: "client certificates are only used for services."