github.com/aavshr/aws-sdk-go@v1.41.3/private/protocol/eventstream/message.go (about)

     1  package eventstream
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"hash/crc32"
     7  )
     8  
     9  const preludeLen = 8
    10  const preludeCRCLen = 4
    11  const msgCRCLen = 4
    12  const minMsgLen = preludeLen + preludeCRCLen + msgCRCLen
    13  const maxPayloadLen = 1024 * 1024 * 16 // 16MB
    14  const maxHeadersLen = 1024 * 128       // 128KB
    15  const maxMsgLen = minMsgLen + maxHeadersLen + maxPayloadLen
    16  
    17  var crc32IEEETable = crc32.MakeTable(crc32.IEEE)
    18  
    19  // A Message provides the eventstream message representation.
    20  type Message struct {
    21  	Headers Headers
    22  	Payload []byte
    23  }
    24  
    25  func (m *Message) rawMessage() (rawMessage, error) {
    26  	var raw rawMessage
    27  
    28  	if len(m.Headers) > 0 {
    29  		var headers bytes.Buffer
    30  		if err := EncodeHeaders(&headers, m.Headers); err != nil {
    31  			return rawMessage{}, err
    32  		}
    33  		raw.Headers = headers.Bytes()
    34  		raw.HeadersLen = uint32(len(raw.Headers))
    35  	}
    36  
    37  	raw.Length = raw.HeadersLen + uint32(len(m.Payload)) + minMsgLen
    38  
    39  	hash := crc32.New(crc32IEEETable)
    40  	binaryWriteFields(hash, binary.BigEndian, raw.Length, raw.HeadersLen)
    41  	raw.PreludeCRC = hash.Sum32()
    42  
    43  	binaryWriteFields(hash, binary.BigEndian, raw.PreludeCRC)
    44  
    45  	if raw.HeadersLen > 0 {
    46  		hash.Write(raw.Headers)
    47  	}
    48  
    49  	// Read payload bytes and update hash for it as well.
    50  	if len(m.Payload) > 0 {
    51  		raw.Payload = m.Payload
    52  		hash.Write(raw.Payload)
    53  	}
    54  
    55  	raw.CRC = hash.Sum32()
    56  
    57  	return raw, nil
    58  }
    59  
    60  // Clone returns a deep copy of the message.
    61  func (m Message) Clone() Message {
    62  	var payload []byte
    63  	if m.Payload != nil {
    64  		payload = make([]byte, len(m.Payload))
    65  		copy(payload, m.Payload)
    66  	}
    67  
    68  	return Message{
    69  		Headers: m.Headers.Clone(),
    70  		Payload: payload,
    71  	}
    72  }
    73  
    74  type messagePrelude struct {
    75  	Length     uint32
    76  	HeadersLen uint32
    77  	PreludeCRC uint32
    78  }
    79  
    80  func (p messagePrelude) PayloadLen() uint32 {
    81  	return p.Length - p.HeadersLen - minMsgLen
    82  }
    83  
    84  func (p messagePrelude) ValidateLens() error {
    85  	if p.Length == 0 || p.Length > maxMsgLen {
    86  		return LengthError{
    87  			Part: "message prelude",
    88  			Want: maxMsgLen,
    89  			Have: int(p.Length),
    90  		}
    91  	}
    92  	if p.HeadersLen > maxHeadersLen {
    93  		return LengthError{
    94  			Part: "message headers",
    95  			Want: maxHeadersLen,
    96  			Have: int(p.HeadersLen),
    97  		}
    98  	}
    99  	if payloadLen := p.PayloadLen(); payloadLen > maxPayloadLen {
   100  		return LengthError{
   101  			Part: "message payload",
   102  			Want: maxPayloadLen,
   103  			Have: int(payloadLen),
   104  		}
   105  	}
   106  
   107  	return nil
   108  }
   109  
   110  type rawMessage struct {
   111  	messagePrelude
   112  
   113  	Headers []byte
   114  	Payload []byte
   115  
   116  	CRC uint32
   117  }