From 9df018b07fe633b5d788349b613e1981f2ec6f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 1 May 2022 09:33:31 +0800 Subject: [PATCH] Add buffered conn --- common/rw/buffer.go | 115 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 5 +- go.sum | 9 ++-- 3 files changed, 121 insertions(+), 8 deletions(-) diff --git a/common/rw/buffer.go b/common/rw/buffer.go index ac22ebe..58cacca 100644 --- a/common/rw/buffer.go +++ b/common/rw/buffer.go @@ -2,11 +2,126 @@ package rw import ( "io" + "net" + "time" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" ) +type CachedReader interface { + common.ReaderWithUpstream + ReadCached() *buf.Buffer +} + +type BufferedConn struct { + net.Conn + Buffer *buf.Buffer +} + +func (c *BufferedConn) ReadCached() *buf.Buffer { + buffer := c.Buffer + c.Buffer = nil + return buffer +} + +func (c *BufferedConn) Read(p []byte) (n int, err error) { + if c.Buffer != nil { + n, err = c.Buffer.Read(p) + if err == nil { + return + } + c.Buffer.Release() + c.Buffer = nil + } + return c.Conn.Read(p) +} + +func (c *BufferedConn) WriteTo(w io.Writer) (n int64, err error) { + if c.Buffer != nil { + wn, wErr := w.Write(c.Buffer.Bytes()) + if wErr != nil { + c.Buffer.Release() + c.Buffer = nil + } + n += int64(wn) + } + cn, err := Copy(w, c.Conn) + n += cn + return +} + +func (c *BufferedConn) SetReadDeadline(t time.Time) error { + if c.Buffer != nil && !c.Buffer.IsEmpty() { + return nil + } + return c.Conn.SetReadDeadline(t) +} + +func (c *BufferedConn) ReadFrom(r io.Reader) (n int64, err error) { + return Copy(c.Conn, r) +} + +func (c *BufferedConn) UpstreamReader() io.Reader { + return c.Conn +} + +func (c *BufferedConn) ReaderReplaceable() bool { + return c.Buffer == nil +} + +func (c *BufferedConn) UpstreamWriter() io.Writer { + return c.Conn +} + +func (c *BufferedConn) WriterReplaceable() bool { + return true +} + +type BufferedReader struct { + Reader io.Reader + Buffer *buf.Buffer +} + +func (c *BufferedReader) ReadCached() *buf.Buffer { + buffer := c.Buffer + c.Buffer = nil + return buffer +} + +func (r *BufferedReader) Read(p []byte) (n int, err error) { + if r.Buffer != nil { + n, err = r.Buffer.Read(p) + if err == nil { + return + } + r.Buffer.Release() + r.Buffer = nil + } + return r.Reader.Read(p) +} + +func (r *BufferedReader) WriteTo(w io.Writer) (n int64, err error) { + if r.Buffer != nil { + wn, wErr := w.Write(r.Buffer.Bytes()) + if wErr != nil { + return 0, wErr + } + n += int64(wn) + } + cn, err := Copy(w, r.Reader) + n += cn + return +} + +func (w *BufferedReader) UpstreamReader() io.Reader { + return w.Reader +} + +func (w *BufferedReader) ReaderReplaceable() bool { + return w.Buffer == nil +} + type BufferedWriter struct { Writer io.Writer Buffer *buf.Buffer diff --git a/go.mod b/go.mod index 7cedbba..96ca220 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/sagernet/sing go 1.18 require ( - github.com/cloudflare/cloudflare-go v0.38.0 + github.com/cloudflare/cloudflare-go v0.30.0 github.com/go-acme/lego/v4 v4.6.0 github.com/go-resty/resty/v2 v2.7.0 github.com/openacid/low v0.1.21 @@ -19,7 +19,7 @@ require ( github.com/vishvananda/netlink v1.1.0 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 - golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 + golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d google.golang.org/protobuf v1.28.0 lukechampine.com/blake3 v1.1.7 @@ -30,7 +30,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/go.sum b/go.sum index f5eb9ff..7f995eb 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.20.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI= -github.com/cloudflare/cloudflare-go v0.38.0 h1:Qf/oVlDmQgb4RfCxqkR0hJoEUQKHvDE4A09MHWssa/w= -github.com/cloudflare/cloudflare-go v0.38.0/go.mod h1:tWDVF03nA9VS9TvFRTrOeY78uSFQzS+n429EcBZszzg= +github.com/cloudflare/cloudflare-go v0.30.0 h1:ho2ObQ1iZfjMqP9RcovvT1Jwp/ZW4Ji5baWVwl2T//A= +github.com/cloudflare/cloudflare-go v0.30.0/go.mod h1:B55yGpU9NdzhWPYu0CDq8smftKrqB/PSDQAdIBEKApw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -162,7 +162,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -606,8 +605,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 h1:Js08h5hqB5xyWR789+QqueR6sDE8mk+YvpETZ+F6X9Y= +golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=