-
Notifications
You must be signed in to change notification settings - Fork 59
Description
This means defining a header type for each transport (http, ws, p2p, electrum/sv1, sv2, zeromq). That will drop into a header std::variant, which will result in the current universal http message (variant body with http header only) becoming a universal tcp message.
This will allow send/receive over the same proxy::write(message) and proxy::read(message) methods with pass-through to the contained socket's two analogous methods. All aspects of framing implemented in the headers (todo), all aspects of body parse and serialization contained in the bodies (which is complete). The socket already handles tcp/p2p, http/ws using a std::optional switch between the tcp and ws stream. This will become generalized to a variant socket, with four stream types, which you can think of as tcp, tls, tcp+ws, and tls+ws. tcp and tls can upgrade to ws (from http messaging), and tls or tcp will be the initialization of any endpoint (i.e. an endpoint is either always tls or not tls). ws is really about framing, but dropping the upgrade process down to the socket simplifies implementation, due to the complexity of ws framing. It really operates more like a transport layer.
Because streams are cumulative, we build tls on tcp and ws on either. The upgrade from one to the next destroys the original socket, so the new one simply takes its place in the variant. So to support all forms of tcp transport, we will still only require the resources of a single socket instance (and the variant type flag). Same for the universal tcp message. One c++ type with just two variants (header and body), no other state. All aspects of the transport protocol are buried in the socket, all aspects of message framing are controlled by message headers and all aspects of message encoding are controlled by message bodies. Messages, being entirely decoupled from transport, framing, and encoding, define the application protocol. This cleanly separates the transport and message plumbing from application semantics. And as such we can run any application protocol in any encoding(s) over any transport(s).
Just to be clear, tls above refers to http/s, also applicable as sv2/s (which is not http), as well as p2p/s (bip324) and zmq/s (curve-cp). All of these will be handled by the same tls socket abstraction and are distinct only in the handshake callback, which is handled by the channel base type that derives from the proxy, which embeds the socket.
I'm working toward completion of the above model with implementations for tls/ws, http/p2p, binary/hex/json/file/span encodings, for admin website, block explorer (html and API), both embedded with file system override, and p2p. Once these are clean on the abstractions the other will slot right in. Most of this is functionally complete but some still needs to be refactored into the above. Getting p2p into this set of abstractions with zero performance hit is a real coup. (edited)