The HTTP2 matcher uses io.ReadFull to read the client preface.
If the client sends a string shorter than the preface (e.g.,
SSL version) io.ReadFull will block.
Replace io.ReadFull with Read and assume partial reads will not
match
Fixes#44
Go 1.8 and 1.9 use different text for the connection closed error.
Use their common prefix (i.e., "use of closed") in the tests for
them to pass on all Go versions.
Go 1.8: "use of closed network connection"
Go 1.9: "use of closed file or network connection"
Suggested-by: Damien Neil <dneil@google.com>
Retun as soon as we have the matched field in the HTTP2 matcher
regardless of weather the value is matched or not. Fixes#35.
Issue #35 reports that cmux leaks memory when the client is HTTP2
but does not sends the expected header field. For example, when
the non-gRPC client sends a large field in the header and we are
matching for gRPC, we waste a lot of memory in the sniff buffer.
As reported in issue #22 reports that Java gRPC clients cannot
handshake with cmux'ed gRPC server, since the client does not
immediately send a header with the content-type field. The reason
is that the java client, block on receiving the first SETTING
frame.
Add MatchWriter that can match and write on the connection. Implement
a MatchWriter that writes a SETTING frame once it receives a SETTING
frame.
After sniffing and buffering data, if we try to read from
the socket again, bufio.Reader may block. This breaks HTTP handlers
in go1.5.2+ if one tries on browsers or with curl. Go's HTTP client,
however, is not broken. This issue is also there with TeeReader.
Return immediately with the data in the sniffed buffer.
bufferedReader is an optimized implementation of io.Reader that behaves
like
```
io.MultiReader(bytes.NewReader(buffer.Bytes()), io.TeeReader(source, buffer))
```
without allocating.
This has a measurable effect on benchmarks:
```
name old time/op new time/op delta
CMuxConn-4 1.09µs ± 4% 0.99µs ±19% -9.32% (p=0.000 n=17+19)
name old alloc/op new alloc/op delta
CMuxConn-4 240B ± 0% 260B ± 0% +8.33% (p=0.000 n=20+20)
name old allocs/op new allocs/op delta
CMuxConn-4 9.00 ± 0% 5.00 ± 0% -44.44% (p=0.000 n=20+20)
```
Note that appropriate test coverage is provided by `TestRead`.
This commit closes the connections that has been buffered
on the connection channel of the cmux listeners, when the
root listener is closed. With this change it is guaranteed
that the connections are either closed or handed of to the
child listeners (returned via Accept()).
There are a couple of changes to the tests to cover corner
cases and the new behavior.
When the root listener is closed, child listeners will not be closed
until all parked connections are served. This prevents losing
connections that have been read from.
This also allows moving the main test to package cmux_test, but that
will happen in a separate change.