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 }