summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Fitzpatrick <[email protected]>2018-06-20 14:17:20 -0700
committerBrad Fitzpatrick <[email protected]>2018-06-20 14:58:24 -0700
commitf5c09fbedceb69e4b238dec52cdf9f2fe9a815e2 (patch)
tree9d9350a1203c4d20b38e85927342295c01b8c24d
parent7f81f7701c9b584822030be9a3a701b125a56c91 (diff)
Take advantage of Go 1.11's splice support, unwrap Conns in DialProxy.HandleConn
-rw-r--r--tcpproxy.go23
1 files changed, 16 insertions, 7 deletions
diff --git a/tcpproxy.go b/tcpproxy.go
index 9bfa26b..9826d94 100644
--- a/tcpproxy.go
+++ b/tcpproxy.go
@@ -254,7 +254,7 @@ type Conn struct {
// In the case of TLS, this is the SNI header, in the case of HTTPHost
// route, it will be the host header. In the case of a fixed
// route, i.e. those created with AddRoute(), this will always be
- // empty. This can be useful in the case where further routing decisions
+ // empty. This can be useful in the case where further routing decisions
// need to be made in the Target impementation.
HostName string
@@ -421,12 +421,21 @@ func (dp *DialProxy) sendProxyHeader(w io.Writer, src net.Conn) error {
// proxyCopy is the function that copies bytes around.
// It's a named function instead of a func literal so users get
// named goroutines in debug goroutine stack dumps.
-func proxyCopy(errc chan<- error, dst io.Writer, src io.Reader) {
- // TODO: make caller switch from src to rawSrc after N bytes (e.g. 4KB)
- // if the io.Copy optimization to switch to Linux splice happens.
- // TODO: if the runtime provides a way to wait for
- // readability, use that to avoid stranding big blocks of
- // memory blocked in idle reads.
+func proxyCopy(errc chan<- error, dst, src net.Conn) {
+ // Before we unwrap src and/or dst, copy any buffered data.
+ if wc, ok := src.(*Conn); ok && len(wc.Peeked) > 0 {
+ if _, err := dst.Write(wc.Peeked); err != nil {
+ errc <- err
+ return
+ }
+ wc.Peeked = nil
+ }
+
+ // Unwrap the src and dst from *Conn to *net.TCPConn so Go
+ // 1.11's splice optimization kicks in.
+ src = UnderlyingConn(src)
+ dst = UnderlyingConn(dst)
+
_, err := io.Copy(dst, src)
errc <- err
}