@@ -14,6 +14,7 @@ import (
1414 "strconv"
1515 "strings"
1616 "sync/atomic"
17+ "time"
1718)
1819
1920type ConnectActionLiteral int
@@ -98,8 +99,9 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
9899 }
99100 ctx .Logf ("Accepting CONNECT to %s" , host )
100101 proxyClient .Write ([]byte ("HTTP/1.0 200 OK\r \n \r \n " ))
101- go copyAndClose (ctx , targetSiteCon , proxyClient )
102- go copyAndClose (ctx , proxyClient , targetSiteCon )
102+
103+ pipeAndClose (ctx , targetSiteCon , proxyClient )
104+
103105 case ConnectHijack :
104106 ctx .Logf ("Hijacking CONNECT to %s" , host )
105107 proxyClient .Write ([]byte ("HTTP/1.0 200 OK\r \n \r \n " ))
@@ -254,15 +256,46 @@ func httpError(w io.WriteCloser, ctx *ProxyCtx, err error) {
254256 }
255257}
256258
257- func copyAndClose (ctx * ProxyCtx , w , r net.Conn ) {
259+ func pipeAndClose (ctx * ProxyCtx , targetSiteCon , proxyClient net.Conn ) {
260+ upCh := make (chan int64 )
261+ downCh := make (chan int64 )
262+ closedConns := 0
263+
264+ go func () {
265+ upCh <- copyAndClose (ctx , targetSiteCon , proxyClient )
266+ }()
267+
268+ go func () {
269+ downCh <- copyAndClose (ctx , proxyClient , targetSiteCon )
270+ }()
271+
272+ for closedConns < 2 {
273+ select {
274+ case bytes := <- upCh :
275+ ctx .BytesUpstream += bytes
276+ closedConns ++
277+ targetSiteCon .SetReadDeadline (time .Now ())
278+
279+ case bytes := <- downCh :
280+ ctx .BytesDownstream += bytes
281+ closedConns ++
282+ proxyClient .SetReadDeadline (time .Now ())
283+ }
284+ }
285+ }
286+
287+ func copyAndClose (ctx * ProxyCtx , w , r net.Conn ) (bytes int64 ) {
258288 connOk := true
259- if _ , err := io .Copy (w , r ); err != nil {
289+ var err error
290+
291+ if bytes , err = io .Copy (w , r ); err != nil && bytes <= 0 {
260292 connOk = false
261293 ctx .Warnf ("Error copying to client: %s" , err )
262294 }
263295 if err := r .Close (); err != nil && connOk {
264296 ctx .Warnf ("Error closing: %s" , err )
265297 }
298+ return bytes
266299}
267300
268301func dialerFromEnv (proxy * ProxyHttpServer ) func (network , addr string ) (net.Conn , error ) {
0 commit comments