4d1bdba55d
UdpServer now serves many concurrent peers on one socket (removes v1's "one peer per accept" limitation). PeerSocket becomes an enum: ConnectedClient (client side, unchanged behavior) vs SharedServer (server side, channel-fed inbox). A master loop reads the shared socket and routes datagrams to the right per-peer inbox by source address; an unknown peer's first TYPE_HS datagram spawns a new handshake task that, on success, hands the established UdpConnection to accept(). Cleanup is lazy via mpsc::Closed — handshake failures and connection drops self- evict from the map. A small Arc<MasterTask> keeps the loop alive for the lifetime of UdpServer OR any spawned UdpConnection, so existing single- client tests (which move UdpServer into an accept task) still pass. ReliableHsAdapter and run_reliable_handshake are unchanged. UdpClient API unchanged. Added 3 tests: two concurrent clients with cross-talk isolation, bad-CA client doesn't block legitimate ones, dropped peer doesn't block others. Workspace: 117 tests green, clippy/fmt clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>