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