github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/codec.go (about) 1 package net 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 ) 9 10 // CRLFByte represents a byte of CRLF. 11 var CRLFByte = byte('\n') 12 13 type ( 14 // ICodec is the interface of gnet codec. 15 ICodec interface { 16 // Encode encodes frames upon server responses into TCP stream. 17 Encode(c Conn, buf []byte) ([]byte, error) 18 // Decode decodes frames from TCP stream via specific implementation. 19 Decode(c Conn) ([]byte, error) 20 } 21 22 // BuiltInFrameCodec is the built-in codec which will be assigned to gnet server when customized codec is not set up. 23 BuiltInFrameCodec struct { 24 } 25 26 // LineBasedFrameCodec encodes/decodes line-separated frames into/from TCP stream. 27 LineBasedFrameCodec struct { 28 } 29 30 // DelimiterBasedFrameCodec encodes/decodes specific-delimiter-separated frames into/from TCP stream. 31 DelimiterBasedFrameCodec struct { 32 delimiter byte 33 } 34 35 // FixedLengthFrameCodec encodes/decodes fixed-length-separated frames into/from TCP stream. 36 FixedLengthFrameCodec struct { 37 frameLength int 38 } 39 40 // LengthFieldBasedFrameCodec is the refactoring from 41 // https://github.com/smallnest/goframe/blob/master/length_field_based_frameconn.go, licensed by Apache License 2.0. 42 // It encodes/decodes frames into/from TCP stream with value of the length field in the message. 43 LengthFieldBasedFrameCodec struct { 44 encoderConfig EncoderConfig 45 decoderConfig DecoderConfig 46 } 47 ) 48 49 // Encode ... 50 func (cc *BuiltInFrameCodec) Encode(c Conn, buf []byte) ([]byte, error) { 51 return buf, nil 52 } 53 54 // Decode ... 55 func (cc *BuiltInFrameCodec) Decode(c Conn) ([]byte, error) { 56 buf := c.Read() 57 if len(buf) == 0 { 58 return nil, nil 59 } 60 c.ResetBuffer() 61 return buf, nil 62 } 63 64 // Encode ... 65 func (cc *LineBasedFrameCodec) Encode(c Conn, buf []byte) ([]byte, error) { 66 return append(buf, CRLFByte), nil 67 } 68 69 // Decode ... 70 func (cc *LineBasedFrameCodec) Decode(c Conn) ([]byte, error) { 71 buf := c.Read() 72 idx := bytes.IndexByte(buf, CRLFByte) 73 if idx == -1 { 74 return nil, errCRLFNotFound 75 } 76 c.ShiftN(idx + 1) 77 return buf[:idx], nil 78 } 79 80 // NewDelimiterBasedFrameCodec instantiates and returns a codec with a specific delimiter. 81 func NewDelimiterBasedFrameCodec(delimiter byte) *DelimiterBasedFrameCodec { 82 return &DelimiterBasedFrameCodec{delimiter} 83 } 84 85 // Encode ... 86 func (cc *DelimiterBasedFrameCodec) Encode(c Conn, buf []byte) ([]byte, error) { 87 return append(buf, cc.delimiter), nil 88 } 89 90 // Decode ... 91 func (cc *DelimiterBasedFrameCodec) Decode(c Conn) ([]byte, error) { 92 buf := c.Read() 93 idx := bytes.IndexByte(buf, cc.delimiter) 94 if idx == -1 { 95 return nil, errDelimiterNotFound 96 } 97 c.ShiftN(idx + 1) 98 return buf[:idx], nil 99 } 100 101 // NewFixedLengthFrameCodec instantiates and returns a codec with fixed length. 102 func NewFixedLengthFrameCodec(frameLength int) *FixedLengthFrameCodec { 103 return &FixedLengthFrameCodec{frameLength} 104 } 105 106 // Encode ... 107 func (cc *FixedLengthFrameCodec) Encode(c Conn, buf []byte) ([]byte, error) { 108 if len(buf)%cc.frameLength != 0 { 109 return nil, errInvalidFixedLength 110 } 111 return buf, nil 112 } 113 114 // Decode ... 115 func (cc *FixedLengthFrameCodec) Decode(c Conn) ([]byte, error) { 116 size, buf := c.ReadN(cc.frameLength) 117 if size == 0 { 118 return nil, errUnexpectedEOF 119 } 120 c.ShiftN(size) 121 return buf, nil 122 } 123 124 // NewLengthFieldBasedFrameCodec instantiates and returns a codec based on the length field. 125 // It is the go implementation of netty LengthFieldBasedFrameecoder and LengthFieldPrepender. 126 // you can see javadoc of them to learn more details. 127 func NewLengthFieldBasedFrameCodec(ec EncoderConfig, dc DecoderConfig) *LengthFieldBasedFrameCodec { 128 return &LengthFieldBasedFrameCodec{encoderConfig: ec, decoderConfig: dc} 129 } 130 131 // EncoderConfig config for encoder. 132 type EncoderConfig struct { 133 // ByteOrder is the ByteOrder of the length field. 134 ByteOrder binary.ByteOrder 135 // LengthFieldLength is the length of the length field. 136 LengthFieldLength int 137 // LengthAdjustment is the compensation value to add to the value of the length field 138 LengthAdjustment int 139 // LengthIncludesLengthFieldLength is true, the length of the prepended length field is added to the value of 140 // the prepended length field 141 LengthIncludesLengthFieldLength bool 142 } 143 144 // DecoderConfig config for decoder. 145 type DecoderConfig struct { 146 // ByteOrder is the ByteOrder of the length field. 147 ByteOrder binary.ByteOrder 148 // LengthFieldOffset is the offset of the length field 149 LengthFieldOffset int 150 // LengthFieldLength is the length of the length field 151 LengthFieldLength int 152 // LengthAdjustment is the compensation value to add to the value of the length field 153 LengthAdjustment int 154 // InitialBytesToStrip is the number of first bytes to strip out from the decoded frame 155 InitialBytesToStrip int 156 } 157 158 // Encode ... 159 func (cc *LengthFieldBasedFrameCodec) Encode(c Conn, buf []byte) (out []byte, err error) { 160 length := len(buf) + cc.encoderConfig.LengthAdjustment 161 if cc.encoderConfig.LengthIncludesLengthFieldLength { 162 length += cc.encoderConfig.LengthFieldLength 163 } 164 165 if length < 0 { 166 return nil, errTooLessLength 167 } 168 169 switch cc.encoderConfig.LengthFieldLength { 170 case 1: 171 if length >= 256 { 172 return nil, fmt.Errorf("length does not fit into a byte: %d", length) 173 } 174 out = []byte{byte(length)} 175 case 2: 176 if length >= 65536 { 177 return nil, fmt.Errorf("length does not fit into a short integer: %d", length) 178 } 179 out = make([]byte, 2) 180 cc.encoderConfig.ByteOrder.PutUint16(out, uint16(length)) 181 case 3: 182 if length >= 16777216 { 183 return nil, fmt.Errorf("length does not fit into a medium integer: %d", length) 184 } 185 out = writeUint24(cc.encoderConfig.ByteOrder, length) 186 case 4: 187 out = make([]byte, 4) 188 cc.encoderConfig.ByteOrder.PutUint32(out, uint32(length)) 189 case 8: 190 out = make([]byte, 8) 191 cc.encoderConfig.ByteOrder.PutUint64(out, uint64(length)) 192 default: 193 return nil, errUnsupportedLength 194 } 195 196 out = append(out, buf...) 197 return 198 } 199 200 type innerBuffer []byte 201 202 func (in *innerBuffer) readN(n int) (buf []byte, err error) { 203 if n <= 0 { 204 return nil, errors.New("zero or negative length is invalid") 205 } else if n > len(*in) { 206 return nil, errors.New("exceeding buffer length") 207 } 208 buf = (*in)[:n] 209 *in = (*in)[n:] 210 return 211 } 212 213 // Decode ... 214 func (cc *LengthFieldBasedFrameCodec) Decode(c Conn) ([]byte, error) { 215 var ( 216 in innerBuffer 217 header []byte 218 err error 219 ) 220 in = c.Read() 221 if cc.decoderConfig.LengthFieldOffset > 0 { //discard header(offset) 222 header, err = in.readN(cc.decoderConfig.LengthFieldOffset) 223 if err != nil { 224 return nil, errUnexpectedEOF 225 } 226 } 227 228 lenBuf, frameLength, err := cc.getUnadjustedFrameLength(&in) 229 if err != nil { 230 return nil, err 231 } 232 233 // real message length 234 msgLength := int(frameLength) + cc.decoderConfig.LengthAdjustment 235 msg, err := in.readN(msgLength) 236 if err != nil { 237 return nil, errUnexpectedEOF 238 } 239 240 fullMessage := make([]byte, len(header)+len(lenBuf)+msgLength) 241 copy(fullMessage, header) 242 copy(fullMessage[len(header):], lenBuf) 243 copy(fullMessage[len(header)+len(lenBuf):], msg) 244 c.ShiftN(len(fullMessage)) 245 return fullMessage[cc.decoderConfig.InitialBytesToStrip:], nil 246 } 247 248 func (cc *LengthFieldBasedFrameCodec) getUnadjustedFrameLength(in *innerBuffer) ([]byte, uint64, error) { 249 switch cc.decoderConfig.LengthFieldLength { 250 case 1: 251 b, err := in.readN(1) 252 if err != nil { 253 return nil, 0, errUnexpectedEOF 254 } 255 return b, uint64(b[0]), nil 256 case 2: 257 lenBuf, err := in.readN(2) 258 if err != nil { 259 return nil, 0, errUnexpectedEOF 260 } 261 return lenBuf, uint64(cc.decoderConfig.ByteOrder.Uint16(lenBuf)), nil 262 case 3: 263 lenBuf, err := in.readN(3) 264 if err != nil { 265 return nil, 0, errUnexpectedEOF 266 } 267 return lenBuf, readUint24(cc.decoderConfig.ByteOrder, lenBuf), nil 268 case 4: 269 lenBuf, err := in.readN(4) 270 if err != nil { 271 return nil, 0, errUnexpectedEOF 272 } 273 return lenBuf, uint64(cc.decoderConfig.ByteOrder.Uint32(lenBuf)), nil 274 case 8: 275 lenBuf, err := in.readN(8) 276 if err != nil { 277 return nil, 0, errUnexpectedEOF 278 } 279 return lenBuf, cc.decoderConfig.ByteOrder.Uint64(lenBuf), nil 280 default: 281 return nil, 0, errUnsupportedLength 282 } 283 } 284 285 func readUint24(byteOrder binary.ByteOrder, b []byte) uint64 { 286 _ = b[2] 287 if byteOrder == binary.LittleEndian { 288 return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 289 } 290 return uint64(b[2]) | uint64(b[1])<<8 | uint64(b[0])<<16 291 } 292 293 func writeUint24(byteOrder binary.ByteOrder, v int) []byte { 294 b := make([]byte, 3) 295 if byteOrder == binary.LittleEndian { 296 b[0] = byte(v) 297 b[1] = byte(v >> 8) 298 b[2] = byte(v >> 16) 299 } else { 300 b[2] = byte(v) 301 b[1] = byte(v >> 8) 302 b[0] = byte(v >> 16) 303 } 304 return b 305 }