1 /* 2 * $HeadURL: /cvsroot/insight/Insight/remote-protocol/src/com/mindtree/insight/remoteprotocol/PacketDataSizeOverLimitsException.java,v $ 3 * $Date: 2005/08/09 18:39:17 $ 4 * $Revision: 1.1 $ 5 * $Author: m1001025 $ 6 * 7 * Copyright (c) 2005 MindTree Consulting Ltd. 8 * 9 * This file is part of Insight Remote Protocol Library. 10 * 11 * Insight Remote Protocol Library is free software: you can redistribute it 12 * and/or modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation, either version 3 of the License, 14 * or (at your option) any later version. 15 * 16 * Insight Remote Protocol Library is distributed in the hope that it will be 17 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 19 * Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along with 22 * Insight Remote Protocol Library. If not, see <http://www.gnu.org/licenses/>. 23 */ 24 25 package com.mindtree.techworks.insight.remoteprotocol.spi; 26 27 import java.io.Serializable; 28 29 import com.mindtree.techworks.insight.remoteprotocol.RemoteProtocolException; 30 import com.mindtree.techworks.insight.remoteprotocol.util.ByteUtils; 31 32 33 /** 34 * This is the common Header for all DataPackets. The format of the Packet 35 * Header is as follows 36 * 37 * <pre> 38 * 0 8 16 24 32 39 * | . . . . . . . | . . . . . . . | . . . . . . . | . . . . . . . | 40 * 41 * +---------------+---------------+-------------------------------+ 42 * | IDENTIFIER | VERSION | PHL | MESSAGE TYPE | 43 * +---------------+---------------+-------------------------------+ 44 * | FLAGS | 0xFF | HEADER CHECKSUM | 45 * +-------------------------------+-------------------------------+ 46 * | SOURCE IDENTIFIER | MESSAGE SEQUENCE | 47 * +-------------------------------+-------------------------------+ 48 * | DATA LENGTH | 49 * +---------------------------------------------------------------+ 50 * | DATA AND PADDING (Multiples of 8 bits) | 51 * < < 52 * > > 53 * | | 54 * +---------------------------------------------------------------+ 55 * 56 * | . . . . . . . | . . . . . . . | . . . . . . . | . . . . . . . | 57 * 0 8 16 24 32 58 * 59 * IDENTIFIER: A constant (01001001 / 0x49) identifying that the 60 * packet is an Insight packet. (The number is the 61 * ASCII for 'I') 62 * 63 * VERSION: The version of the packet. Currently 0x01 64 * 65 * PHL: Packet Header Length. Basically identifies the start 66 * of the data content 67 * 68 * MESSAGE TYPE: The identifier for the message. Currently the 69 * following will be used: 70 * 0x01 Startup The content in the Data field will contain the 71 * format specified. 72 * 0x02 Log Data The content will be data from the log event. 73 * 0x03 Shutdown The content will be empty. 74 * 75 * FLAGS: Currently Unused 76 * 77 * HEADER CHECKSUM: The checksum of the header with the checksum fields 78 * set to 0xFF. 79 * 80 * SOURCE IDENTIFIER: This will uniquely identify a source for a message. 81 * This field will be generated by the source (sender) 82 * and Insight will cache it on receipt of the first 83 * message from the source. All messages from the same 84 * source will be associated. 85 * 86 * MESSAGE SEQUENCE: The sequence number of the message. Ideally the 87 * Startup message will have the sequence number 0x00, 88 * and it will roll over after 0xFF. 89 * 90 * DATA LENGTH: Number of bytes in the data part. 91 * </pre> 92 * 93 * <p> 94 * For details on the different supported message types, see the static fields 95 * in the 96 * {@link com.mindtree.techworks.insight.remoteprotocol.spi.MessageType MessageType} 97 * class. 98 * </p> 99 * <p> 100 * The format of the data content for the different message types are: 101 * <ul> 102 * <li> <b>Startup Message:</b> See 103 * {@link com.mindtree.techworks.insight.remoteprotocol.spi.StartupMessageDataContent StartupMessageDataContent} 104 * </li> 105 * <li> <b>Log Message:</b> Byte representation of the string data</li> 106 * <li> <b>Shutdown Message:</b> No content</li> 107 * </ul> 108 * </p> 109 * 110 * @see com.mindtree.techworks.insight.remoteprotocol.spi.DataPacket 111 * @author <a href="mailto:bindul_bhowmik@mindtree.com">Bindul Bhowmik</a> 112 * @version $Revision: 1.1 $ $Date: 2005/08/03 14:39:18 $ 113 */ 114 public class PacketHeader implements Serializable { 115 116 // ------------------------------------------------------------------------- 117 // Constants 118 // ------------------------------------------------------------------------- 119 120 /** 121 * The serial version UID of the class 122 */ 123 private static final long serialVersionUID = 819535169935681001L; 124 125 /** 126 * The identifier for an Insight Packet. Always ASCII - <code>I</code> 127 */ 128 public static final byte INSIGHT_PACKET_IDENTIFIER = 0x49; 129 130 /** 131 * The packet header length for this version. 132 */ 133 public static final byte PACKET_HEADER_LENGTH = 16; 134 135 // ------------------------------------------------------------------------- 136 // Instance variables 137 // ------------------------------------------------------------------------- 138 139 /** 140 * The version of the packet / packet header. Currently 1 141 */ 142 private byte version = 1; 143 144 /** 145 * The length of the packet header. For version 1, it is a fixed 16 bytes 146 */ 147 private byte packetHeaderLength; 148 149 /** 150 * The message type. For the different types of messages, see the 151 * {@link PacketDataContent PacketDataContent} class. 152 */ 153 private MessageType messageType; 154 155 /** 156 * The flags for the message. Curently message dependent 157 */ 158 private byte flags; 159 160 /** 161 * The checksum of all the fields of the header except the checksum field 162 * (set to 0xFF) 163 */ 164 private short headerChecksum; 165 166 /** 167 * The unique identifier for the source of the message. Should be different 168 * for each source and namespace within the source. 169 */ 170 private short sourceIdentifier; 171 172 /** 173 * The sequence number of the message. 174 */ 175 private short messageSequence; 176 177 /** 178 * Length of data in the message. 179 */ 180 private int dataLength; 181 182 // ------------------------------------------------------------------------- 183 // Constructors 184 // ------------------------------------------------------------------------- 185 186 /** 187 * Creates an instance of the packet header 188 */ 189 public PacketHeader () { 190 191 // No Args constructor 192 } 193 194 /** 195 * Creates an instance of the header from the byte array passed in. 196 * 197 * @param packetData The byte array representing the header 198 * @throws RemoteProtocolException If the header is not well formatted. 199 */ 200 public PacketHeader (byte [] packetData) throws RemoteProtocolException { 201 202 // Check our favourite constant 203 if (packetData[0] != INSIGHT_PACKET_IDENTIFIER) { 204 throw new RemoteProtocolException( 205 "Specified data not of Insight Connector Packet type"); 206 } 207 208 this.version = packetData[1]; 209 210 // We support only version 1 211 if (version != 0x01) { 212 throw new RemoteProtocolException("Unsupported packet version"); 213 } 214 215 this.packetHeaderLength = packetData[2]; 216 this.messageType = MessageType.getMessageTypeForByte(packetData[3]); 217 this.flags = packetData[4]; 218 219 this.headerChecksum = ByteUtils.readShortFromByteArray(packetData, 6); 220 this.sourceIdentifier = ByteUtils.readShortFromByteArray(packetData, 8); 221 this.messageSequence = ByteUtils.readShortFromByteArray(packetData, 10); 222 this.dataLength = ByteUtils.readIntFromByteArray(packetData, 12); 223 224 // Check checksum and see if we are fine 225 if (this.headerChecksum != calculateHeaderChecksum()) { 226 throw new RemoteProtocolException( 227 "Corrupted Header: Header Checksum does not match."); 228 } 229 } 230 231 // ------------------------------------------------------------------------- 232 // Accessors 233 // ------------------------------------------------------------------------- 234 235 /** 236 * Returns the dataLength 237 * 238 * @return Returns the dataLength. 239 */ 240 public int getDataLength () { 241 242 return dataLength; 243 } 244 245 246 /** 247 * Sets the dataLength 248 * 249 * @param dataLength The dataLength to set. 250 */ 251 public void setDataLength (int dataLength) { 252 253 this.dataLength = dataLength; 254 } 255 256 257 /** 258 * Returns the flags 259 * 260 * @return Returns the flags. 261 */ 262 public byte getFlags () { 263 264 return flags; 265 } 266 267 268 /** 269 * Sets the flags 270 * 271 * @param flags The flags to set. 272 */ 273 public void setFlags (byte flags) { 274 275 this.flags = flags; 276 } 277 278 279 /** 280 * Returns the messageSequence 281 * 282 * @return Returns the messageSequence. 283 */ 284 public short getMessageSequence () { 285 286 return messageSequence; 287 } 288 289 290 /** 291 * Sets the messageSequence 292 * 293 * @param messageSequence The messageSequence to set. 294 */ 295 public void setMessageSequence (short messageSequence) { 296 297 this.messageSequence = messageSequence; 298 } 299 300 301 /** 302 * Returns the messageType 303 * 304 * @return Returns the messageType. 305 */ 306 public MessageType getMessageType () { 307 308 return messageType; 309 } 310 311 312 /** 313 * Sets the messageType 314 * 315 * @param messageType The messageType to set. 316 */ 317 public void setMessageType (MessageType messageType) { 318 319 this.messageType = messageType; 320 } 321 322 323 /** 324 * Returns the sourceIdentifier 325 * 326 * @return Returns the sourceIdentifier. 327 */ 328 public short getSourceIdentifier () { 329 330 return sourceIdentifier; 331 } 332 333 334 /** 335 * Sets the sourceIdentifier 336 * 337 * @param sourceIdentifier The sourceIdentifier to set. 338 */ 339 public void setSourceIdentifier (short sourceIdentifier) { 340 341 this.sourceIdentifier = sourceIdentifier; 342 } 343 344 345 /** 346 * Returns the version 347 * 348 * @return Returns the version. 349 */ 350 public byte getVersion () { 351 352 return version; 353 } 354 355 356 /** 357 * Sets the version 358 * 359 * @param version The version to set. 360 */ 361 public void setVersion (byte version) { 362 363 this.version = version; 364 } 365 366 367 /** 368 * Returns the headerChecksum 369 * 370 * @return Returns the headerChecksum. 371 */ 372 public short getHeaderChecksum () { 373 374 return headerChecksum; 375 } 376 377 378 /** 379 * Returns the packetHeaderLength 380 * 381 * @return Returns the packetHeaderLength. 382 */ 383 public byte getPacketHeaderLength () { 384 385 return packetHeaderLength; 386 } 387 388 // ------------------------------------------------------------------------- 389 // Public methods 390 // ------------------------------------------------------------------------- 391 392 /** 393 * Gets the packet Header as a byte array 394 * 395 * @return A <code>byte</code> array containing the data from the header. 396 */ 397 public byte [] getPacketHeaderAsByteArray () { 398 399 if (this.packetHeaderLength == 0) { 400 this.packetHeaderLength = PACKET_HEADER_LENGTH; 401 } 402 403 byte [] packetHeaderData = new byte [this.packetHeaderLength]; 404 405 packetHeaderData[0] = INSIGHT_PACKET_IDENTIFIER; 406 packetHeaderData[1] = 0x01; 407 packetHeaderData[2] = this.packetHeaderLength; 408 packetHeaderData[3] = this.messageType.getType(); 409 410 packetHeaderData[4] = this.flags; 411 packetHeaderData[5] = (byte) 0xFF; 412 // packetHeaderData[6] = (byte) ((this.headerChecksum >> 8) & 0x00FF); 413 // packetHeaderData[7] = (byte) (this.headerChecksum & 0x00FF); 414 ByteUtils.putBytesInArrayForShort(this.headerChecksum, 415 packetHeaderData, 6); 416 417 // packetHeaderData[8] = (byte) ((this.sourceIdentifier >> 8) & 0x00FF); 418 // packetHeaderData[9] = (byte) this.sourceIdentifier; 419 ByteUtils.putBytesInArrayForShort(this.sourceIdentifier, 420 packetHeaderData, 8); 421 // packetHeaderData[10] = (byte) ((this.messageSequence >> 8) & 0x00FF); 422 // packetHeaderData[11] = (byte) this.messageSequence; 423 ByteUtils.putBytesInArrayForShort(this.messageSequence, 424 packetHeaderData, 10); 425 426 // packetHeaderData[12] = (byte) ((this.dataLength >> 24) & 0x000000FF); 427 // packetHeaderData[13] = (byte) ((this.dataLength >> 16) & 0x000000FF); 428 // packetHeaderData[14] = (byte) ((this.dataLength >> 8) & 0x000000FF); 429 // packetHeaderData[15] = (byte) (this.dataLength & 0x000000FF); 430 ByteUtils.putBytesInArrayForInt(this.dataLength, packetHeaderData, 12); 431 432 return packetHeaderData; 433 } 434 435 /** 436 * Recalculates the Header for this packet using the PacketDataContent field 437 * passed in. The only field in the header directly dependent on the content 438 * of the packet is the <code>DATA LENGTH</code> field. However changing 439 * this field changes the <code>HEADER CHECKSUM</code>, hence this method 440 * changes the checksum too. In later versions of the 441 * <code>DataPacket</code> if variable length headers are allowed, then 442 * the <code>PHL</code> field would also be set in this method. 443 * 444 * @param content The data content accompanying this packet header 445 */ 446 public void recalculateHeader (PacketDataContent content) { 447 448 this.dataLength = content.getLength(); 449 if (this.packetHeaderLength == 0) { 450 this.packetHeaderLength = PACKET_HEADER_LENGTH; 451 } 452 this.headerChecksum = calculateHeaderChecksum(); 453 454 } 455 456 // ------------------------------------------------------------------------- 457 // Util Methods 458 // ------------------------------------------------------------------------- 459 /** 460 * Calculates and returns the checksum for this header from the fields set. 461 * 462 * @return The checksum of the header 463 */ 464 private short calculateHeaderChecksum () { 465 466 // TODO Implement 467 return 0; 468 } 469 470 }