diff --git a/shadowsocks/leakybuf.go b/shadowsocks/leakybuf.go new file mode 100644 index 0000000..3c7dd8c --- /dev/null +++ b/shadowsocks/leakybuf.go @@ -0,0 +1,40 @@ +// Provides leaky buffer, based on the example in Effective Go. +package shadowsocks + +type LeakyBuf struct { + bufSize int // size of each buffer + freeList chan []byte +} + +// NewLeakyBuf creates a leaky buffer which can hold at most n buffer, each +// with bufSize bytes. +func NewLeakyBuf(n, bufSize int) *LeakyBuf { + return &LeakyBuf{ + bufSize: bufSize, + freeList: make(chan []byte, n), + } +} + +// Get returns a buffer from the leaky buffer or create a new buffer. +func (lb *LeakyBuf) Get() (b []byte) { + select { + case b = <-lb.freeList: + default: + b = make([]byte, lb.bufSize) + } + return +} + +// Put add the buffer into the free buffer pool for reuse. Panic if the buffer +// size is not the same with the leaky buffer's. This is intended to expose +// error usage of leaky buffer. +func (lb *LeakyBuf) Put(b []byte) { + if len(b) != lb.bufSize { + panic("invalid buffer size that's put into leaky buffer") + } + select { + case lb.freeList <- b: + default: + } + return +} diff --git a/shadowsocks/pipe.go b/shadowsocks/pipe.go index f41ce8f..35f356f 100644 --- a/shadowsocks/pipe.go +++ b/shadowsocks/pipe.go @@ -2,7 +2,6 @@ package shadowsocks import ( // "io" - "github.com/cyfdecyf/leakybuf" "net" "time" ) @@ -21,7 +20,7 @@ func SetReadTimeout(c net.Conn) { const bufSize = 4096 const nBuf = 2048 -var pipeBuf = leakybuf.NewLeakyBuf(nBuf, bufSize) +var pipeBuf = NewLeakyBuf(nBuf, bufSize) // PipeThenClose copies data from src to dst, closes dst when done. func PipeThenClose(src, dst net.Conn, timeoutOpt int) {