Files
2021-05-03 06:19:57 +08:00

142 lines
2.5 KiB
Go

package common
import (
"io"
"net"
"sync"
"github.com/p4gefau1t/trojan-go/log"
)
type RewindReader struct {
mu sync.Mutex
rawReader io.Reader
buf []byte
bufReadIdx int
rewound bool
buffering bool
bufferSize int
}
func (r *RewindReader) Read(p []byte) (int, error) {
r.mu.Lock()
defer r.mu.Unlock()
if r.rewound {
if len(r.buf) > r.bufReadIdx {
n := copy(p, r.buf[r.bufReadIdx:])
r.bufReadIdx += n
return n, nil
}
r.rewound = false // all buffering content has been read
}
n, err := r.rawReader.Read(p)
if r.buffering {
r.buf = append(r.buf, p[:n]...)
if len(r.buf) > r.bufferSize*2 {
log.Debug("read too many bytes!")
}
}
return n, err
}
func (r *RewindReader) ReadByte() (byte, error) {
buf := [1]byte{}
_, err := r.Read(buf[:])
return buf[0], err
}
func (r *RewindReader) Discard(n int) (int, error) {
buf := [128]byte{}
if n < 128 {
return r.Read(buf[:n])
}
for discarded := 0; discarded+128 < n; discarded += 128 {
_, err := r.Read(buf[:])
if err != nil {
return discarded, err
}
}
if rest := n % 128; rest != 0 {
return r.Read(buf[:rest])
}
return n, nil
}
func (r *RewindReader) Rewind() {
r.mu.Lock()
if r.bufferSize == 0 {
panic("no buffer")
}
r.rewound = true
r.bufReadIdx = 0
r.mu.Unlock()
}
func (r *RewindReader) StopBuffering() {
r.mu.Lock()
r.buffering = false
r.mu.Unlock()
}
func (r *RewindReader) SetBufferSize(size int) {
r.mu.Lock()
if size == 0 { // disable buffering
if !r.buffering {
panic("reader is disabled")
}
r.buffering = false
r.buf = nil
r.bufReadIdx = 0
r.bufferSize = 0
} else {
if r.buffering {
panic("reader is buffering")
}
r.buffering = true
r.bufReadIdx = 0
r.bufferSize = size
r.buf = make([]byte, 0, size)
}
r.mu.Unlock()
}
type RewindConn struct {
net.Conn
*RewindReader
}
func (c *RewindConn) Read(p []byte) (int, error) {
return c.RewindReader.Read(p)
}
func NewRewindConn(conn net.Conn) *RewindConn {
return &RewindConn{
Conn: conn,
RewindReader: &RewindReader{
rawReader: conn,
},
}
}
type StickyWriter struct {
rawWriter io.Writer
writeBuffer []byte
MaxBuffered int
}
func (w *StickyWriter) Write(p []byte) (int, error) {
if w.MaxBuffered > 0 {
w.MaxBuffered--
w.writeBuffer = append(w.writeBuffer, p...)
if w.MaxBuffered != 0 {
return len(p), nil
}
w.MaxBuffered = 0
_, err := w.rawWriter.Write(w.writeBuffer)
w.writeBuffer = nil
return len(p), err
}
return w.rawWriter.Write(p)
}