OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 org.chromium.mojo.bindings; | |
6 | |
7 import java.nio.ByteBuffer; | |
8 | |
9 /** | |
10 * Header information for a message. | |
11 */ | |
12 public class MessageHeader { | |
13 | |
14 private static final int SIMPLE_MESSAGE_SIZE = 16; | |
15 private static final int SIMPLE_MESSAGE_VERSION = 0; | |
16 private static final DataHeader SIMPLE_MESSAGE_STRUCT_INFO = | |
17 new DataHeader(SIMPLE_MESSAGE_SIZE, SIMPLE_MESSAGE_VERSION); | |
18 | |
19 private static final int MESSAGE_WITH_REQUEST_ID_SIZE = 24; | |
20 private static final int MESSAGE_WITH_REQUEST_ID_VERSION = 1; | |
21 private static final DataHeader MESSAGE_WITH_REQUEST_ID_STRUCT_INFO = | |
22 new DataHeader(MESSAGE_WITH_REQUEST_ID_SIZE, MESSAGE_WITH_REQUEST_ID
_VERSION); | |
23 | |
24 private static final int TYPE_OFFSET = 8; | |
25 private static final int FLAGS_OFFSET = 12; | |
26 private static final int REQUEST_ID_OFFSET = 16; | |
27 | |
28 /** | |
29 * Flag for a header of a simple message. | |
30 */ | |
31 public static final int NO_FLAG = 0; | |
32 | |
33 /** | |
34 * Flag for a header of a message that expected a response. | |
35 */ | |
36 public static final int MESSAGE_EXPECTS_RESPONSE_FLAG = 1 << 0; | |
37 | |
38 /** | |
39 * Flag for a header of a message that is a response. | |
40 */ | |
41 public static final int MESSAGE_IS_RESPONSE_FLAG = 1 << 1; | |
42 | |
43 private final DataHeader mDataHeader; | |
44 private final int mType; | |
45 private final int mFlags; | |
46 private long mRequestId; | |
47 | |
48 /** | |
49 * Constructor for the header of a message which does not have a response. | |
50 */ | |
51 public MessageHeader(int type) { | |
52 mDataHeader = SIMPLE_MESSAGE_STRUCT_INFO; | |
53 mType = type; | |
54 mFlags = 0; | |
55 mRequestId = 0; | |
56 } | |
57 | |
58 /** | |
59 * Constructor for the header of a message which have a response or being it
self a response. | |
60 */ | |
61 public MessageHeader(int type, int flags, long requestId) { | |
62 assert mustHaveRequestId(flags); | |
63 mDataHeader = MESSAGE_WITH_REQUEST_ID_STRUCT_INFO; | |
64 mType = type; | |
65 mFlags = flags; | |
66 mRequestId = requestId; | |
67 } | |
68 | |
69 /** | |
70 * Constructor, parsing the header from a message. Should only be used by {@
link Message} | |
71 * itself. | |
72 */ | |
73 MessageHeader(Message message) { | |
74 Decoder decoder = new Decoder(message); | |
75 mDataHeader = decoder.readDataHeader(); | |
76 validateDataHeader(mDataHeader); | |
77 mType = decoder.readInt(TYPE_OFFSET); | |
78 mFlags = decoder.readInt(FLAGS_OFFSET); | |
79 if (mustHaveRequestId(mFlags)) { | |
80 if (mDataHeader.size < MESSAGE_WITH_REQUEST_ID_SIZE) { | |
81 throw new DeserializationException("Incorrect message size, expe
cting at least " | |
82 + MESSAGE_WITH_REQUEST_ID_SIZE | |
83 + " for a message with a request identifier, but got: "
+ mDataHeader.size); | |
84 | |
85 } | |
86 mRequestId = decoder.readLong(REQUEST_ID_OFFSET); | |
87 } else { | |
88 mRequestId = 0; | |
89 } | |
90 } | |
91 | |
92 /** | |
93 * Returns the size in bytes of the serialization of the header. | |
94 */ | |
95 public int getSize() { | |
96 return mDataHeader.size; | |
97 } | |
98 | |
99 /** | |
100 * Returns the type of the message. | |
101 */ | |
102 public int getType() { | |
103 return mType; | |
104 } | |
105 | |
106 /** | |
107 * Returns the flags associated to the message. | |
108 */ | |
109 public int getFlags() { | |
110 return mFlags; | |
111 } | |
112 | |
113 /** | |
114 * Returns if the message has the given flag. | |
115 */ | |
116 public boolean hasFlag(int flag) { | |
117 return (mFlags & flag) == flag; | |
118 } | |
119 | |
120 /** | |
121 * Returns if the message has a request id. | |
122 */ | |
123 public boolean hasRequestId() { | |
124 return mustHaveRequestId(mFlags); | |
125 } | |
126 | |
127 /** | |
128 * Return the request id for the message. Must only be called if the message
has a request id. | |
129 */ | |
130 public long getRequestId() { | |
131 assert hasRequestId(); | |
132 return mRequestId; | |
133 } | |
134 | |
135 /** | |
136 * Encode the header. | |
137 */ | |
138 public void encode(Encoder encoder) { | |
139 encoder.encode(mDataHeader); | |
140 encoder.encode(getType(), TYPE_OFFSET); | |
141 encoder.encode(getFlags(), FLAGS_OFFSET); | |
142 if (hasRequestId()) { | |
143 encoder.encode(getRequestId(), REQUEST_ID_OFFSET); | |
144 } | |
145 } | |
146 | |
147 /** | |
148 * Returns true if the header has the expected flags. Only considers flags t
his class knows | |
149 * about in order to allow this class to work with future version of the hea
der format. | |
150 */ | |
151 public boolean validateHeader(int expectedFlags) { | |
152 int knownFlags = getFlags() & (MESSAGE_EXPECTS_RESPONSE_FLAG | MESSAGE_I
S_RESPONSE_FLAG); | |
153 return knownFlags == expectedFlags; | |
154 } | |
155 | |
156 /** | |
157 * Returns true if the header has the expected type and flags. Only consider
flags this class | |
158 * knows about in order to allow this class to work with future version of t
he header format. | |
159 */ | |
160 public boolean validateHeader(int expectedType, int expectedFlags) { | |
161 return getType() == expectedType && validateHeader(expectedFlags); | |
162 } | |
163 | |
164 /** | |
165 * @see Object#hashCode() | |
166 */ | |
167 @Override | |
168 public int hashCode() { | |
169 final int prime = 31; | |
170 int result = 1; | |
171 result = prime * result + ((mDataHeader == null) ? 0 : mDataHeader.hashC
ode()); | |
172 result = prime * result + mFlags; | |
173 result = prime * result + (int) (mRequestId ^ (mRequestId >>> 32)); | |
174 result = prime * result + mType; | |
175 return result; | |
176 } | |
177 | |
178 /** | |
179 * @see Object#equals(Object) | |
180 */ | |
181 @Override | |
182 public boolean equals(Object object) { | |
183 if (object == this) return true; | |
184 if (object == null) return false; | |
185 if (getClass() != object.getClass()) return false; | |
186 | |
187 MessageHeader other = (MessageHeader) object; | |
188 return (BindingsHelper.equals(mDataHeader, other.mDataHeader) | |
189 && mFlags == other.mFlags | |
190 && mRequestId == other.mRequestId | |
191 && mType == other.mType); | |
192 } | |
193 | |
194 /** | |
195 * Set the request id on the message contained in the given buffer. | |
196 */ | |
197 void setRequestId(ByteBuffer buffer, long requestId) { | |
198 assert mustHaveRequestId(buffer.getInt(FLAGS_OFFSET)); | |
199 buffer.putLong(REQUEST_ID_OFFSET, requestId); | |
200 mRequestId = requestId; | |
201 } | |
202 | |
203 /** | |
204 * Returns whether a message with the given flags must have a request Id. | |
205 */ | |
206 private static boolean mustHaveRequestId(int flags) { | |
207 return (flags & (MESSAGE_EXPECTS_RESPONSE_FLAG | MESSAGE_IS_RESPONSE_FLA
G)) != 0; | |
208 } | |
209 | |
210 /** | |
211 * Validate that the given {@link DataHeader} can be the data header of a me
ssage header. | |
212 */ | |
213 private static void validateDataHeader(DataHeader dataHeader) { | |
214 if (dataHeader.elementsOrVersion < SIMPLE_MESSAGE_VERSION) { | |
215 throw new DeserializationException("Incorrect number of fields, expe
cting at least " | |
216 + SIMPLE_MESSAGE_VERSION + ", but got: " + dataHeader.elemen
tsOrVersion); | |
217 } | |
218 if (dataHeader.size < SIMPLE_MESSAGE_SIZE) { | |
219 throw new DeserializationException( | |
220 "Incorrect message size, expecting at least " + SIMPLE_MESSA
GE_SIZE | |
221 + ", but got: " + dataHeader.size); | |
222 } | |
223 if (dataHeader.elementsOrVersion == SIMPLE_MESSAGE_VERSION | |
224 && dataHeader.size != SIMPLE_MESSAGE_SIZE) { | |
225 throw new DeserializationException("Incorrect message size for a mes
sage with " | |
226 + SIMPLE_MESSAGE_VERSION + " fields, expecting " + SIMPLE_ME
SSAGE_SIZE | |
227 + ", but got: " + dataHeader.size); | |
228 } | |
229 if (dataHeader.elementsOrVersion == MESSAGE_WITH_REQUEST_ID_VERSION | |
230 && dataHeader.size != MESSAGE_WITH_REQUEST_ID_SIZE) { | |
231 throw new DeserializationException("Incorrect message size for a mes
sage with " | |
232 + MESSAGE_WITH_REQUEST_ID_VERSION + " fields, expecting " | |
233 + MESSAGE_WITH_REQUEST_ID_SIZE + ", but got: " + dataHeader.
size); | |
234 } | |
235 } | |
236 | |
237 } | |
OLD | NEW |