Documentation ¶
Overview ¶
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.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
A Listener accepts new connections from its net.Listener and begins muxado server connections on them.
It's API is very similar to a net.Listener, but it returns muxado.Sessions instead of net.Conn's.
func Listen ¶
Listen binds to a network address and returns a Listener which accepts new connections and starts muxado server sessions on them.
func ListenTLS ¶
ListenTLS binds to a network address and accepts new TLS-encrypted connections. It returns a Listener which starts new muxado server sessions on the connections.
func NewListener ¶
NewListener creates a new muxado listener which creates new muxado server sessions by accepting connections from the given net.Listener
func (*Listener) Accept ¶
Accept the next connection from the listener and begin a muxado session on it.
type Session ¶
type Session interface { // Open initiates a new stream on the session. It is equivalent to OpenStream(0, 0, false) Open() (Stream, error) // OpenStream initiates a new stream on the session. A caller can specify a stream's priority and an opaque stream type. // Setting fin to true will cause the stream to be half-closed from the local side immediately upon creation. OpenStream(priority StreamPriority, streamType StreamType, fin bool) (Stream, error) // Accept returns the next stream initiated by the remote side Accept() (Stream, error) // Kill closes the underlying transport stream immediately. // // You SHOULD always perfer to call Close() instead so that the connection // closes cleanly by sending a GoAway frame. Kill() error // Close instructs the session to close cleanly, sending a GoAway frame if one hasn't already been sent. // // This implementation does not "linger". Pending writes on streams may fail. // // You MAY call Close() more than once. Each time after // the first, Close() will return an error. Close() error // GoAway instructs the other side of the connection to stop // initiating new streams by sending a GoAway frame. Most clients // will just call Close(), but you may want explicit control of this // in order to facilitate clean shutdowns. // // You MAY call GoAway() more than once. Each time after the first, // GoAway() will return an error. GoAway(ErrorCode, []byte) error // LocalAddr returns the local address of the transport stream over which the session is running. LocalAddr() net.Addr // RemoteAddr returns the address of the remote side of the transport stream over which the session is running. RemoteAddr() net.Addr // Wait blocks until the session has shutdown and returns the error code for session termination. It also // returns the error that caused the session to terminate as well as any debug information sent in the GoAway // frame by the remote side. Wait() (code ErrorCode, err error, debug []byte) // NetListener returns an adaptor object which allows this Session to be used as a net.Listener. The returned // net.Listener returns new streams initiated by the remote side as net.Conn's when calling Accept(). NetListener() net.Listener // NetDial is a function that implements the same API as net.Dial and can be used in place of it. Users should keep // in mind that it is the same as a call to Open(). It ignores both arguments passed to it, always initiate a new stream // to the remote side. NetDial(_, _ string) (net.Conn, error) }
Session multiplexes many Streams over a single underlying stream transport. Both sides of a muxado session can open new Streams. Sessions can also accept new streams from the remote side.
A muxado Session implements the net.Listener interface, returning new Streams from the remote side.
func Dial ¶
Dial opens a new connection to the given network/address and then beings a muxado client session on it.
type Stream ¶
type Stream interface { // Write writes the bytes in the given buffer to the stream Write([]byte) (int, error) // Read reads the next bytes on the stream into the given buffer Read([]byte) (int, error) // Close closes the stream. It attempts to behave as Close does for a TCP conn in that it // half-closes the stream for sending, and it will send an RST if any more data is received // from the remote side. Close() error // SetDeadline sets a time after which future Read and Write operations will fail. SetDeadline(time.Time) error // SetReadDeadline sets a time after which future Read operations will fail. SetReadDeadline(time.Time) error // SetWriteDeadline sets a time after which future Write operations will fail. SetWriteDeadline(time.Time) error // HalfClose sends a data frame with a fin flag set to half-close the stream from the local side. HalfClose([]byte) (int, error) // Id returns the stream's id. Id() StreamId // StreamType returns the stream's type StreamType() StreamType // Session returns the session object this stream is running on. Session() Session // RemoteAddr returns the session transport's remote address. RemoteAddr() net.Addr // LocalAddr returns the session transport's local address. LocalAddr() net.Addr }
Stream is a full duplex stream-oriented connection that is multiplexed over a Session. Stream implement the net.Conn inteface.
type StreamPriority ¶
type StreamPriority frame.StreamPriority
type StreamType ¶
type StreamType frame.StreamType