diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index 5a55c1b2f..dceba917e 100644 --- a/app/dispatcher/default.go +++ b/app/dispatcher/default.go @@ -37,7 +37,7 @@ func (r *cachedReader) Cache(b *buf.Buffer) { mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100) r.Lock() if !mb.IsEmpty() { - common.Must(r.cache.WriteMultiBuffer(mb)) + r.cache, _ = buf.MergeMulti(r.cache, mb) } b.Clear() rawBytes := b.Extend(buf.Size) @@ -75,8 +75,7 @@ func (r *cachedReader) ReadMultiBufferTimeout(timeout time.Duration) (buf.MultiB func (r *cachedReader) CloseError() { r.Lock() if r.cache != nil { - r.cache.Release() - r.cache = nil + r.cache = buf.ReleaseMulti(r.cache) } r.Unlock() r.reader.CloseError() diff --git a/app/dispatcher/stats_test.go b/app/dispatcher/stats_test.go index 5a42faa3f..7091e7e64 100644 --- a/app/dispatcher/stats_test.go +++ b/app/dispatcher/stats_test.go @@ -36,7 +36,7 @@ func TestStatsWriter(t *testing.T) { common.Must2(mb.Write([]byte("abcd"))) common.Must(writer.WriteMultiBuffer(mb)) - mb.Release() + mb = buf.ReleaseMulti(mb) common.Must2(mb.Write([]byte("efg"))) common.Must(writer.WriteMultiBuffer(mb)) diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go index e03d950bc..ce1a21cc7 100644 --- a/common/buf/multi_buffer.go +++ b/common/buf/multi_buffer.go @@ -13,7 +13,7 @@ func ReadAllToMultiBuffer(reader io.Reader) (MultiBuffer, error) { mb := make(MultiBuffer, 0, 128) if _, err := mb.ReadFrom(reader); err != nil { - mb.Release() + ReleaseMulti(mb) return nil, err } @@ -31,7 +31,7 @@ func ReadAllToBytes(reader io.Reader) ([]byte, error) { } b := make([]byte, mb.Len()) common.Must2(mb.Read(b)) - mb.Release() + ReleaseMulti(mb) return b, nil } @@ -47,6 +47,15 @@ func MergeMulti(dest MultiBuffer, src MultiBuffer) (MultiBuffer, MultiBuffer) { return dest, src[:0] } +// ReleaseMulti release all content of the MultiBuffer, and returns an empty MultiBuffer. +func ReleaseMulti(mb MultiBuffer) MultiBuffer { + for i := range mb { + mb[i].Release() + mb[i] = nil + } + return mb[:0] +} + // Copy copied the beginning part of the MultiBuffer into the given byte array. func (mb MultiBuffer) Copy(b []byte) int { total := 0 @@ -107,7 +116,9 @@ func (mb *MultiBuffer) Read(b []byte) (int, error) { // WriteTo implements io.WriterTo. func (mb *MultiBuffer) WriteTo(writer io.Writer) (int64, error) { - defer mb.Release() + defer func() { + *mb = ReleaseMulti(*mb) + }() totalBytes := int64(0) for _, b := range *mb { @@ -143,10 +154,7 @@ func (mb *MultiBuffer) Write(b []byte) (int, error) { // WriteMultiBuffer implements Writer. func (mb *MultiBuffer) WriteMultiBuffer(b MultiBuffer) error { - *mb = append(*mb, b...) - for i := range b { - b[i] = nil - } + *mb, _ = MergeMulti(*mb, b) return nil } @@ -173,15 +181,7 @@ func (mb MultiBuffer) IsEmpty() bool { return true } -// Release releases all Buffers in the MultiBuffer. -func (mb *MultiBuffer) Release() { - for i, b := range *mb { - b.Release() - (*mb)[i] = nil - } - *mb = nil -} - +// String returns the content of the MultiBuffer in string. func (mb MultiBuffer) String() string { v := make([]interface{}, len(mb)) for i, b := range mb { diff --git a/common/buf/reader.go b/common/buf/reader.go index fb1dd4883..90baa48cb 100644 --- a/common/buf/reader.go +++ b/common/buf/reader.go @@ -49,7 +49,6 @@ func (r *BufferedReader) Read(b []byte) (int, error) { nBytes, err := r.Buffer.Read(b) common.Must(err) if r.Buffer.IsEmpty() { - r.Buffer.Release() r.Buffer = nil } return nBytes, nil @@ -123,7 +122,8 @@ func (r *BufferedReader) WriteTo(writer io.Writer) (int64, error) { // Close implements io.Closer. func (r *BufferedReader) Close() error { if !r.Buffer.IsEmpty() { - r.Buffer.Release() + ReleaseMulti(r.Buffer) + r.Buffer = nil } return common.Close(r.Reader) } diff --git a/common/buf/readv_reader.go b/common/buf/readv_reader.go index f127ccde9..ef10ead35 100644 --- a/common/buf/readv_reader.go +++ b/common/buf/readv_reader.go @@ -83,14 +83,12 @@ func (r *ReadVReader) readMulti() (MultiBuffer, error) { r.mr.Clear() if err != nil { - mb := MultiBuffer(bs) - mb.Release() + ReleaseMulti(MultiBuffer(bs)) return nil, err } if nBytes == 0 { - mb := MultiBuffer(bs) - mb.Release() + ReleaseMulti(MultiBuffer(bs)) return nil, io.EOF } diff --git a/common/buf/writer.go b/common/buf/writer.go index 7caabd092..b6d5a15b3 100644 --- a/common/buf/writer.go +++ b/common/buf/writer.go @@ -18,7 +18,7 @@ type BufferToBytesWriter struct { // WriteMultiBuffer implements Writer. This method takes ownership of the given buffer. func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error { - defer mb.Release() + defer ReleaseMulti(mb) size := mb.Len() if size == 0 { @@ -134,7 +134,7 @@ func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error { return w.writer.WriteMultiBuffer(b) } - defer b.Release() + defer ReleaseMulti(b) for !b.IsEmpty() { if w.buffer == nil { @@ -216,7 +216,7 @@ type SequentialWriter struct { // WriteMultiBuffer implements Writer. func (w *SequentialWriter) WriteMultiBuffer(mb MultiBuffer) error { - defer mb.Release() + defer ReleaseMulti(mb) for _, b := range mb { if b.IsEmpty() { @@ -234,7 +234,7 @@ func (w *SequentialWriter) WriteMultiBuffer(mb MultiBuffer) error { type noOpWriter byte func (noOpWriter) WriteMultiBuffer(b MultiBuffer) error { - b.Release() + ReleaseMulti(b) return nil } diff --git a/common/crypto/auth.go b/common/crypto/auth.go index a1202b40d..35147200a 100644 --- a/common/crypto/auth.go +++ b/common/crypto/auth.go @@ -202,7 +202,7 @@ func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) { const readSize = 16 mb := make(buf.MultiBuffer, 0, readSize) if err := r.readInternal(false, &mb); err != nil { - mb.Release() + buf.ReleaseMulti(mb) return nil, err } @@ -212,7 +212,7 @@ func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) { break } if err != nil { - mb.Release() + buf.ReleaseMulti(mb) return nil, err } } @@ -269,7 +269,7 @@ func (w *AuthenticationWriter) seal(b []byte) (*buf.Buffer, error) { } func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error { - defer mb.Release() + defer buf.ReleaseMulti(mb) var maxPadding int32 if w.padding != nil { @@ -286,7 +286,7 @@ func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error { b.Release() if err != nil { - mb2Write.Release() + buf.ReleaseMulti(mb2Write) return err } mb2Write = append(mb2Write, eb) @@ -299,7 +299,7 @@ func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error { } func (w *AuthenticationWriter) writePacket(mb buf.MultiBuffer) error { - defer mb.Release() + defer buf.ReleaseMulti(mb) mb2Write := make(buf.MultiBuffer, 0, len(mb)+1) diff --git a/common/mux/writer.go b/common/mux/writer.go index cd6daf1fc..2dc3904c8 100644 --- a/common/mux/writer.go +++ b/common/mux/writer.go @@ -85,7 +85,7 @@ func (w *Writer) writeData(mb buf.MultiBuffer) error { // WriteMultiBuffer implements buf.Writer. func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error { - defer mb.Release() + defer buf.ReleaseMulti(mb) if mb.IsEmpty() { return w.writeMetaOnly() diff --git a/common/platform/ctlcmd/ctlcmd.go b/common/platform/ctlcmd/ctlcmd.go index 0e1506c39..459329537 100644 --- a/common/platform/ctlcmd/ctlcmd.go +++ b/common/platform/ctlcmd/ctlcmd.go @@ -37,8 +37,8 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) { if errBuffer.Len() > 0 { msg += ": " + errBuffer.String() } - errBuffer.Release() - outBuffer.Release() + buf.ReleaseMulti(errBuffer) + buf.ReleaseMulti(outBuffer) return nil, newError(msg).Base(err) } diff --git a/functions.go b/functions.go index 5fb39dc29..6c49a2d8e 100644 --- a/functions.go +++ b/functions.go @@ -1,10 +1,10 @@ package core import ( + "bytes" "context" "v2ray.com/core/common" - "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/features/routing" ) @@ -21,11 +21,7 @@ func CreateObject(v *Instance, config interface{}) (interface{}, error) { // StartInstance starts a new V2Ray instance with given serialized config. // By default V2Ray only support config in protobuf format, i.e., configFormat = "protobuf". Caller need to load other packages to add JSON support. func StartInstance(configFormat string, configBytes []byte) (*Instance, error) { - var mb buf.MultiBuffer - defer mb.Release() - - common.Must2(mb.Write(configBytes)) - config, err := LoadConfig(configFormat, "", &mb) + config, err := LoadConfig(configFormat, "", bytes.NewReader(configBytes)) if err != nil { return nil, err } diff --git a/main/confloader/external/external.go b/main/confloader/external/external.go index 4c78ef6ee..ef5611fe9 100644 --- a/main/confloader/external/external.go +++ b/main/confloader/external/external.go @@ -17,7 +17,8 @@ type ClosableMultiBuffer struct { } func (c *ClosableMultiBuffer) Close() error { - c.MultiBuffer.Release() + buf.ReleaseMulti(c.MultiBuffer) + c.MultiBuffer = nil return nil } diff --git a/proxy/shadowsocks/ota.go b/proxy/shadowsocks/ota.go index 7a5cf1b4b..ab0d3b597 100644 --- a/proxy/shadowsocks/ota.go +++ b/proxy/shadowsocks/ota.go @@ -114,7 +114,7 @@ func NewChunkWriter(writer io.Writer, auth *Authenticator) *ChunkWriter { // WriteMultiBuffer implements buf.Writer. func (w *ChunkWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { - defer mb.Release() + defer buf.ReleaseMulti(mb) for { payloadLen, _ := mb.Read(w.buffer[2+AuthSize:]) diff --git a/transport/internet/kcp/connection.go b/transport/internet/kcp/connection.go index 7fd67d035..31494006c 100644 --- a/transport/internet/kcp/connection.go +++ b/transport/internet/kcp/connection.go @@ -377,7 +377,7 @@ func (c *Connection) Write(b []byte) (int, error) { // WriteMultiBuffer implements buf.Writer. func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error { - defer mb.Release() + defer buf.ReleaseMulti(mb) updatePending := false defer func() { diff --git a/transport/internet/kcp/receiving.go b/transport/internet/kcp/receiving.go index 688151400..86c389e14 100644 --- a/transport/internet/kcp/receiving.go +++ b/transport/internet/kcp/receiving.go @@ -151,7 +151,8 @@ func NewReceivingWorker(kcp *Connection) *ReceivingWorker { func (w *ReceivingWorker) Release() { w.Lock() - w.leftOver.Release() + buf.ReleaseMulti(w.leftOver) + w.leftOver = nil w.Unlock() } diff --git a/transport/pipe/impl.go b/transport/pipe/impl.go index a2df2787d..d5e929c94 100644 --- a/transport/pipe/impl.go +++ b/transport/pipe/impl.go @@ -144,10 +144,10 @@ func (p *pipe) WriteMultiBuffer(mb buf.MultiBuffer) error { runtime.Gosched() return nil case err == errBufferFull && p.option.discardOverflow: - mb.Release() + buf.ReleaseMulti(mb) return nil case err != errBufferFull: - mb.Release() + buf.ReleaseMulti(mb) p.readSignal.Signal() return err } @@ -184,7 +184,7 @@ func (p *pipe) CloseError() { p.state = errord if !p.data.IsEmpty() { - p.data.Release() + buf.ReleaseMulti(p.data) p.data = nil }