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 |
| 187 MessageHeader other = (MessageHeader) object; |
| 188 if (mDataHeader == null) { |
| 189 if (other.mDataHeader != null) { |
| 190 return false; |
| 191 } |
| 192 } else { |
| 193 if (!mDataHeader.equals(other.mDataHeader)) { |
| 194 return false; |
| 195 } |
| 196 } |
| 197 |
| 198 return (mFlags == other.mFlags && |
| 199 mRequestId == other.mRequestId && |
| 200 mType == other.mType); |
| 201 } |
| 202 |
| 203 /** |
| 204 * Set the request id on the message contained in the given buffer. |
| 205 */ |
| 206 void setRequestId(ByteBuffer buffer, long requestId) { |
| 207 assert mustHaveRequestId(buffer.getInt(FLAGS_OFFSET)); |
| 208 buffer.putLong(REQUEST_ID_OFFSET, requestId); |
| 209 mRequestId = requestId; |
| 210 } |
| 211 |
| 212 /** |
| 213 * Returns whether a message with the given flags must have a request Id. |
| 214 */ |
| 215 private static boolean mustHaveRequestId(int flags) { |
| 216 return (flags & (MESSAGE_EXPECTS_RESPONSE_FLAG | MESSAGE_IS_RESPONSE_FLA
G)) != 0; |
| 217 } |
| 218 |
| 219 /** |
| 220 * Validate that the given {@link DataHeader} can be the data header of a me
ssage header. |
| 221 */ |
| 222 private static void validateDataHeader(DataHeader dataHeader) { |
| 223 if (dataHeader.numFields < SIMPLE_MESSAGE_NUM_FIELDS) { |
| 224 throw new DeserializationException( |
| 225 "Incorrect number of fields, expecting at least " + SIMPLE_M
ESSAGE_NUM_FIELDS |
| 226 + ", but got: " + dataHeader.numFields); |
| 227 } |
| 228 if (dataHeader.size < SIMPLE_MESSAGE_SIZE) { |
| 229 throw new DeserializationException( |
| 230 "Incorrect message size, expecting at least " + SIMPLE_MESSA
GE_SIZE |
| 231 + ", but got: " + dataHeader.size); |
| 232 } |
| 233 if (dataHeader.numFields == SIMPLE_MESSAGE_NUM_FIELDS |
| 234 && dataHeader.size != SIMPLE_MESSAGE_SIZE) { |
| 235 throw new DeserializationException( |
| 236 "Incorrect message size for a message with " + SIMPLE_MESSAG
E_NUM_FIELDS |
| 237 + " fields, expecting " + SIMPLE_MESSAGE_SIZE + ", but got:
" |
| 238 + dataHeader.size); |
| 239 } |
| 240 if (dataHeader.numFields == MESSAGE_WITH_REQUEST_ID_NUM_FIELDS |
| 241 && dataHeader.size != MESSAGE_WITH_REQUEST_ID_SIZE) { |
| 242 throw new DeserializationException( |
| 243 "Incorrect message size for a message with " |
| 244 + MESSAGE_WITH_REQUEST_ID_NUM_FIELDS + " fields, expecting " |
| 245 + MESSAGE_WITH_REQUEST_ID_SIZE + ", but got: " + dataHeader.
size); |
| 246 } |
| 247 } |
| 248 |
| 249 } |
OLD | NEW |