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.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 }