Skip to content
Connection multiplexer for GoLang: serve different services on the same port!
Go
Branch: master
Clone or download
Pull request Compare This branch is 19 commits ahead, 51 commits behind soheilhy:master.
a-robinson Merge pull request #9 from a-robinson/revert
Revert "Fix muxListener to always close its channel of connections"
Latest commit 30d10be Jan 11, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore Initial commit Jul 29, 2015
.travis.yml Update to use go 1.7 Jan 6, 2017
CONTRIBUTORS Add the list of contributors Jul 12, 2016
LICENSE Add the license file Aug 1, 2015
README.md
bench_test.go Merge pull request soheilhy#30 from soheilhy/fix-patricia-tree Jul 15, 2016
buffer.go
cmux.go Revert "Fix muxListener to always close its channel of connections" Jan 10, 2017
cmux_test.go Revert "Fix muxListener to always close its channel of connections" Jan 10, 2017
doc.go
example_recursive_test.go
example_test.go Add copyright notice headers on all Go files. Jul 12, 2016
example_tls_test.go Add copyright notice headers on all Go files. Jul 12, 2016
matchers.go Add copyright notice headers on all Go files. Jul 12, 2016
patricia.go Merge pull request soheilhy#33 from soheilhy/fix-b32 Jul 15, 2016
patricia_test.go Merge pull request soheilhy#33 from soheilhy/fix-b32 Jul 15, 2016

README.md

cmux: Connection Mux Build Status GoDoc

cmux is a generic Go library to multiplex connections based on their payload. Using cmux, you can serve gRPC, SSH, HTTPS, HTTP, Go RPC, and pretty much any other protocol on the same TCP listener.

How-To

Simply create your main listener, create a cmux for that listener, and then match connections:

// Create the main listener.
l, err := net.Listen("tcp", ":23456")
if err != nil {
	log.Fatal(err)
}

// Create a cmux.
m := cmux.New(l)

// Match connections in order:
// First grpc, then HTTP, and otherwise Go RPC/TCP.
grpcL := m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
httpL := m.Match(cmux.HTTP1Fast())
trpcL := m.Match(cmux.Any()) // Any means anything that is not yet matched.

// Create your protocol servers.
grpcS := grpc.NewServer()
grpchello.RegisterGreeterServer(grpcs, &server{})

httpS := &http.Server{
	Handler: &helloHTTP1Handler{},
}

trpcS := rpc.NewServer()
s.Register(&ExampleRPCRcvr{})

// Use the muxed listeners for your servers.
go grpcS.Serve(grpcL)
go httpS.Serve(httpL)
go trpcS.Accept(trpcL)

// Start serving!
m.Serve()

There are more examples on GoDoc.

Performance

Since we are only matching the very first bytes of a connection, the performance overhead on long-lived connections (i.e., RPCs and pipelined HTTP streams) is negligible.

Limitations

  • TLS: net/http uses a type assertion to identify TLS connections; since cmux's lookahead-implementing connection wraps the underlying TLS connection, this type assertion fails. This means you can serve HTTPS using cmux but http.Request.TLS will not be set in your handlers. If you are able to wrap TLS around cmux, you can work around this limitation. See https://github.com/cockroachdb/cockroach/commit/83caba2 for an example of this approach.

  • Different Protocols on The Same Connection: cmux matches the connection when it's accepted. For example, one connection can be either gRPC or REST, but not both. That is, we assume that a client connection is either used for gRPC or REST.

Copyright and License

Copyright 2016 The CMux Authors. All rights reserved.

See CONTRIBUTORS for the CMux Authors. Code is released under the Apache 2 license.

You can’t perform that action at this time.