58 lines
3.4 KiB
Go
58 lines
3.4 KiB
Go
|
// muxado is an implementation of a general-purpose stream-multiplexing protocol.
|
||
|
//
|
||
|
// muxado allows clients applications to multiplex a single stream-oriented connection,
|
||
|
// like a TCP connection, and communicate over many streams on top of it. muxado accomplishes
|
||
|
// this by chunking data sent over each stream into frames and then reassembling the
|
||
|
// frames and buffering the data before being passed up to the application
|
||
|
// layer on the other side.
|
||
|
//
|
||
|
// muxado is very nearly an exact implementation of the HTTP2 framing layer while leaving out all
|
||
|
// the HTTP-specific parts. It is heavily inspired by HTTP2/SPDY/WebMUX.
|
||
|
//
|
||
|
// muxado's documentation uses the following terms consistently for easier communication:
|
||
|
// - "a transport" is an underlying stream (typically TCP) over which frames are sent between
|
||
|
// endpoints
|
||
|
// - "a stream" is any of the full-duplex byte-streams multiplexed over the transport
|
||
|
// - "a session" refers to an instance of the muxado protocol running over a transport between
|
||
|
// two endpoints
|
||
|
//
|
||
|
// Perhaps the best part of muxado is the interface exposed to client libraries. Since new
|
||
|
// streams may be initiated by both sides at any time, a muxado.Session implements the net.Listener
|
||
|
// interface (almost! Go unfortunately doesn't support covariant interface satisfaction so there's
|
||
|
// a shim). Each muxado stream implements the net.Conn interface. This allows you to integrate
|
||
|
// muxado into existing code which works with these interfaces (which is most Golang networking code)
|
||
|
// with very little difficulty. Consider the following toy example. Here we'll initiate a new secure
|
||
|
// connection to a server, and then ask it which application it wants via an HTTP request over a muxado stream
|
||
|
// and then serve an entire HTTP application *to the server*.
|
||
|
//
|
||
|
//
|
||
|
// sess, err := muxado.DialTLS("tcp", "example.com:1234", new(tls.Config))
|
||
|
// client := &http.Client{Transport: &http.Transport{Dial: sess.NetDial}}
|
||
|
// resp, err := client.Get("http://example.com/appchoice")
|
||
|
// switch getChoice(resp.Body) {
|
||
|
// case "foo":
|
||
|
// http.Serve(sess.NetListener(), fooHandler)
|
||
|
// case "bar":
|
||
|
// http.Serve(sess.NetListener(), barHandler)
|
||
|
// }
|
||
|
//
|
||
|
//
|
||
|
// In addition to enabling multiple streams over a single connection, muxado enables other
|
||
|
// behaviors which can be useful to the application layer:
|
||
|
// - Both sides of a muxado session may initiate new streams
|
||
|
// - muxado can transparently run application-level heartbeats and timeout dead sessions
|
||
|
// - When connections fail, muxado indicates to the application which streams may be safely retried
|
||
|
// - muxado supports prioritizing streams to maximize useful throughput when bandwidth-constrained
|
||
|
//
|
||
|
// A few examples of what these capabilities might make muxado useful for:
|
||
|
// - eliminating custom async/pipeling code for your protocols
|
||
|
// - eliminating connection pools in your protocols
|
||
|
// - eliminating custom NAT traversal logic for enabling server-initiated streams
|
||
|
//
|
||
|
// muxado has been tuned to be very performant within the limits of what you can expect of pure-Go code.
|
||
|
// Some of muxado's code looks unidiomatic in the quest for better performance. (Locks over channels, never allocating
|
||
|
// from the heap, etc). muxado will typically outperform TCP connections when rapidly initiating many new
|
||
|
// streams with small payloads. When sending a large payload over a single stream, muxado's worst case, it can
|
||
|
// be 2-3x slower and does not parallelize well.
|
||
|
package muxado
|