From 851fc461043a58fe272785b523f111584dbdca2e Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Thu, 3 Sep 2020 00:12:00 +0800 Subject: [PATCH] conn: optimize relay operation --- common/conn/conn.go | 70 +++++++++++++++++++++++++++++++++++++++++++-- go.mod | 5 ++-- go.sum | 9 +++--- proxy/tls/tls.go | 2 +- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/common/conn/conn.go b/common/conn/conn.go index e697bb2..ee84a5d 100644 --- a/common/conn/conn.go +++ b/common/conn/conn.go @@ -73,12 +73,78 @@ func Relay(left, right net.Conn) error { return nil } +func worthReadFrom(src io.Reader) bool { + switch v := src.(type) { + case *net.TCPConn: + return true + case *net.UnixConn: + return true + case *os.File: + fi, err := v.Stat() + if err != nil { + return false + } + return fi.Mode().IsRegular() + case *io.LimitedReader: + return worthReadFrom(v.R) + default: + return false + } +} + // Copy copies from src to dst. +// it will try to avoid memory allocating by using WriteTo or ReadFrom method, +// if both failed, then it'll fallback to call CopyBuffer method. func Copy(dst io.Writer, src io.Reader) (written int64, err error) { - buf := pool.GetBuffer(TCPBufSize) + if wt, ok := src.(io.WriterTo); ok { + return wt.WriteTo(dst) + } + + if rt, ok := dst.(io.ReaderFrom); ok && worthReadFrom(src) { + return rt.ReadFrom(src) + } + + return CopyBuffer(dst, src) +} + +// CopyBuffer copies from src to dst with a userspace buffer. +func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) { + size := TCPBufSize + if l, ok := src.(*io.LimitedReader); ok && int64(size) > l.N { + if l.N < 1 { + size = 1 + } else { + size = int(l.N) + } + } + + buf := pool.GetBuffer(size) defer pool.PutBuffer(buf) - return io.CopyBuffer(dst, src, buf) + for { + nr, er := src.Read(buf) + if nr > 0 { + nw, ew := dst.Write(buf[0:nr]) + if nw > 0 { + written += int64(nw) + } + if ew != nil { + err = ew + break + } + if nr != nw { + err = io.ErrShortWrite + break + } + } + if er != nil { + if er != io.EOF { + err = er + } + break + } + } + return written, err } // RelayUDP copys from src to dst at target with read timeout. diff --git a/go.mod b/go.mod index d344f2f..60b43a3 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,8 @@ require ( github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/xtaci/kcp-go/v5 v5.5.15 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a - golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect - golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 // indirect - golang.org/x/tools v0.0.0-20200826040757-bc8aaaa29e06 // indirect + golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a // indirect + golang.org/x/tools v0.0.0-20200902151623-5b9ef244dc36 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 0feaeb0..3aa71db 100644 --- a/go.sum +++ b/go.sum @@ -72,6 +72,7 @@ github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+A github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c h1:yrfrd1u7MWIwWIulet2TZPEkeNQhQ/GcPLdPXgiEEr0= gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c/go.mod h1:3x6b94nWCP/a2XB/joOPMiGYUBvqbLfeY/BkHLeDs6s= golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= @@ -117,15 +118,15 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs= golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4= -golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a h1:i47hUS795cOydZI4AwJQCKXOr4BvxzvikwDoDtHhP2Y= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200826040757-bc8aaaa29e06 h1:ChBCbOHeLqK+j+znGPlWCcvx/t2PdxmyPBheVZxXbcc= -golang.org/x/tools v0.0.0-20200826040757-bc8aaaa29e06/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200902151623-5b9ef244dc36 h1:0C2pK23jzHryVdIUZ/n6UAuSISdaXMsrwdDQCVW6TRA= +golang.org/x/tools v0.0.0-20200902151623-5b9ef244dc36/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/proxy/tls/tls.go b/proxy/tls/tls.go index 6238823..a20af1f 100644 --- a/proxy/tls/tls.go +++ b/proxy/tls/tls.go @@ -116,7 +116,7 @@ func NewTLSServer(s string, p proxy.Proxy) (proxy.Server, error) { t.tlsConfig = &stdtls.Config{ Certificates: []stdtls.Certificate{cert}, - MinVersion: stdtls.VersionTLS10, + MinVersion: stdtls.VersionTLS12, } t.server, err = proxy.ServerFromURL(transport[1], p)