github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/core/dst/packets.go (about)

     1  // Copyright 2014 The DST Authors. All rights reserved.
     2  // Use of this source code is governed by an MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package dst
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"net"
    11  )
    12  
    13  const dstHeaderLen = 12
    14  
    15  type packetType int8
    16  
    17  const (
    18  	typeHandshake packetType = 0x0
    19  	typeData                 = 0x1
    20  	typeAck                  = 0x2
    21  	typeNegAck               = 0x3
    22  	typeShutdown             = 0x4
    23  )
    24  
    25  func (t packetType) String() string {
    26  	switch t {
    27  	case typeData:
    28  		return "data"
    29  	case typeHandshake:
    30  		return "handshake"
    31  	case typeAck:
    32  		return "ack"
    33  	case typeNegAck:
    34  		return "negAck"
    35  	case typeShutdown:
    36  		return "shutdown"
    37  	default:
    38  		return "unknown"
    39  	}
    40  }
    41  
    42  type connectionID uint32
    43  
    44  func (c connectionID) String() string {
    45  	return fmt.Sprintf("Ci%08x", uint32(c))
    46  }
    47  
    48  type sequenceNo uint32
    49  
    50  func (s sequenceNo) String() string {
    51  	return fmt.Sprintf("Sq%d", uint32(s))
    52  }
    53  
    54  type timestamp uint32
    55  
    56  func (t timestamp) String() string {
    57  	return fmt.Sprintf("Ts%d", uint32(t))
    58  }
    59  
    60  const (
    61  	flagRequest  = 1 << 0 // This packet is a handshake request
    62  	flagResponse = 1 << 1 // This packet is a handshake response
    63  	flagCookie   = 1 << 2 // This packet contains a coookie challenge
    64  )
    65  
    66  type header struct {
    67  	packetType packetType   // 4 bits
    68  	flags      uint8        // 4 bits
    69  	connID     connectionID // 24 bits
    70  	sequenceNo sequenceNo
    71  	timestamp  timestamp
    72  }
    73  
    74  func (h header) marshal(bs []byte) {
    75  	binary.BigEndian.PutUint32(bs, uint32(h.connID&0xffffff))
    76  	bs[0] = h.flags | uint8(h.packetType)<<4
    77  	binary.BigEndian.PutUint32(bs[4:], uint32(h.sequenceNo))
    78  	binary.BigEndian.PutUint32(bs[8:], uint32(h.timestamp))
    79  }
    80  
    81  func unmarshalHeader(bs []byte) header {
    82  	var h header
    83  	h.packetType = packetType(bs[0] >> 4)
    84  	h.flags = bs[0] & 0xf
    85  	h.connID = connectionID(binary.BigEndian.Uint32(bs) & 0xffffff)
    86  	h.sequenceNo = sequenceNo(binary.BigEndian.Uint32(bs[4:]))
    87  	h.timestamp = timestamp(binary.BigEndian.Uint32(bs[8:]))
    88  	return h
    89  }
    90  
    91  func (h header) String() string {
    92  	return fmt.Sprintf("header{type=%s flags=0x%x connID=%v seq=%v time=%v}", h.packetType, h.flags, h.connID, h.sequenceNo, h.timestamp)
    93  }
    94  
    95  type handshakeData struct {
    96  	packetSize uint32
    97  	connID     connectionID
    98  	cookie     uint32
    99  }
   100  
   101  func (h handshakeData) marshalInto(data []byte) {
   102  	binary.BigEndian.PutUint32(data[0:], h.packetSize)
   103  	binary.BigEndian.PutUint32(data[4:], uint32(h.connID))
   104  	binary.BigEndian.PutUint32(data[8:], h.cookie)
   105  }
   106  
   107  func (h handshakeData) marshal() []byte {
   108  	var data [12]byte
   109  	h.marshalInto(data[:])
   110  	return data[:]
   111  }
   112  
   113  func unmarshalHandshakeData(data []byte) handshakeData {
   114  	var h handshakeData
   115  	h.packetSize = binary.BigEndian.Uint32(data[0:])
   116  	h.connID = connectionID(binary.BigEndian.Uint32(data[4:]))
   117  	h.cookie = binary.BigEndian.Uint32(data[8:])
   118  	return h
   119  }
   120  
   121  func (h handshakeData) String() string {
   122  	return fmt.Sprintf("handshake{size=%d connID=%v cookie=0x%08x}", h.packetSize, h.connID, h.cookie)
   123  }
   124  
   125  type packet struct {
   126  	src  connectionID
   127  	dst  net.Addr
   128  	hdr  header
   129  	data []byte
   130  }
   131  
   132  func (p packet) String() string {
   133  	var dst string
   134  	if p.dst != nil {
   135  		dst = "dst=" + p.dst.String() + " "
   136  	}
   137  	switch p.hdr.packetType {
   138  	case typeHandshake:
   139  		return fmt.Sprintf("%spacket{src=%v %v %v}", dst, p.src, p.hdr, unmarshalHandshakeData(p.data))
   140  	default:
   141  		return fmt.Sprintf("%spacket{src=%v %v data[:%d]}", dst, p.src, p.hdr, len(p.data))
   142  	}
   143  }
   144  
   145  func (p packet) LessSeq(seq sequenceNo) bool {
   146  	diff := seq - p.hdr.sequenceNo
   147  	if diff == 0 {
   148  		return false
   149  	}
   150  	return diff < 1<<31
   151  }
   152  
   153  func (a packet) Less(b packet) bool {
   154  	return a.LessSeq(b.hdr.sequenceNo)
   155  }