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 }