mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-05 21:07:41 +03:00
Refine bufio
This commit is contained in:
parent
edd8b71a7c
commit
b21aa294fc
12 changed files with 319 additions and 247 deletions
|
@ -15,11 +15,11 @@ import (
|
|||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/acme"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
_ "github.com/sagernet/sing/common/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/protocol/trojan"
|
||||
transTLS "github.com/sagernet/sing/transport/tls"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -180,7 +180,7 @@ func (i *TrojanInstance) NewConnection(ctx context.Context, conn net.Conn, metad
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rw.CopyConn(ctx, conn, destConn)
|
||||
return bufio.CopyConn(ctx, conn, destConn)
|
||||
}
|
||||
|
||||
func (i *TrojanInstance) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -191,7 +191,7 @@ func (i *TrojanInstance) NewPacketConnection(ctx context.Context, conn N.PacketC
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return N.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
return bufio.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
}
|
||||
|
||||
func (i *TrojanInstance) loopRequests() {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/geoip"
|
||||
"github.com/sagernet/sing/common/geosite"
|
||||
|
@ -324,7 +325,7 @@ func (c *client) NewConnection(ctx context.Context, conn net.Conn, metadata M.Me
|
|||
return E.Cause(err, "client handshake")
|
||||
}
|
||||
runtime.KeepAlive(_payload)
|
||||
return rw.CopyConn(ctx, serverConn, conn)
|
||||
return bufio.CopyConn(ctx, serverConn, conn)
|
||||
}
|
||||
|
||||
func (c *client) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -334,7 +335,7 @@ func (c *client) NewPacketConnection(ctx context.Context, conn N.PacketConn, met
|
|||
return err
|
||||
}
|
||||
serverConn := c.method.DialPacketConn(udpConn)
|
||||
return N.CopyPacketConn(ctx, serverConn, conn)
|
||||
return bufio.CopyPacketConn(ctx, serverConn, conn)
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, flags *flags) {
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
_ "github.com/sagernet/sing/common/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/random"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead_2022"
|
||||
|
@ -191,7 +191,7 @@ func (s *server) NewConnection(ctx context.Context, conn net.Conn, metadata M.Me
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rw.CopyConn(ctx, conn, destConn)
|
||||
return bufio.CopyConn(ctx, conn, destConn)
|
||||
}
|
||||
|
||||
func (s *server) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -200,7 +200,7 @@ func (s *server) NewPacketConnection(ctx context.Context, conn N.PacketConn, met
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return N.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
return bufio.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
}
|
||||
|
||||
func (s *server) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error {
|
||||
|
|
|
@ -17,12 +17,12 @@ import (
|
|||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
_ "github.com/sagernet/sing/common/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/redir"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/protocol/trojan"
|
||||
"github.com/sagernet/sing/transport/mixed"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -317,7 +317,7 @@ func (c *client) NewConnection(ctx context.Context, conn net.Conn, metadata M.Me
|
|||
return E.Cause(err, "client handshake")
|
||||
}
|
||||
runtime.KeepAlive(_request)
|
||||
return rw.CopyConn(ctx, clientConn, conn)
|
||||
return bufio.CopyConn(ctx, clientConn, conn)
|
||||
}
|
||||
|
||||
func (c *client) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -333,7 +333,7 @@ func (c *client) NewPacketConnection(ctx context.Context, conn N.PacketConn, met
|
|||
}
|
||||
return socks.CopyPacketConn(ctx, &trojan.PacketConn{Conn: tlsConn}, conn)*/
|
||||
clientConn := trojan.NewClientPacketConn(tlsConn, c.key)
|
||||
return N.CopyPacketConn(ctx, clientConn, conn)
|
||||
return bufio.CopyPacketConn(ctx, clientConn, conn)
|
||||
}
|
||||
|
||||
func (c *client) HandleError(err error) {
|
||||
|
|
|
@ -14,11 +14,11 @@ import (
|
|||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/acme"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
_ "github.com/sagernet/sing/common/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/protocol/trojan"
|
||||
"github.com/sagernet/sing/transport/tcp"
|
||||
transTLS "github.com/sagernet/sing/transport/tls"
|
||||
|
@ -197,7 +197,7 @@ func (s *server) NewConnection(ctx context.Context, conn net.Conn, metadata M.Me
|
|||
return err
|
||||
}
|
||||
logrus.Info("inbound TCP ", conn.RemoteAddr(), " ==> ", metadata.Destination)
|
||||
return rw.CopyConn(ctx, conn, destConn)
|
||||
return bufio.CopyConn(ctx, conn, destConn)
|
||||
}
|
||||
|
||||
func (s *server) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -206,7 +206,7 @@ func (s *server) NewPacketConnection(ctx context.Context, conn N.PacketConn, met
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return N.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
return bufio.CopyNetPacketConn(ctx, conn, udpConn)
|
||||
}
|
||||
|
||||
func (s *server) HandleError(err error) {
|
||||
|
|
|
@ -10,12 +10,12 @@ import (
|
|||
|
||||
"github.com/sagernet/sing"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
_ "github.com/sagernet/sing/common/log"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/redir"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
"github.com/sagernet/sing/protocol/socks"
|
||||
"github.com/sagernet/sing/transport/mixed"
|
||||
|
@ -108,7 +108,7 @@ func (c *localClient) NewConnection(ctx context.Context, conn net.Conn, metadata
|
|||
return err
|
||||
}
|
||||
|
||||
return rw.CopyConn(context.Background(), conn, upstream)
|
||||
return bufio.CopyConn(context.Background(), conn, upstream)
|
||||
}
|
||||
|
||||
func (c *localClient) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
|
@ -119,7 +119,7 @@ func (c *localClient) NewPacketConnection(ctx context.Context, conn N.PacketConn
|
|||
return err
|
||||
}
|
||||
|
||||
return N.CopyPacketConn(ctx, conn, uot.NewClientConn(upstream))
|
||||
return bufio.CopyPacketConn(ctx, conn, uot.NewClientConn(upstream))
|
||||
}
|
||||
|
||||
func (c *localClient) OnError(err error) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package rw
|
||||
package bufio
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
)
|
||||
|
||||
type CachedReader interface {
|
||||
|
@ -124,7 +125,7 @@ func (w *BufferedWriter) Write(p []byte) (n int, err error) {
|
|||
}
|
||||
fd, err := common.TryFileDescriptor(w.Writer)
|
||||
if err == nil {
|
||||
_, err = WriteV(fd, w.Buffer.Bytes(), p[n:])
|
||||
_, err = rw.WriteV(fd, w.Buffer.Bytes(), p[n:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -189,7 +190,7 @@ func (w *HeaderWriter) Write(p []byte) (n int, err error) {
|
|||
}
|
||||
fd, err := common.TryFileDescriptor(w.Writer)
|
||||
if err == nil {
|
||||
_, err = WriteV(fd, w.Header.Bytes(), p)
|
||||
_, err = rw.WriteV(fd, w.Header.Bytes(), p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
274
common/bufio/conn.go
Normal file
274
common/bufio/conn.go
Normal file
|
@ -0,0 +1,274 @@
|
|||
package bufio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/common/task"
|
||||
)
|
||||
|
||||
type PacketConnStub struct{}
|
||||
|
||||
func (s *PacketConnStub) RemoteAddr() net.Addr {
|
||||
return &common.DummyAddr{}
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetReadDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetWriteDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func Copy(dst io.Writer, src io.Reader) (n int64, err error) {
|
||||
if wt, ok := src.(io.WriterTo); ok {
|
||||
return wt.WriteTo(dst)
|
||||
}
|
||||
if rt, ok := dst.(io.ReaderFrom); ok {
|
||||
return rt.ReadFrom(src)
|
||||
}
|
||||
extendedSrc, srcExtended := src.(N.ExtendedReader)
|
||||
extendedDst, dstExtended := dst.(N.ExtendedWriter)
|
||||
if !srcExtended && !dstExtended {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
for {
|
||||
buffer.FullReset()
|
||||
_, err = buffer.ReadFrom(src)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var cn int
|
||||
cn, err = dst.Write(buffer.Bytes())
|
||||
n += int64(cn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if !srcExtended {
|
||||
return CopyExtended(extendedDst, &ExtendedReaderWrapper{src})
|
||||
} else if !dstExtended {
|
||||
return CopyExtended(&ExtendedWriterWrapper{dst}, extendedSrc)
|
||||
} else {
|
||||
return CopyExtended(extendedDst, extendedSrc)
|
||||
}
|
||||
}
|
||||
|
||||
func CopyExtended(dst N.ExtendedWriter, src N.ExtendedReader) (n int64, err error) {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.Reset()
|
||||
err = src.ReadBuffer(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dataLen := data.Len()
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), dataLen)
|
||||
err = dst.WriteBuffer(buffer)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n += int64(dataLen)
|
||||
}
|
||||
}
|
||||
|
||||
func CopyConn(ctx context.Context, conn net.Conn, dest net.Conn) error {
|
||||
err := task.Run(ctx, func() error {
|
||||
defer rw.CloseRead(conn)
|
||||
defer rw.CloseWrite(dest)
|
||||
return common.Error(Copy(dest, conn))
|
||||
}, func() error {
|
||||
defer rw.CloseRead(dest)
|
||||
defer rw.CloseWrite(conn)
|
||||
return common.Error(Copy(conn, dest))
|
||||
})
|
||||
conn.Close()
|
||||
dest.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func CopyExtendedConn(ctx context.Context, conn N.ExtendedConn, dest N.ExtendedConn) error {
|
||||
return task.Run(ctx, func() error {
|
||||
defer rw.CloseRead(conn)
|
||||
defer rw.CloseWrite(dest)
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.Reset()
|
||||
_, err := data.ReadFrom(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = dest.WriteBuffer(buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}, func() error {
|
||||
defer rw.CloseRead(dest)
|
||||
defer rw.CloseWrite(conn)
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.Reset()
|
||||
_, err := data.ReadFrom(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = conn.WriteBuffer(buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func CopyPacketConn(ctx context.Context, conn N.PacketConn, dest N.PacketConn) error {
|
||||
defer common.Close(conn, dest)
|
||||
return task.Run(ctx, func() error {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.FullReset()
|
||||
destination, err := conn.ReadPacket(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = dest.WritePacket(buffer, destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}, func() error {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.FullReset()
|
||||
destination, err := dest.ReadPacket(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = conn.WritePacket(buffer, destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func CopyNetPacketConn(ctx context.Context, conn N.PacketConn, dest net.PacketConn) error {
|
||||
if udpConn, ok := dest.(*net.UDPConn); ok {
|
||||
return CopyPacketConn(ctx, conn, &UDPConnWrapper{udpConn})
|
||||
} else {
|
||||
return CopyPacketConn(ctx, conn, &PacketConnWrapper{dest})
|
||||
}
|
||||
}
|
||||
|
||||
type UDPConnWrapper struct {
|
||||
*net.UDPConn
|
||||
}
|
||||
|
||||
func (w *UDPConnWrapper) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||
n, addr, err := w.ReadFromUDPAddrPort(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
return M.Socksaddr{}, err
|
||||
}
|
||||
buffer.Truncate(n)
|
||||
return M.SocksaddrFromNetIP(addr), nil
|
||||
}
|
||||
|
||||
func (w *UDPConnWrapper) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||
if destination.Family().IsFqdn() {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", destination.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return common.Error(w.UDPConn.WriteTo(buffer.Bytes(), udpAddr))
|
||||
}
|
||||
return common.Error(w.UDPConn.WriteToUDP(buffer.Bytes(), destination.UDPAddr()))
|
||||
}
|
||||
|
||||
type PacketConnWrapper struct {
|
||||
net.PacketConn
|
||||
}
|
||||
|
||||
func (p *PacketConnWrapper) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||
_, addr, err := buffer.ReadPacketFrom(p)
|
||||
if err != nil {
|
||||
return M.Socksaddr{}, err
|
||||
}
|
||||
return M.SocksaddrFromNet(addr), err
|
||||
}
|
||||
|
||||
func (p *PacketConnWrapper) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||
return common.Error(p.WriteTo(buffer.Bytes(), destination.UDPAddr()))
|
||||
}
|
||||
|
||||
type BindPacketConn struct {
|
||||
net.PacketConn
|
||||
Addr net.Addr
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) Read(b []byte) (n int, err error) {
|
||||
n, _, err = c.ReadFrom(b)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) Write(b []byte) (n int, err error) {
|
||||
return c.WriteTo(b, c.Addr)
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) RemoteAddr() net.Addr {
|
||||
return c.Addr
|
||||
}
|
||||
|
||||
type ExtendedReaderWrapper struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (r *ExtendedReaderWrapper) ReadBuffer(buffer *buf.Buffer) error {
|
||||
n, err := r.Read(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Truncate(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExtendedWriterWrapper struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (w *ExtendedWriterWrapper) WriteBuffer(buffer *buf.Buffer) error {
|
||||
return common.Error(w.Write(buffer.Bytes()))
|
||||
}
|
|
@ -2,15 +2,12 @@ package network
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/task"
|
||||
)
|
||||
|
||||
type PacketReader interface {
|
||||
|
@ -32,6 +29,22 @@ type PacketConn interface {
|
|||
SetWriteDeadline(t time.Time) error
|
||||
}
|
||||
|
||||
type ExtendedReader interface {
|
||||
io.Reader
|
||||
ReadBuffer(buffer *buf.Buffer) error
|
||||
}
|
||||
|
||||
type ExtendedWriter interface {
|
||||
io.Writer
|
||||
WriteBuffer(buffer *buf.Buffer) error
|
||||
}
|
||||
|
||||
type ExtendedConn interface {
|
||||
ExtendedReader
|
||||
ExtendedWriter
|
||||
net.Conn
|
||||
}
|
||||
|
||||
type NetPacketConn interface {
|
||||
net.PacketConn
|
||||
PacketConn
|
||||
|
@ -44,126 +57,3 @@ type UDPHandler interface {
|
|||
type UDPConnectionHandler interface {
|
||||
NewPacketConnection(ctx context.Context, conn PacketConn, metadata M.Metadata) error
|
||||
}
|
||||
|
||||
type PacketConnStub struct{}
|
||||
|
||||
func (s *PacketConnStub) RemoteAddr() net.Addr {
|
||||
return &common.DummyAddr{}
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetReadDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *PacketConnStub) SetWriteDeadline(t time.Time) error {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
func CopyPacketConn(ctx context.Context, conn PacketConn, dest PacketConn) error {
|
||||
defer common.Close(conn, dest)
|
||||
return task.Run(ctx, func() error {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.FullReset()
|
||||
destination, err := conn.ReadPacket(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = dest.WritePacket(buffer, destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}, func() error {
|
||||
_buffer := buf.StackNewMax()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
data := buffer.Cut(buf.ReversedHeader, buf.ReversedHeader)
|
||||
for {
|
||||
data.FullReset()
|
||||
destination, err := dest.ReadPacket(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Resize(buf.ReversedHeader+data.Start(), data.Len())
|
||||
err = conn.WritePacket(buffer, destination)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func CopyNetPacketConn(ctx context.Context, conn PacketConn, dest net.PacketConn) error {
|
||||
if udpConn, ok := dest.(*net.UDPConn); ok {
|
||||
return CopyPacketConn(ctx, conn, &UDPConnWrapper{udpConn})
|
||||
} else {
|
||||
return CopyPacketConn(ctx, conn, &PacketConnWrapper{dest})
|
||||
}
|
||||
}
|
||||
|
||||
type UDPConnWrapper struct {
|
||||
*net.UDPConn
|
||||
}
|
||||
|
||||
func (w *UDPConnWrapper) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||
n, addr, err := w.ReadFromUDPAddrPort(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
return M.Socksaddr{}, err
|
||||
}
|
||||
buffer.Truncate(n)
|
||||
return M.SocksaddrFromNetIP(addr), nil
|
||||
}
|
||||
|
||||
func (w *UDPConnWrapper) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||
if destination.Family().IsFqdn() {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", destination.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return common.Error(w.UDPConn.WriteTo(buffer.Bytes(), udpAddr))
|
||||
}
|
||||
return common.Error(w.UDPConn.WriteToUDP(buffer.Bytes(), destination.UDPAddr()))
|
||||
}
|
||||
|
||||
type PacketConnWrapper struct {
|
||||
net.PacketConn
|
||||
}
|
||||
|
||||
func (p *PacketConnWrapper) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||
_, addr, err := buffer.ReadPacketFrom(p)
|
||||
if err != nil {
|
||||
return M.Socksaddr{}, err
|
||||
}
|
||||
return M.SocksaddrFromNet(addr), err
|
||||
}
|
||||
|
||||
func (p *PacketConnWrapper) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||
return common.Error(p.WriteTo(buffer.Bytes(), destination.UDPAddr()))
|
||||
}
|
||||
|
||||
type BindPacketConn struct {
|
||||
net.PacketConn
|
||||
Addr net.Addr
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) Read(b []byte) (n int, err error) {
|
||||
n, _, err = c.ReadFrom(b)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) Write(b []byte) (n int, err error) {
|
||||
return c.WriteTo(b, c.Addr)
|
||||
}
|
||||
|
||||
func (c *BindPacketConn) RemoteAddr() net.Addr {
|
||||
return c.Addr
|
||||
}
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
package rw
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/task"
|
||||
)
|
||||
|
||||
func CopyConn(ctx context.Context, conn net.Conn, dest net.Conn) error {
|
||||
if pc, inPc := conn.(net.PacketConn); inPc {
|
||||
if destPc, outPc := dest.(net.PacketConn); outPc {
|
||||
return CopyPacketConn(ctx, pc, destPc)
|
||||
}
|
||||
}
|
||||
|
||||
err := task.Run(ctx, func() error {
|
||||
defer CloseRead(conn)
|
||||
defer CloseWrite(dest)
|
||||
return common.Error(Copy(dest, conn))
|
||||
}, func() error {
|
||||
defer CloseRead(dest)
|
||||
defer CloseWrite(conn)
|
||||
return common.Error(Copy(conn, dest))
|
||||
})
|
||||
conn.Close()
|
||||
dest.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func Copy(dst io.Writer, src io.Reader) (n int64, err error) {
|
||||
if wt, ok := src.(io.WriterTo); ok {
|
||||
return wt.WriteTo(dst)
|
||||
}
|
||||
if rt, ok := dst.(io.ReaderFrom); ok {
|
||||
return rt.ReadFrom(src)
|
||||
}
|
||||
_buffer := buf.StackNew()
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
for {
|
||||
buffer.Reset()
|
||||
_, err = buffer.ReadFrom(src)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
var cn int
|
||||
cn, err = dst.Write(buffer.Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
n += int64(cn)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CopyPacketConn(ctx context.Context, conn net.PacketConn, outPacketConn net.PacketConn) error {
|
||||
return task.Run(ctx, func() error {
|
||||
_buffer := buf.With(make([]byte, buf.UDPBufferSize))
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
for {
|
||||
n, addr, err := conn.ReadFrom(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Truncate(n)
|
||||
_, err = outPacketConn.WriteTo(buffer.Bytes(), addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.FullReset()
|
||||
}
|
||||
}, func() error {
|
||||
_buffer := buf.With(make([]byte, buf.UDPBufferSize))
|
||||
defer runtime.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
for {
|
||||
n, addr, err := outPacketConn.ReadFrom(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.Truncate(n)
|
||||
_, err = conn.WriteTo(buffer.Bytes(), addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer.FullReset()
|
||||
}
|
||||
})
|
||||
}
|
|
@ -12,11 +12,11 @@ import (
|
|||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
"github.com/sagernet/sing/common/cache"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/common/udpnat"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead"
|
||||
|
@ -163,7 +163,7 @@ func (s *Relay[U]) newConnection(ctx context.Context, conn net.Conn, metadata M.
|
|||
}
|
||||
metadata.Protocol = "shadowsocks-relay"
|
||||
metadata.Destination = s.uDestination[user]
|
||||
conn = &rw.BufferedConn{
|
||||
conn = &bufio.BufferedConn{
|
||||
Conn: conn,
|
||||
Buffer: requestHeader,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package mixed
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
std_bufio "bufio"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/auth"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
@ -66,7 +67,7 @@ func (l *Listener) NewConnection(ctx context.Context, conn net.Conn, metadata M.
|
|||
return socks.HandleConnection0(ctx, conn, headerType, l.authenticator, l.handler, metadata)
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(&rw.BufferedReader{
|
||||
reader := std_bufio.NewReader(&bufio.BufferedReader{
|
||||
Reader: conn,
|
||||
Buffer: buf.As([]byte{headerType}),
|
||||
})
|
||||
|
@ -107,7 +108,7 @@ func (l *Listener) NewConnection(ctx context.Context, conn net.Conn, metadata M.
|
|||
return err
|
||||
}
|
||||
|
||||
conn = &rw.BufferedConn{
|
||||
conn = &bufio.BufferedConn{
|
||||
Conn: conn,
|
||||
Buffer: buffer,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue