mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-03 11:57:39 +03:00
239 lines
4.5 KiB
Go
239 lines
4.5 KiB
Go
package bufio
|
|
|
|
import (
|
|
"io"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/sagernet/sing/common/buf"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
N "github.com/sagernet/sing/common/network"
|
|
)
|
|
|
|
type CachedConn struct {
|
|
net.Conn
|
|
buffer *buf.Buffer
|
|
}
|
|
|
|
func NewCachedConn(conn net.Conn, buffer *buf.Buffer) *CachedConn {
|
|
buffer.IncRef()
|
|
return &CachedConn{
|
|
Conn: conn,
|
|
buffer: buffer,
|
|
}
|
|
}
|
|
|
|
func (c *CachedConn) ReadCached() *buf.Buffer {
|
|
buffer := c.buffer
|
|
c.buffer = nil
|
|
if buffer != nil {
|
|
buffer.DecRef()
|
|
}
|
|
return buffer
|
|
}
|
|
|
|
func (c *CachedConn) Read(p []byte) (n int, err error) {
|
|
if c.buffer != nil {
|
|
n, err = c.buffer.Read(p)
|
|
if err == nil {
|
|
return
|
|
}
|
|
c.buffer.DecRef()
|
|
c.buffer.Release()
|
|
c.buffer = nil
|
|
}
|
|
return c.Conn.Read(p)
|
|
}
|
|
|
|
func (c *CachedConn) WriteTo(w io.Writer) (n int64, err error) {
|
|
if c.buffer != nil {
|
|
wn, wErr := w.Write(c.buffer.Bytes())
|
|
if wErr != nil {
|
|
c.buffer.DecRef()
|
|
c.buffer.Release()
|
|
c.buffer = nil
|
|
}
|
|
n += int64(wn)
|
|
}
|
|
cn, err := Copy(w, c.Conn)
|
|
n += cn
|
|
return
|
|
}
|
|
|
|
func (c *CachedConn) SetReadDeadline(t time.Time) error {
|
|
if c.buffer != nil && !c.buffer.IsEmpty() {
|
|
return nil
|
|
}
|
|
return c.Conn.SetReadDeadline(t)
|
|
}
|
|
|
|
func (c *CachedConn) ReadFrom(r io.Reader) (n int64, err error) {
|
|
return Copy(c.Conn, r)
|
|
}
|
|
|
|
func (c *CachedConn) Upstream() any {
|
|
return c.Conn
|
|
}
|
|
|
|
func (c *CachedConn) ReaderReplaceable() bool {
|
|
return c.buffer == nil
|
|
}
|
|
|
|
func (c *CachedConn) WriterReplaceable() bool {
|
|
return true
|
|
}
|
|
|
|
func (c *CachedConn) CreateReadWaiter() (ReadWaiter, bool) {
|
|
reader, created := CreateReadWaiter(c.Conn)
|
|
if !created {
|
|
return nil, false
|
|
}
|
|
if c.buffer == nil {
|
|
return reader, true
|
|
}
|
|
return &cachedReadWaiter{reader, c.buffer}, true
|
|
}
|
|
|
|
func (c *CachedConn) Close() error {
|
|
if buffer := c.buffer; buffer != nil {
|
|
buffer.DecRef()
|
|
buffer.Release()
|
|
c.buffer = nil
|
|
}
|
|
return c.Conn.Close()
|
|
}
|
|
|
|
type CachedReader struct {
|
|
upstream io.Reader
|
|
buffer *buf.Buffer
|
|
}
|
|
|
|
func NewCachedReader(upstream io.Reader, buffer *buf.Buffer) *CachedReader {
|
|
buffer.IncRef()
|
|
return &CachedReader{
|
|
upstream: upstream,
|
|
buffer: buffer,
|
|
}
|
|
}
|
|
|
|
func (r *CachedReader) ReadCached() *buf.Buffer {
|
|
buffer := r.buffer
|
|
r.buffer = nil
|
|
if buffer != nil {
|
|
buffer.DecRef()
|
|
}
|
|
return buffer
|
|
}
|
|
|
|
func (r *CachedReader) Read(p []byte) (n int, err error) {
|
|
if r.buffer != nil {
|
|
n, err = r.buffer.Read(p)
|
|
if err == nil {
|
|
return
|
|
}
|
|
r.buffer.DecRef()
|
|
r.buffer.Release()
|
|
r.buffer = nil
|
|
}
|
|
return r.upstream.Read(p)
|
|
}
|
|
|
|
func (r *CachedReader) 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.upstream)
|
|
n += cn
|
|
return
|
|
}
|
|
|
|
func (r *CachedReader) Upstream() any {
|
|
return r.upstream
|
|
}
|
|
|
|
func (r *CachedReader) ReaderReplaceable() bool {
|
|
return r.buffer == nil
|
|
}
|
|
|
|
func (r *CachedReader) Close() error {
|
|
if buffer := r.buffer; buffer != nil {
|
|
buffer.DecRef()
|
|
buffer.Release()
|
|
r.buffer = nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type CachedPacketConn struct {
|
|
N.PacketConn
|
|
buffer *buf.Buffer
|
|
destination M.Socksaddr
|
|
}
|
|
|
|
func NewCachedPacketConn(conn N.PacketConn, buffer *buf.Buffer, destination M.Socksaddr) *CachedPacketConn {
|
|
buffer.IncRef()
|
|
return &CachedPacketConn{
|
|
PacketConn: conn,
|
|
buffer: buffer,
|
|
destination: destination,
|
|
}
|
|
}
|
|
|
|
func (c *CachedPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
|
|
if c.buffer != nil {
|
|
_, err = buffer.ReadOnceFrom(c.buffer)
|
|
if err != nil {
|
|
return M.Socksaddr{}, err
|
|
}
|
|
c.buffer.DecRef()
|
|
c.buffer.Release()
|
|
c.buffer = nil
|
|
return c.destination, nil
|
|
}
|
|
return c.PacketConn.ReadPacket(buffer)
|
|
}
|
|
|
|
func (c *CachedPacketConn) ReadCachedPacket() (destination M.Socksaddr, buffer *buf.Buffer) {
|
|
buffer = c.buffer
|
|
c.buffer = nil
|
|
if buffer != nil {
|
|
buffer.DecRef()
|
|
}
|
|
return c.destination, buffer
|
|
}
|
|
|
|
func (c *CachedPacketConn) Upstream() any {
|
|
return c.PacketConn
|
|
}
|
|
|
|
func (c *CachedPacketConn) ReaderReplaceable() bool {
|
|
return c.buffer == nil
|
|
}
|
|
|
|
func (c *CachedPacketConn) WriterReplaceable() bool {
|
|
return true
|
|
}
|
|
|
|
func (c *CachedPacketConn) CreatePacketReadWaiter() (PacketReadWaiter, bool) {
|
|
reader, created := CreatePacketReadWaiter(c.PacketConn)
|
|
if !created {
|
|
return nil, false
|
|
}
|
|
if c.buffer == nil {
|
|
return reader, true
|
|
}
|
|
return &cachedPacketReadWaiter{reader, c.buffer, c.destination}, true
|
|
}
|
|
|
|
func (c *CachedPacketConn) Close() error {
|
|
if buffer := c.buffer; buffer != nil {
|
|
buffer.DecRef()
|
|
buffer.Release()
|
|
c.buffer = nil
|
|
}
|
|
return c.PacketConn.Close()
|
|
}
|