mirror of https://github.com/XTLS/Xray-core
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.0 KiB
147 lines
3.0 KiB
//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 |
|
}
|
|
|