Project update: my paired network layer library works! Example: https://gist.github.com/joepie91/4f366440ac5e97e990f30e748a7b3f0f?ts=4
This is a low-ish level network library that uses mutual TLS to implement a peer-to-peer CA-less pairing procedure (only one side needs to enter a pairing code). It's meant for building custom protocols on top of.
It gives you a bidirectional CBOR-encoded pipe with a built-in request/reply mechanism. It doesn't care what you send over it, values that you write (or reply) on one end come out the other end.
It also lets you specify your own protocol negotiation code; and it is client-initiated, so the server does not reveal anything about the protocol it speaks unless the client already knows what to ask for.
Identities are generated and managed automatically; you don't need to hand-generate or set up TLS certificates or anything, all you need to give it is an arbitrary key/value store. It ships with an in-memory and filesystem-based store implementation, but you can add others.
Soon to be published on a package registry near you :) #pairnet
The biggest remaining issue right now is how the message processing loop is implemented; with the current structure, I need to pick from one of either:
1. Risk of deadlocking when making a query from an event handler
2. Swallowing an error in a number of edgecases, and leaving a client hanging
3. Processing incoming events out of order
None of these are really acceptable, so it's time to rework the message processing loop instead! The new approach will be to split inbound query replies and events; events will be guaranteed ordered, but query replies will not be (as they are tied to a specific query anyway, so any ordering naturally happens in user code).
This way, a query reply cannot be held up by an event that's being processed (case 1), and I also won't need weird error-buffering techniques to make the receiving loop continue (case 2), while still leaving ordering intact for those messages where that might actually matter (namely, events).