mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-12-23 22:19:49 +00:00
148 lines
3.0 KiB
Go
148 lines
3.0 KiB
Go
//go:build go1.18
|
|
|
|
package shadowsocks_2022
|
|
|
|
import (
|
|
"io"
|
|
|
|
B "github.com/sagernet/sing/common/buf"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
"github.com/xtls/xray-core/common/buf"
|
|
"github.com/xtls/xray-core/common/net"
|
|
)
|
|
|
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
|
|
func toDestination(socksaddr M.Socksaddr, network net.Network) net.Destination {
|
|
if socksaddr.Family().IsFqdn() {
|
|
return net.Destination{
|
|
Network: network,
|
|
Address: net.DomainAddress(socksaddr.Fqdn),
|
|
Port: net.Port(socksaddr.Port),
|
|
}
|
|
} else {
|
|
return net.Destination{
|
|
Network: network,
|
|
Address: net.IPAddress(socksaddr.Addr.AsSlice()),
|
|
Port: net.Port(socksaddr.Port),
|
|
}
|
|
}
|
|
}
|
|
|
|
func toSocksaddr(destination net.Destination) M.Socksaddr {
|
|
var addr M.Socksaddr
|
|
switch destination.Address.Family() {
|
|
case net.AddressFamilyDomain:
|
|
addr.Fqdn = destination.Address.Domain()
|
|
default:
|
|
addr.Addr = M.AddrFromIP(destination.Address.IP())
|
|
}
|
|
addr.Port = uint16(destination.Port)
|
|
return addr
|
|
}
|
|
|
|
type pipeConnWrapper struct {
|
|
R io.Reader
|
|
W buf.Writer
|
|
net.Conn
|
|
}
|
|
|
|
func (w *pipeConnWrapper) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (w *pipeConnWrapper) Read(b []byte) (n int, err error) {
|
|
return w.R.Read(b)
|
|
}
|
|
|
|
func (w *pipeConnWrapper) Write(p []byte) (n int, err error) {
|
|
n = len(p)
|
|
var mb buf.MultiBuffer
|
|
pLen := len(p)
|
|
for pLen > 0 {
|
|
buffer := buf.New()
|
|
if pLen > buf.Size {
|
|
_, err = buffer.Write(p[:buf.Size])
|
|
p = p[buf.Size:]
|
|
} else {
|
|
buffer.Write(p)
|
|
}
|
|
pLen -= int(buffer.Len())
|
|
mb = append(mb, buffer)
|
|
}
|
|
err = w.W.WriteMultiBuffer(mb)
|
|
if err != nil {
|
|
n = 0
|
|
buf.ReleaseMulti(mb)
|
|
}
|
|
return
|
|
}
|
|
|
|
type packetConnWrapper struct {
|
|
buf.Reader
|
|
buf.Writer
|
|
net.Conn
|
|
Dest net.Destination
|
|
cached buf.MultiBuffer
|
|
}
|
|
|
|
func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
|
|
if w.cached != nil {
|
|
mb, bb := buf.SplitFirst(w.cached)
|
|
if bb == nil {
|
|
w.cached = nil
|
|
} else {
|
|
buffer.Write(bb.Bytes())
|
|
w.cached = mb
|
|
var destination net.Destination
|
|
if bb.UDP != nil {
|
|
destination = *bb.UDP
|
|
} else {
|
|
destination = w.Dest
|
|
}
|
|
bb.Release()
|
|
return toSocksaddr(destination), nil
|
|
}
|
|
}
|
|
mb, err := w.ReadMultiBuffer()
|
|
if err != nil {
|
|
return M.Socksaddr{}, err
|
|
}
|
|
nb, bb := buf.SplitFirst(mb)
|
|
if bb == nil {
|
|
return M.Socksaddr{}, nil
|
|
} else {
|
|
buffer.Write(bb.Bytes())
|
|
w.cached = nb
|
|
var destination net.Destination
|
|
if bb.UDP != nil {
|
|
destination = *bb.UDP
|
|
} else {
|
|
destination = w.Dest
|
|
}
|
|
bb.Release()
|
|
return toSocksaddr(destination), nil
|
|
}
|
|
}
|
|
|
|
func (w *packetConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
|
|
vBuf := buf.New()
|
|
vBuf.Write(buffer.Bytes())
|
|
endpoint := toDestination(destination, net.Network_UDP)
|
|
vBuf.UDP = &endpoint
|
|
return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
|
|
}
|
|
|
|
func (w *packetConnWrapper) Close() error {
|
|
buf.ReleaseMulti(w.cached)
|
|
return nil
|
|
}
|
|
|
|
func returnError(err error) error {
|
|
if E.IsClosed(err) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|