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