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.
138 lines
3.0 KiB
138 lines
3.0 KiB
4 years ago
|
package xudp
|
||
4 years ago
|
|
||
|
import (
|
||
|
"io"
|
||
|
|
||
|
"github.com/xtls/xray-core/common/buf"
|
||
|
"github.com/xtls/xray-core/common/net"
|
||
|
"github.com/xtls/xray-core/common/protocol"
|
||
|
)
|
||
|
|
||
|
var addrParser = protocol.NewAddressParser(
|
||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
|
||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
|
||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
|
||
|
protocol.PortThenAddress(),
|
||
|
)
|
||
|
|
||
|
func NewPacketWriter(writer buf.Writer, dest net.Destination) *PacketWriter {
|
||
|
return &PacketWriter{
|
||
|
Writer: writer,
|
||
|
Dest: dest,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type PacketWriter struct {
|
||
|
Writer buf.Writer
|
||
|
Dest net.Destination
|
||
|
}
|
||
|
|
||
|
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||
|
defer buf.ReleaseMulti(mb)
|
||
|
mb2Write := make(buf.MultiBuffer, 0, len(mb))
|
||
|
for _, b := range mb {
|
||
|
length := b.Len()
|
||
|
if length == 0 || length+666 > buf.Size {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
eb := buf.New()
|
||
|
eb.Write([]byte{0, 0, 0, 0})
|
||
|
if w.Dest.Network == net.Network_UDP {
|
||
|
eb.WriteByte(1) // New
|
||
|
eb.WriteByte(1) // Opt
|
||
|
eb.WriteByte(2) // UDP
|
||
|
addrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port)
|
||
|
w.Dest.Network = net.Network_Unknown
|
||
|
} else {
|
||
|
eb.WriteByte(2) // Keep
|
||
|
eb.WriteByte(1)
|
||
|
if b.UDP != nil {
|
||
|
eb.WriteByte(2)
|
||
|
addrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port)
|
||
|
}
|
||
|
}
|
||
|
l := eb.Len() - 2
|
||
|
eb.SetByte(0, byte(l>>8))
|
||
|
eb.SetByte(1, byte(l))
|
||
|
eb.WriteByte(byte(length >> 8))
|
||
|
eb.WriteByte(byte(length))
|
||
|
eb.Write(b.Bytes())
|
||
|
|
||
|
mb2Write = append(mb2Write, eb)
|
||
|
}
|
||
|
if mb2Write.IsEmpty() {
|
||
|
return nil
|
||
|
}
|
||
|
return w.Writer.WriteMultiBuffer(mb2Write)
|
||
|
}
|
||
|
|
||
|
func NewPacketReader(reader io.Reader) *PacketReader {
|
||
|
return &PacketReader{
|
||
|
Reader: reader,
|
||
|
cache: make([]byte, 2),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type PacketReader struct {
|
||
|
Reader io.Reader
|
||
|
cache []byte
|
||
|
}
|
||
|
|
||
|
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||
|
for {
|
||
|
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
l := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||
|
if l < 4 {
|
||
|
return nil, io.EOF
|
||
|
}
|
||
|
b := buf.New()
|
||
|
if _, err := b.ReadFullFrom(r.Reader, l); err != nil {
|
||
|
b.Release()
|
||
|
return nil, err
|
||
|
}
|
||
|
discard := false
|
||
|
switch b.Byte(2) {
|
||
|
case 2:
|
||
|
if l != 4 {
|
||
|
b.Advance(5)
|
||
|
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||
|
if err != nil {
|
||
|
b.Release()
|
||
|
return nil, err
|
||
|
}
|
||
|
b.UDP = &net.Destination{
|
||
|
Network: net.Network_UDP,
|
||
|
Address: addr,
|
||
|
Port: port,
|
||
|
}
|
||
|
}
|
||
|
case 4:
|
||
|
discard = true
|
||
|
default:
|
||
|
b.Release()
|
||
|
return nil, io.EOF
|
||
|
}
|
||
|
if b.Byte(3) == 1 {
|
||
|
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||
|
b.Release()
|
||
|
return nil, err
|
||
|
}
|
||
|
length := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||
|
if length > 0 {
|
||
|
b.Clear()
|
||
|
if _, err := b.ReadFullFrom(r.Reader, length); err != nil {
|
||
|
b.Release()
|
||
|
return nil, err
|
||
|
}
|
||
|
if !discard {
|
||
|
return buf.MultiBuffer{b}, nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
b.Release()
|
||
|
}
|
||
|
}
|