View Javadoc

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   *     &lt;                                                               &lt;
52   *      &gt;                                                               &gt;
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 }