@@ -254,7 +254,7 @@ type Conn struct {
254254 // In the case of TLS, this is the SNI header, in the case of HTTPHost
255255 // route, it will be the host header. In the case of a fixed
256256 // route, i.e. those created with AddRoute(), this will always be
257- // empty. This can be useful in the case where further routing decisions
257+ // empty. This can be useful in the case where further routing decisions
258258 // need to be made in the Target impementation.
259259 HostName string
260260
@@ -421,12 +421,21 @@ func (dp *DialProxy) sendProxyHeader(w io.Writer, src net.Conn) error {
421421// proxyCopy is the function that copies bytes around.
422422// It's a named function instead of a func literal so users get
423423// named goroutines in debug goroutine stack dumps.
424- func proxyCopy (errc chan <- error , dst io.Writer , src io.Reader ) {
425- // TODO: make caller switch from src to rawSrc after N bytes (e.g. 4KB)
426- // if the io.Copy optimization to switch to Linux splice happens.
427- // TODO: if the runtime provides a way to wait for
428- // readability, use that to avoid stranding big blocks of
429- // memory blocked in idle reads.
424+ func proxyCopy (errc chan <- error , dst , src net.Conn ) {
425+ // Before we unwrap src and/or dst, copy any buffered data.
426+ if wc , ok := src .(* Conn ); ok && len (wc .Peeked ) > 0 {
427+ if _ , err := dst .Write (wc .Peeked ); err != nil {
428+ errc <- err
429+ return
430+ }
431+ wc .Peeked = nil
432+ }
433+
434+ // Unwrap the src and dst from *Conn to *net.TCPConn so Go
435+ // 1.11's splice optimization kicks in.
436+ src = UnderlyingConn (src )
437+ dst = UnderlyingConn (dst )
438+
430439 _ , err := io .Copy (dst , src )
431440 errc <- err
432441}
0 commit comments