github.com/ipfans/trojan-go@v0.11.0/tunnel/trojan/packet.go (about)

     1  package trojan
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"io"
     7  	"io/ioutil"
     8  	"net"
     9  
    10  	"github.com/ipfans/trojan-go/common"
    11  	"github.com/ipfans/trojan-go/log"
    12  	"github.com/ipfans/trojan-go/tunnel"
    13  )
    14  
    15  type PacketConn struct {
    16  	tunnel.Conn
    17  }
    18  
    19  func (c *PacketConn) ReadFrom(payload []byte) (int, net.Addr, error) {
    20  	return c.ReadWithMetadata(payload)
    21  }
    22  
    23  func (c *PacketConn) WriteTo(payload []byte, addr net.Addr) (int, error) {
    24  	address, err := tunnel.NewAddressFromAddr("udp", addr.String())
    25  	if err != nil {
    26  		return 0, err
    27  	}
    28  	m := &tunnel.Metadata{
    29  		Address: address,
    30  	}
    31  	return c.WriteWithMetadata(payload, m)
    32  }
    33  
    34  func (c *PacketConn) WriteWithMetadata(payload []byte, metadata *tunnel.Metadata) (int, error) {
    35  	packet := make([]byte, 0, MaxPacketSize)
    36  	w := bytes.NewBuffer(packet)
    37  	metadata.Address.WriteTo(w)
    38  
    39  	length := len(payload)
    40  	lengthBuf := [2]byte{}
    41  	crlf := [2]byte{0x0d, 0x0a}
    42  
    43  	binary.BigEndian.PutUint16(lengthBuf[:], uint16(length))
    44  	w.Write(lengthBuf[:])
    45  	w.Write(crlf[:])
    46  	w.Write(payload)
    47  
    48  	_, err := c.Conn.Write(w.Bytes())
    49  
    50  	log.Debug("udp packet remote", c.RemoteAddr(), "metadata", metadata, "size", length)
    51  	return len(payload), err
    52  }
    53  
    54  func (c *PacketConn) ReadWithMetadata(payload []byte) (int, *tunnel.Metadata, error) {
    55  	addr := &tunnel.Address{
    56  		NetworkType: "udp",
    57  	}
    58  	if err := addr.ReadFrom(c.Conn); err != nil {
    59  		return 0, nil, common.NewError("failed to parse udp packet addr").Base(err)
    60  	}
    61  	lengthBuf := [2]byte{}
    62  	if _, err := io.ReadFull(c.Conn, lengthBuf[:]); err != nil {
    63  		return 0, nil, common.NewError("failed to read length")
    64  	}
    65  	length := int(binary.BigEndian.Uint16(lengthBuf[:]))
    66  
    67  	crlf := [2]byte{}
    68  	if _, err := io.ReadFull(c.Conn, crlf[:]); err != nil {
    69  		return 0, nil, common.NewError("failed to read crlf")
    70  	}
    71  
    72  	if len(payload) < length || length > MaxPacketSize {
    73  		io.CopyN(ioutil.Discard, c.Conn, int64(length)) // drain the rest of the packet
    74  		return 0, nil, common.NewError("incoming packet size is too large")
    75  	}
    76  
    77  	if _, err := io.ReadFull(c.Conn, payload[:length]); err != nil {
    78  		return 0, nil, common.NewError("failed to read payload")
    79  	}
    80  
    81  	log.Debug("udp packet from", c.RemoteAddr(), "metadata", addr.String(), "size", length)
    82  	return length, &tunnel.Metadata{
    83  		Address: addr,
    84  	}, nil
    85  }