github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/kcp/segment.go (about)

     1  // +build !confonly
     2  
     3  package kcp
     4  
     5  import (
     6  	"encoding/binary"
     7  
     8  	"v2ray.com/core/common/buf"
     9  )
    10  
    11  // Command is a KCP command that indicate the purpose of a Segment.
    12  type Command byte
    13  
    14  const (
    15  	// CommandACK indicates an AckSegment.
    16  	CommandACK Command = 0
    17  	// CommandData indicates a DataSegment.
    18  	CommandData Command = 1
    19  	// CommandTerminate indicates that peer terminates the connection.
    20  	CommandTerminate Command = 2
    21  	// CommandPing indicates a ping.
    22  	CommandPing Command = 3
    23  )
    24  
    25  type SegmentOption byte
    26  
    27  const (
    28  	SegmentOptionClose SegmentOption = 1
    29  )
    30  
    31  type Segment interface {
    32  	Release()
    33  	Conversation() uint16
    34  	Command() Command
    35  	ByteSize() int32
    36  	Serialize([]byte)
    37  	parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte)
    38  }
    39  
    40  const (
    41  	DataSegmentOverhead = 18
    42  )
    43  
    44  type DataSegment struct {
    45  	Conv        uint16
    46  	Option      SegmentOption
    47  	Timestamp   uint32
    48  	Number      uint32
    49  	SendingNext uint32
    50  
    51  	payload  *buf.Buffer
    52  	timeout  uint32
    53  	transmit uint32
    54  }
    55  
    56  func NewDataSegment() *DataSegment {
    57  	return new(DataSegment)
    58  }
    59  
    60  func (s *DataSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte) {
    61  	s.Conv = conv
    62  	s.Option = opt
    63  	if len(buf) < 15 {
    64  		return false, nil
    65  	}
    66  	s.Timestamp = binary.BigEndian.Uint32(buf)
    67  	buf = buf[4:]
    68  
    69  	s.Number = binary.BigEndian.Uint32(buf)
    70  	buf = buf[4:]
    71  
    72  	s.SendingNext = binary.BigEndian.Uint32(buf)
    73  	buf = buf[4:]
    74  
    75  	dataLen := int(binary.BigEndian.Uint16(buf))
    76  	buf = buf[2:]
    77  
    78  	if len(buf) < dataLen {
    79  		return false, nil
    80  	}
    81  	s.Data().Clear()
    82  	s.Data().Write(buf[:dataLen])
    83  	buf = buf[dataLen:]
    84  
    85  	return true, buf
    86  }
    87  
    88  func (s *DataSegment) Conversation() uint16 {
    89  	return s.Conv
    90  }
    91  
    92  func (*DataSegment) Command() Command {
    93  	return CommandData
    94  }
    95  
    96  func (s *DataSegment) Detach() *buf.Buffer {
    97  	r := s.payload
    98  	s.payload = nil
    99  	return r
   100  }
   101  
   102  func (s *DataSegment) Data() *buf.Buffer {
   103  	if s.payload == nil {
   104  		s.payload = buf.New()
   105  	}
   106  	return s.payload
   107  }
   108  
   109  func (s *DataSegment) Serialize(b []byte) {
   110  	binary.BigEndian.PutUint16(b, s.Conv)
   111  	b[2] = byte(CommandData)
   112  	b[3] = byte(s.Option)
   113  	binary.BigEndian.PutUint32(b[4:], s.Timestamp)
   114  	binary.BigEndian.PutUint32(b[8:], s.Number)
   115  	binary.BigEndian.PutUint32(b[12:], s.SendingNext)
   116  	binary.BigEndian.PutUint16(b[16:], uint16(s.payload.Len()))
   117  	copy(b[18:], s.payload.Bytes())
   118  }
   119  
   120  func (s *DataSegment) ByteSize() int32 {
   121  	return 2 + 1 + 1 + 4 + 4 + 4 + 2 + s.payload.Len()
   122  }
   123  
   124  func (s *DataSegment) Release() {
   125  	s.payload.Release()
   126  	s.payload = nil
   127  }
   128  
   129  type AckSegment struct {
   130  	Conv            uint16
   131  	Option          SegmentOption
   132  	ReceivingWindow uint32
   133  	ReceivingNext   uint32
   134  	Timestamp       uint32
   135  	NumberList      []uint32
   136  }
   137  
   138  const ackNumberLimit = 128
   139  
   140  func NewAckSegment() *AckSegment {
   141  	return new(AckSegment)
   142  }
   143  
   144  func (s *AckSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte) {
   145  	s.Conv = conv
   146  	s.Option = opt
   147  	if len(buf) < 13 {
   148  		return false, nil
   149  	}
   150  
   151  	s.ReceivingWindow = binary.BigEndian.Uint32(buf)
   152  	buf = buf[4:]
   153  
   154  	s.ReceivingNext = binary.BigEndian.Uint32(buf)
   155  	buf = buf[4:]
   156  
   157  	s.Timestamp = binary.BigEndian.Uint32(buf)
   158  	buf = buf[4:]
   159  
   160  	count := int(buf[0])
   161  	buf = buf[1:]
   162  
   163  	if len(buf) < count*4 {
   164  		return false, nil
   165  	}
   166  	for i := 0; i < count; i++ {
   167  		s.PutNumber(binary.BigEndian.Uint32(buf))
   168  		buf = buf[4:]
   169  	}
   170  
   171  	return true, buf
   172  }
   173  
   174  func (s *AckSegment) Conversation() uint16 {
   175  	return s.Conv
   176  }
   177  
   178  func (*AckSegment) Command() Command {
   179  	return CommandACK
   180  }
   181  
   182  func (s *AckSegment) PutTimestamp(timestamp uint32) {
   183  	if timestamp-s.Timestamp < 0x7FFFFFFF {
   184  		s.Timestamp = timestamp
   185  	}
   186  }
   187  
   188  func (s *AckSegment) PutNumber(number uint32) {
   189  	s.NumberList = append(s.NumberList, number)
   190  }
   191  
   192  func (s *AckSegment) IsFull() bool {
   193  	return len(s.NumberList) == ackNumberLimit
   194  }
   195  
   196  func (s *AckSegment) IsEmpty() bool {
   197  	return len(s.NumberList) == 0
   198  }
   199  
   200  func (s *AckSegment) ByteSize() int32 {
   201  	return 2 + 1 + 1 + 4 + 4 + 4 + 1 + int32(len(s.NumberList)*4)
   202  }
   203  
   204  func (s *AckSegment) Serialize(b []byte) {
   205  	binary.BigEndian.PutUint16(b, s.Conv)
   206  	b[2] = byte(CommandACK)
   207  	b[3] = byte(s.Option)
   208  	binary.BigEndian.PutUint32(b[4:], s.ReceivingWindow)
   209  	binary.BigEndian.PutUint32(b[8:], s.ReceivingNext)
   210  	binary.BigEndian.PutUint32(b[12:], s.Timestamp)
   211  	b[16] = byte(len(s.NumberList))
   212  	n := 17
   213  	for _, number := range s.NumberList {
   214  		binary.BigEndian.PutUint32(b[n:], number)
   215  		n += 4
   216  	}
   217  }
   218  
   219  func (s *AckSegment) Release() {}
   220  
   221  type CmdOnlySegment struct {
   222  	Conv          uint16
   223  	Cmd           Command
   224  	Option        SegmentOption
   225  	SendingNext   uint32
   226  	ReceivingNext uint32
   227  	PeerRTO       uint32
   228  }
   229  
   230  func NewCmdOnlySegment() *CmdOnlySegment {
   231  	return new(CmdOnlySegment)
   232  }
   233  
   234  func (s *CmdOnlySegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte) {
   235  	s.Conv = conv
   236  	s.Cmd = cmd
   237  	s.Option = opt
   238  
   239  	if len(buf) < 12 {
   240  		return false, nil
   241  	}
   242  
   243  	s.SendingNext = binary.BigEndian.Uint32(buf)
   244  	buf = buf[4:]
   245  
   246  	s.ReceivingNext = binary.BigEndian.Uint32(buf)
   247  	buf = buf[4:]
   248  
   249  	s.PeerRTO = binary.BigEndian.Uint32(buf)
   250  	buf = buf[4:]
   251  
   252  	return true, buf
   253  }
   254  
   255  func (s *CmdOnlySegment) Conversation() uint16 {
   256  	return s.Conv
   257  }
   258  
   259  func (s *CmdOnlySegment) Command() Command {
   260  	return s.Cmd
   261  }
   262  
   263  func (*CmdOnlySegment) ByteSize() int32 {
   264  	return 2 + 1 + 1 + 4 + 4 + 4
   265  }
   266  
   267  func (s *CmdOnlySegment) Serialize(b []byte) {
   268  	binary.BigEndian.PutUint16(b, s.Conv)
   269  	b[2] = byte(s.Cmd)
   270  	b[3] = byte(s.Option)
   271  	binary.BigEndian.PutUint32(b[4:], s.SendingNext)
   272  	binary.BigEndian.PutUint32(b[8:], s.ReceivingNext)
   273  	binary.BigEndian.PutUint32(b[12:], s.PeerRTO)
   274  }
   275  
   276  func (*CmdOnlySegment) Release() {}
   277  
   278  func ReadSegment(buf []byte) (Segment, []byte) {
   279  	if len(buf) < 4 {
   280  		return nil, nil
   281  	}
   282  
   283  	conv := binary.BigEndian.Uint16(buf)
   284  	buf = buf[2:]
   285  
   286  	cmd := Command(buf[0])
   287  	opt := SegmentOption(buf[1])
   288  	buf = buf[2:]
   289  
   290  	var seg Segment
   291  	switch cmd {
   292  	case CommandData:
   293  		seg = NewDataSegment()
   294  	case CommandACK:
   295  		seg = NewAckSegment()
   296  	default:
   297  		seg = NewCmdOnlySegment()
   298  	}
   299  
   300  	valid, extra := seg.parse(conv, cmd, opt, buf)
   301  	if !valid {
   302  		return nil, nil
   303  	}
   304  	return seg, extra
   305  }