Simulation & testing
Socket-less simulated connections, awaitable observers, in-memory TCP links, and the WebSocket test host — pick the lowest faithful tier.
Elarion.Connections.Simulation ships the pieces every gateway test suite — and every runnable
dev/demo device simulator — otherwise hand-rolls. SimulatedClientConnection is an in-memory sink
double — register it with the real registry and drive twins, observers, and presence logic
deterministically: await its Sent channel for outbound messages, answer InvokeAsync via
InvokeResponder, and Close() it to assert your code survives ClientConnectionClosedException.
AwaitableConnectionObserver turns lifecycle edges into awaitable completions (with Reset() for
reconnect scenarios). TcpSimulatorClient is the framed client for simulated devices/peers:
connect it to a listener (or wrap the accepted side of a fake device an Elarion dialer reached) and
speak whole messages through the endpoint's own framer, with text helpers for challenge/response
handshakes.
The default for codec/handler-level work is fully in-memory — no OS sockets, ports, or firewall
prompts: InMemoryTcpLink.Start(handler, registry, o => o.Framer = …) runs the complete connection
lifecycle (per-connection sessions, handshake, framing, registry, codec, idle hook) over an in-memory
duplex pair, hands you the simulator-side Client, a deterministic ServerConnection await (the
registered sink — no polling, no handshake races), and a ServerCompletion for teardown assertions.
By default the client speaks the endpoint framer instance (fine for stateless framers); when the
handler's sessions create a stateful framer (negotiated framing, encryption toggles), pass the
client its own instance via the clientFramer parameter — the two ends of a real link never share
framing state.
Reserve real sockets (loopback TCP, Kestrel + ClientWebSocket) for integration tests of the adapters
themselves — the separate Elarion.Connections.AspNetCore.Simulation package's WebSocketTestHost
covers a real Kestrel upgrade, handshake, codec, and close path. InMemoryDuplexStream.CreatePair()
is public for anything else that wants a socket pair without the socket.
Device gateways
Keepalives, codec conversation helpers, and the full device-gateway loop — connections as the carrier, actors as the concurrency gate, handlers as the authorization gate.
Low-allocation dispatch
The opt-in profile (ADR-0066) that removes steady-state garbage from connection dispatch — per-connection scopes, singleton handlers, telemetry opt-down, writer sends — down to 0 B per message.