| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package bindings | |
| 6 | |
| 7 import ( | |
| 8 "fmt" | |
| 9 | |
| 10 "mojo/public/go/system" | |
| 11 ) | |
| 12 | |
| 13 const ( | |
| 14 // Flag for a header of a simple message. | |
| 15 MessageNoFlag = 0 | |
| 16 | |
| 17 // Flag for a header of a message that expected a response. | |
| 18 MessageExpectsResponseFlag = 1 << 0 | |
| 19 | |
| 20 // Flag for a header of a message that is a response. | |
| 21 MessageIsResponseFlag = 1 << 1 | |
| 22 | |
| 23 dataHeaderSize = 8 | |
| 24 defaultAlignment = 8 | |
| 25 pointerBitSize = 64 | |
| 26 ) | |
| 27 | |
| 28 var mapHeader DataHeader | |
| 29 | |
| 30 func init() { | |
| 31 mapHeader = DataHeader{24, 0} | |
| 32 } | |
| 33 | |
| 34 const ( | |
| 35 DifferentSizedArraysInMap = "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS
_IN_MAP" | |
| 36 IllegalHandle = "VALIDATION_ERROR_ILLEGAL_HANDLE" | |
| 37 IllegalMemoryRange = "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE" | |
| 38 IllegalPointer = "VALIDATION_ERROR_ILLEGAL_POINTER" | |
| 39 MessageHeaderInvalidFlags = "VALIDATION_ERROR_MESSAGE_HEADER_INVALID
_FLAGS" | |
| 40 MessageHeaderMissingRequestId = "VALIDATION_ERROR_MESSAGE_HEADER_MISSING
_REQUEST_ID" | |
| 41 MessageHeaderUnknownMethod = "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN
_METHOD" | |
| 42 MisalignedObject = "VALIDATION_ERROR_MISALIGNED_OBJECT" | |
| 43 UnexpectedArrayHeader = "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADE
R" | |
| 44 UnexpectedInvalidHandle = "VALIDATION_ERROR_UNEXPECTED_INVALID_HAN
DLE" | |
| 45 UnexpectedNullPointer = "VALIDATION_ERROR_UNEXPECTED_NULL_POINTE
R" | |
| 46 UnexpectedNullUnion = "VALIDATION_ERROR_UNEXPECTED_NULL_UNION" | |
| 47 UnexpectedStructHeader = "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEAD
ER" | |
| 48 ) | |
| 49 | |
| 50 // ValidationError is an error that can happen during message validation. | |
| 51 type ValidationError struct { | |
| 52 ErrorCode string | |
| 53 Message string | |
| 54 } | |
| 55 | |
| 56 func (e *ValidationError) Error() string { | |
| 57 return e.Message | |
| 58 } | |
| 59 | |
| 60 // Payload is an interface implemented by a mojo struct that can encode/decode | |
| 61 // itself into mojo archive format. | |
| 62 type Payload interface { | |
| 63 Encode(encoder *Encoder) error | |
| 64 Decode(decoder *Decoder) error | |
| 65 } | |
| 66 | |
| 67 // DataHeader is a header for a mojo complex element. | |
| 68 type DataHeader struct { | |
| 69 Size uint32 | |
| 70 ElementsOrVersion uint32 | |
| 71 } | |
| 72 | |
| 73 // MessageHeader is a header information for a message. | |
| 74 type MessageHeader struct { | |
| 75 Type uint32 | |
| 76 Flags uint32 | |
| 77 RequestId uint64 | |
| 78 } | |
| 79 | |
| 80 func (h *MessageHeader) Encode(encoder *Encoder) error { | |
| 81 encoder.StartStruct(h.dataSize(), h.version()) | |
| 82 if err := encoder.WriteUint32(h.Type); err != nil { | |
| 83 return err | |
| 84 } | |
| 85 if err := encoder.WriteUint32(h.Flags); err != nil { | |
| 86 return err | |
| 87 } | |
| 88 if h.Flags != MessageNoFlag { | |
| 89 if err := encoder.WriteUint64(h.RequestId); err != nil { | |
| 90 return err | |
| 91 } | |
| 92 } | |
| 93 return encoder.Finish() | |
| 94 } | |
| 95 | |
| 96 func (h *MessageHeader) Decode(decoder *Decoder) error { | |
| 97 header, err := decoder.StartStruct() | |
| 98 if err != nil { | |
| 99 return err | |
| 100 } | |
| 101 version := header.ElementsOrVersion | |
| 102 if version > 1 { | |
| 103 return &ValidationError{UnexpectedStructHeader, | |
| 104 fmt.Sprintf("invalid message header: it should be of ver
sion 0 or 1, but has %d", version), | |
| 105 } | |
| 106 } | |
| 107 expectedSize := uint32(dataHeaderSize + 2*4) | |
| 108 if version == 1 { | |
| 109 expectedSize += 8 | |
| 110 } | |
| 111 if expectedSize != header.Size { | |
| 112 return &ValidationError{UnexpectedStructHeader, | |
| 113 fmt.Sprintf("unexpected struct header size: expected %d,
but got %d", expectedSize, header.Size), | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 if h.Type, err = decoder.ReadUint32(); err != nil { | |
| 118 return err | |
| 119 } | |
| 120 if h.Flags, err = decoder.ReadUint32(); err != nil { | |
| 121 return err | |
| 122 } | |
| 123 if version == 1 { | |
| 124 if h.Flags != MessageExpectsResponseFlag && h.Flags != MessageIs
ResponseFlag { | |
| 125 return &ValidationError{MessageHeaderInvalidFlags, | |
| 126 fmt.Sprintf("message header flags(%v) should be
MessageExpectsResponseFlag or MessageIsResponseFlag", h.Flags), | |
| 127 } | |
| 128 } | |
| 129 if h.RequestId, err = decoder.ReadUint64(); err != nil { | |
| 130 return err | |
| 131 } | |
| 132 } else { | |
| 133 if h.Flags != MessageNoFlag { | |
| 134 return &ValidationError{MessageHeaderMissingRequestId, "
missing request ID in message header"} | |
| 135 } | |
| 136 } | |
| 137 return decoder.Finish() | |
| 138 } | |
| 139 | |
| 140 func (h *MessageHeader) dataSize() uint32 { | |
| 141 var size uint32 | |
| 142 size = 2 * 4 | |
| 143 if h.Flags != MessageNoFlag { | |
| 144 size += 8 | |
| 145 } | |
| 146 return size | |
| 147 } | |
| 148 | |
| 149 func (h *MessageHeader) version() uint32 { | |
| 150 if h.Flags != MessageNoFlag { | |
| 151 return 1 | |
| 152 } else { | |
| 153 return 0 | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // Message is a a raw message to be sent/received from a message pipe handle | |
| 158 // which contains a message header. | |
| 159 type Message struct { | |
| 160 Header MessageHeader | |
| 161 Bytes []byte | |
| 162 Handles []system.UntypedHandle | |
| 163 Payload []byte | |
| 164 } | |
| 165 | |
| 166 func newMessage(header MessageHeader, bytes []byte, handles []system.UntypedHand
le) *Message { | |
| 167 return &Message{header, bytes, handles, bytes[header.dataSize()+dataHead
erSize:]} | |
| 168 } | |
| 169 | |
| 170 // DecodePayload decodes the provided payload from the message. | |
| 171 func (m *Message) DecodePayload(payload Payload) error { | |
| 172 decoder := NewDecoder(m.Payload, m.Handles) | |
| 173 if err := payload.Decode(decoder); err != nil { | |
| 174 return err | |
| 175 } | |
| 176 return nil | |
| 177 } | |
| 178 | |
| 179 // EncodeMessage returns a message with provided header that has provided | |
| 180 // payload encoded in mojo archive format. | |
| 181 func EncodeMessage(header MessageHeader, payload Payload) (*Message, error) { | |
| 182 encoder := NewEncoder() | |
| 183 if err := header.Encode(encoder); err != nil { | |
| 184 return nil, err | |
| 185 } | |
| 186 if err := payload.Encode(encoder); err != nil { | |
| 187 return nil, err | |
| 188 } | |
| 189 if bytes, handles, err := encoder.Data(); err != nil { | |
| 190 return nil, err | |
| 191 } else { | |
| 192 return newMessage(header, bytes, handles), nil | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 // ParseMessage parses message header from byte buffer with attached handles | |
| 197 // and returnes parsed message. | |
| 198 func ParseMessage(bytes []byte, handles []system.UntypedHandle) (*Message, error
) { | |
| 199 decoder := NewDecoder(bytes, []system.UntypedHandle{}) | |
| 200 var header MessageHeader | |
| 201 if err := header.Decode(decoder); err != nil { | |
| 202 return nil, err | |
| 203 } | |
| 204 return newMessage(header, bytes, handles), nil | |
| 205 } | |
| OLD | NEW |