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 }