Not generalized, AFAICT; from reading the docs, Fanout just does websockets, no?

I'm talking about a routing layer that could allow a serverless function to be the backend for an arbitrary stateful TCP protocol, e.g. IRC, SMTP, FTP, PGSQL, etc; where the service doesn't need to add support for a new L7 protocol for functions to use it; instead, the support for the L7 protocol is part of the function, the same way it's part of a regular network daemon.

I would imagine that this would work like the following:

- the logic for the L7 protocol's connection state-transitions lives within the stateless function;

- each call to the stateless function is handed the pre-transition L7 state, and returns the new post-transition L7 state, with the routing layer persisting this state between calls. (Compare/contrast: Erlang gen_server state management, between the gen_server module [routing layer] and the user-supplied delegate module [compute layer].) Any arbitrary compute node can then handle each "step" of the computation... but only one compute "worker" at a time will ever be tasked with handling messages for a given connection, because each call requires an input L7 state, which depends on the output L7 state of the previous compute-step;

- the function declares in its metadata what L4 protocols it accepts (TCP/UDP, maybe SCTP or DTLS, or TCP+TLS, etc); the routing layer then manages flows for these as portable persisted state-machine-state resources on virtual IPs owned collectively by the routing layer mesh — similar to how a distributed wireless AP or eNodeB manages established flows across its listeners;

- likely, the L4 state lives in the same persisted (distributed KV?) store as the L7 state, but just isn't passed back to the serverless function — except for maybe SNI info in the case of TLS. (This would make sense to me because you're never going to update the L7 state without also updating the L4 state. I can imagine a connection-listener state machine that touches the "L4 part" of a backing data-structure in response to most L4 packets, but then, when it's built up enough of a buffer to have a complete L4 message†, it would pass the message to the L7 and get an L7 update in response, and then commit a new L4+L7 state together.)

- And yes, the †ed part above means that another required part of the serverless function's metadata, would be a definition in some language of a lexer/parser for recognizing+extracting toplevel L7 messages from the carrier stream, such that the routing layer would then use this lexer/parser to know when it has one or more lexically-complete messages in its buffer to be pushed down atomically to the compute layer. (I say "lexer/parser" because mostly this code wouldn't have to parse messages — the L7 is still receiving just a stream of bytes it's expected to parse itself; but it's required to be "just a stream of bytes" sliced to consist of exactly one L7 message per call. So for most protocols, this would be cheap: most stateful protocols are either "newline is always toplevel break" or they're binary length-prefixed, and these can both be delimited by a dumb lexer, or even a fixed-buffer DSP-alike. Sadly, though, some stateful protocols require full parsing to know where each message ends. So the routing layer would need to support both — probably with a lot of "function compilation time" grunt-work put into recognizing when the routing layer can apply less than a full Turing-complete parser to the task.) Probably for most protocols this could look like an abstract-DSL version of something with capabilities equivalent to a Wireshark dissector definition or eBPF bytecode; and that in turn could be abstracted over with something like a "buildpack" / "cloud-init" sort of strategy, where instead of supplying the code yourself, you supply the URL of a repo that contains the code.