KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > net > protocol > transport > WireProtocolHeader


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.net.protocol.transport;
5
6 import com.tc.bytes.TCByteBuffer;
7 import com.tc.net.protocol.AbstractTCNetworkHeader;
8 import com.tc.net.protocol.TCNetworkMessage;
9 import com.tc.net.protocol.delivery.OOOProtocolMessage;
10 import com.tc.net.protocol.tcm.TCMessage;
11 import com.tc.util.Conversion;
12
13 /**
14  * This class models the header portion of a TC wire protocol message. NOTE: This class makes no attempt to be thread
15  * safe! All concurrent access must be syncronized
16  *
17  * <pre>
18  * 0 1 2 3
19  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
20  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21  * |Version| HL |Type of Service| Time to Live | Protocol |
22  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23  * | Magic number |
24  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25  * | 32 Bit Total Length |
26  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27  * | Alder32 Header Checksum |
28  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29  * | Source Address |
30  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31  * | Destination Address |
32  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33  * | Source Port | Destination Port |
34  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35  * | Options | Padding |
36  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37  * </pre>
38  *
39  * @author teck
40  */

41
42 public class WireProtocolHeader extends AbstractTCNetworkHeader {
43   public static final byte VERSION_1 = 1;
44   public static final byte[] VALID_VERSIONS = new byte[] { VERSION_1 };
45
46   public static final short DEFAULT_TTL = 64;
47
48   public static final short PROTOCOL_UNKNOWN = 0;
49   public static final short PROTOCOL_TCM = 1;
50   public static final short PROTOCOL_TRANSPORT_HANDSHAKE = 2;
51   public static final short PROTOCOL_OOOP = 3;
52
53   private static final int MAGIC_NUM = 0xAAAAAAAA;
54
55   public static final short[] VALID_PROTOCOLS = new short[] { PROTOCOL_TCM, PROTOCOL_TRANSPORT_HANDSHAKE,
56       PROTOCOL_OOOP };
57
58   // 15 32-bit words max
59
static final short MAX_LENGTH = 15 * 4;
60
61   // 7 32-bit words min
62
static final short MIN_LENGTH = 7 * 4;
63
64   public static short getProtocolForMessageClass(TCNetworkMessage msg) {
65     // TODO: is there a better way to do this (ie. not using instanceof)?
66
if (msg instanceof TCMessage) {
67       return PROTOCOL_TCM;
68     } else if (msg instanceof OOOProtocolMessage) { return PROTOCOL_OOOP; }
69
70     throw new AssertionError JavaDoc("Unknown protocol");
71   }
72
73   public WireProtocolHeader() {
74     super(MIN_LENGTH, MAX_LENGTH);
75
76     setMagicNum(MAGIC_NUM);
77     setVersion(VERSION_1);
78     setHeaderLength((byte) (MIN_LENGTH / 4));
79     setTimeToLive(DEFAULT_TTL);
80     setTypeOfService(TypeOfService.DEFAULT_TOS.getByteValue());
81   }
82
83   public WireProtocolHeader(TCByteBuffer buffer) {
84     super(buffer, MIN_LENGTH, MAX_LENGTH);
85   }
86
87   private void setMagicNum(int magic_num2) {
88     data.putInt(4, MAGIC_NUM);
89   }
90
91   public void setVersion(byte version) {
92     if ((version <= 0) || (version > 15)) { throw new IllegalArgumentException JavaDoc("invalid version: " + version); }
93
94     set4BitValue(0, true, version);
95   }
96
97   protected void setHeaderLength(short length) {
98     if ((length < 6) || (length > 15)) { throw new IllegalArgumentException JavaDoc("Header length must in range 6-15"); }
99
100     set4BitValue(0, false, (byte) length);
101   }
102
103   public void setTypeOfService(short tos) {
104     data.putUbyte(1, tos);
105   }
106
107   public void setTimeToLive(short ttl) {
108     data.putUbyte(2, ttl);
109   }
110
111   public void setProtocol(short protocol) {
112     data.putUbyte(3, protocol);
113   }
114
115   public void setTotalPacketLength(int length) {
116     data.putInt(8, length);
117   }
118
119   public void setSourceAddress(byte[] srcAddr) {
120     data.put(16, srcAddr, 0, 4);
121   }
122
123   public void setDestinationAddress(byte[] destAddr) {
124     data.put(20, destAddr, 0, 4);
125   }
126
127   public void setSourcePort(int srcPort) {
128     data.putUshort(24, srcPort);
129   }
130
131   public void setDestinationPort(int dstPort) {
132     data.putUshort(26, dstPort);
133   }
134
135   public int getMagicNum() {
136     return data.getInt(4);
137   }
138
139   public byte getVersion() {
140     return get4BitValue(0, true);
141   }
142
143   public byte getHeaderLength() {
144     return get4BitValue(0, false);
145   }
146
147   public short getTypeOfService() {
148     return data.getUbyte(1);
149   }
150
151   public short getTimeToLive() {
152     return data.getUbyte(2);
153   }
154
155   public short getProtocol() {
156     return data.getUbyte(3);
157   }
158
159   public int getTotalPacketLength() {
160     return data.getInt(8);
161   }
162
163   public long getChecksum() {
164     return data.getUint(12);
165   }
166
167   public byte[] getSourceAddress() {
168     return getBytes(16, 4);
169   }
170
171   public byte[] getDestinationAddress() {
172     return getBytes(20, 4);
173   }
174
175   public int getSourcePort() {
176     return data.getUshort(24);
177   }
178
179   public int getDestinationPort() {
180     return data.getUshort(26);
181   }
182
183   public void computeChecksum() {
184     computeAdler32Checksum(12, true);
185   }
186
187   public boolean isChecksumValid() {
188     return getChecksum() == computeAdler32Checksum(12, false);
189   }
190
191   public void validate() throws WireProtocolHeaderFormatException {
192     // validate the magic num
193
int magic = getMagicNum();
194     if (magic != MAGIC_NUM) { throw new WireProtocolHeaderFormatException("Invalid magic number: " + magic + " != "
195                                                                           + MAGIC_NUM); }
196
197     // validate the version byte
198
boolean validVersion = false;
199     byte version = getVersion();
200
201     for (int i = 0; i < VALID_VERSIONS.length; i++) {
202       if (version == VALID_VERSIONS[i]) {
203         validVersion = true;
204         break;
205       }
206     }
207
208     if (!validVersion) { throw new WireProtocolHeaderFormatException("Bad Version: " + Conversion.byte2uint(version)); }
209
210     // TODO: validate the TOS byte
211

212     // validate the TTL byte
213
int ttl = getTimeToLive();
214     if (0 == ttl) { throw new WireProtocolHeaderFormatException("TTL byte cannot be equal to zero"); }
215
216     // validate the protocol byte
217
boolean validProtocol = false;
218     short protocol = getProtocol();
219
220     for (int i = 0; i < VALID_PROTOCOLS.length; i++) {
221       if (protocol == VALID_PROTOCOLS[i]) {
222         validProtocol = true;
223         break;
224       }
225     }
226
227     if (!validProtocol) { throw new WireProtocolHeaderFormatException("Bad Protocol byte: " + protocol); }
228
229     // validate the total packet length value
230
int totalLength = getTotalPacketLength();
231
232     if (totalLength < MIN_LENGTH) { throw new WireProtocolHeaderFormatException(
233                                                                                 "Total length ("
234                                                                                                                                                                 + totalLength
235                                                                                                                                                                 + ") can not be less than minimum header size ("
236                                                                                                                                                                 + MIN_LENGTH
237                                                                                                                                                                 + ")"); }
238
239     if (totalLength < getHeaderByteLength()) { throw new WireProtocolHeaderFormatException(
240                                                                                            "Total length ("
241                                                                                                                                                                                       + totalLength
242                                                                                                                                                                                       + ") can not be less than actual header length ("
243                                                                                                                                                                                       + getHeaderByteLength()
244                                                                                                                                                                                       + ")"); }
245
246     // validate the checksum
247
if (!isChecksumValid()) { throw new WireProtocolHeaderFormatException("Invalid Checksum"); }
248
249     if (getSourcePort() == 0) { throw new WireProtocolHeaderFormatException("Source port cannot be zero"); }
250
251     if (getDestinationPort() == 0) { throw new WireProtocolHeaderFormatException("Destination port cannot be zero"); }
252
253     // if (Arrays.equals(getDestinationAddress(), FOUR_ZERO_BYTES)) { throw new WireProtocolHeaderFormatException(
254
// "Destination address cannot be 0.0.0.0"); }
255
//
256
// if (Arrays.equals(getSourceAddress(), FOUR_ZERO_BYTES)) { throw new WireProtocolHeaderFormatException(
257
// "Source address cannot be 0.0.0.0"); }
258

259     // TODO: validate options (once they exist)
260
}
261
262   public String JavaDoc toString() {
263     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
264     buf.append("Version: ").append(Conversion.byte2uint(getVersion())).append(", ");
265     buf.append("Header Length: ").append(Conversion.byte2uint(getHeaderLength())).append(", ");
266     buf.append("TOS: ").append(getTypeOfService()).append(", ");
267     buf.append("TTL: ").append(getTimeToLive()).append(", ");
268     buf.append("Protocol: ").append(getProtocolString());
269     buf.append("\n");
270     buf.append("Total Packet Length: ").append(getTotalPacketLength()).append("\n");
271     buf.append("Adler32 Checksum: ").append(getChecksum()).append(" (valid: ").append(isChecksumValid()).append(")\n");
272     buf.append("Source Addresss: ");
273
274     byte src[] = getSourceAddress();
275     byte dest[] = getDestinationAddress();
276
277     for (int i = 0; i < src.length; i++) {
278       buf.append(Conversion.byte2uint(src[i]));
279       if (i != (src.length - 1)) {
280         buf.append(".");
281       }
282     }
283     buf.append("\n");
284
285     buf.append("Destination Addresss: ");
286     for (int i = 0; i < dest.length; i++) {
287       buf.append(Conversion.byte2uint(dest[i]));
288       if (i != (dest.length - 1)) {
289         buf.append(".");
290       }
291     }
292     buf.append("\n");
293
294     buf.append("Source Port: ").append(getSourcePort());
295     buf.append(", Destination Port: ").append(getDestinationPort());
296     buf.append("\n");
297
298     String JavaDoc errMsg = "no message";
299     boolean valid = true;
300     try {
301       validate();
302     } catch (WireProtocolHeaderFormatException e) {
303       errMsg = e.getMessage();
304       valid = false;
305     }
306     buf.append("Header Validity: ").append(valid).append(" (").append(errMsg).append(")\n");
307
308     // TODO: display the options (if any)
309

310     return buf.toString();
311   }
312
313   private String JavaDoc getProtocolString() {
314     final short protocol = getProtocol();
315     switch (protocol) {
316       case PROTOCOL_TCM: {
317         return "TCM";
318       }
319       case PROTOCOL_OOOP: {
320         return "OOOP";
321       }
322       case PROTOCOL_TRANSPORT_HANDSHAKE: {
323         return "TRANSPORT HANDSHAKE";
324       }
325       default: {
326         return "UNKNOWN (" + protocol + ")";
327       }
328     }
329   }
330
331   public int getMaxByteLength() {
332     return WireProtocolHeader.MAX_LENGTH;
333   }
334
335   public int getMinByteLength() {
336     return WireProtocolHeader.MIN_LENGTH;
337   }
338
339   public int getHeaderByteLength() {
340     return 4 * getHeaderLength();
341   }
342
343   public boolean isTransportHandshakeMessage() {
344     return getProtocol() == PROTOCOL_TRANSPORT_HANDSHAKE;
345   }
346 }
Popular Tags