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 |