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  }