001: // ICPMessage.java
002: // $Id: ICPMessage.java,v 1.5 2000/08/16 21:38:04 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1996.
004: // please first read the full copyright statement in file COPYRIGHT.HTML
005:
006: package org.w3c.www.protocol.http.icp;
007:
008: import java.net.DatagramPacket;
009: import java.net.InetAddress;
010: import java.net.URL;
011:
012: class ICPMessage implements ICP {
013: /**
014: * The ICP opcde for that message.
015: */
016: protected int opcode = -1;
017: /**
018: * The ICP major version of the message.
019: */
020: protected int version = -1;
021: /**
022: * The identifier of the message.
023: */
024: protected int id = -1;
025: /**
026: * The options for this message.
027: */
028: protected int options = 0;
029: /**
030: * The InetAddress of the sender or <strong>null</strong> otherwise.
031: */
032: protected InetAddress addr = null;
033: /**
034: * The port number of the sender of that message, or <strong>-1</strong>
035: * if that message was created locally.
036: */
037: protected int port = -1;
038: /**
039: * The URL of the message.
040: */
041: URL url = null;
042:
043: /**
044: * Parse the given datagram into an ICP message.
045: * @exception ICPProtocolException If that reply doesn't conform to ICP
046: * protocol.
047: */
048:
049: protected static ICPMessage parse(DatagramPacket p)
050: throws ICPProtocolException {
051: byte buf[] = p.getData();
052: int len = p.getLength();
053: if (len < 4)
054: throw new ICPProtocolException(
055: "Invalid ICP datagram length");
056: InetAddress addr = p.getAddress();
057: int port = p.getPort();
058: // Decode the first word:
059: int opcode = buf[0];
060: int version = buf[1];
061: int plen = (((buf[2] & 0xff) << 8) + (buf[3] & 0xff));
062: if (plen != len)
063: throw new ICPProtocolException("Didn't got full message: "
064: + len + "/" + plen);
065: // Construct an appropriate message:
066: ICPMessage msg = null;
067: switch (opcode) {
068: case ICP_OP_QUERY:
069: msg = new ICPQuery(addr, port, opcode, version, buf, 4, len);
070: break;
071: case ICP_OP_HIT:
072: case ICP_OP_MISS:
073: msg = new ICPReply(addr, port, opcode, version, buf, 4, len);
074: break;
075: default:
076: throw new ICPProtocolException("Unsupported opcode: "
077: + opcode);
078: }
079: return msg;
080: }
081:
082: protected int parse(byte buf[], int off, int len)
083: throws ICPProtocolException {
084: // Decode the request identifier:
085: this .id = (((buf[off] & 0xff) << 24)
086: + ((buf[off + 1] & 0xff) << 16)
087: + ((buf[off + 2] & 0xff) << 8) + ((buf[off + 3] & 0xff) << 0));
088: off += 4;
089: // Decode the options:
090: this .options = (((buf[off] & 0xff) << 24)
091: + ((buf[off + 1] & 0xff) << 16)
092: + ((buf[off + 2] & 0xff) << 8) + ((buf[off + 3] & 0xff) << 0));
093: off += 4;
094: // Skip padding (four bytes):
095: off += 4;
096: return off;
097: }
098:
099: /**
100: * Get the length of that ICP message, if it were to be emitted.
101: * @return The length of the packet that would be emitted.
102: */
103:
104: protected int getByteArrayLength() {
105: return 16;
106: }
107:
108: /**
109: * Pack that message into a byte array suitable for emitting.
110: * @param buf The array to pack the request in.
111: * @return The length of the query, in bytes, or a negative number
112: * representing the size of the query.
113: */
114:
115: protected int toByteArray(byte buf[]) {
116: // Check that we have enough room:
117: int length = getByteArrayLength();
118: if (length > buf.length)
119: return -length;
120: // Setup the ICP header:
121: buf[0] = (byte) opcode;
122: buf[1] = (byte) ICP.ICP_VERSION;
123: // Encode the length:
124: buf[2] = (byte) ((length >>> 8) & 0xff);
125: buf[3] = (byte) ((length >>> 0) & 0xff);
126: // Encode the identifier:
127: buf[4] = (byte) ((id >>> 24) & 0xff);
128: buf[5] = (byte) ((id >>> 16) & 0xff);
129: buf[6] = (byte) ((id >>> 8) & 0xff);
130: buf[7] = (byte) ((id >>> 0) & 0xff);
131: // We don't implement any options (four bytes):
132: buf[8] = (byte) ((options >>> 24) & 0xff);
133: buf[9] = (byte) ((options >>> 16) & 0xff);
134: buf[10] = (byte) ((options >>> 8) & 0xff);
135: buf[11] = (byte) ((options >>> 0) & 0xff);
136: // Skip padding:
137:
138: return 16;
139: }
140:
141: /**
142: * Get the identifier of that ICP message.
143: * @return An integer identifier.
144: */
145:
146: protected final int getIdentifier() {
147: return id;
148: }
149:
150: /**
151: * Get the opcode for this message.
152: * @return An integer opcode (as defined by the ICP protocol).
153: * @see ICP
154: */
155:
156: protected final int getOpcode() {
157: return opcode;
158: }
159:
160: /**
161: * Get the URL contained in that message.
162: * @return An URL instance.
163: */
164:
165: protected final URL getURL() {
166: return url;
167: }
168:
169: /**
170: * Get the address of the host that sent this packet.
171: * @return An InetAddress instance, or <strong>null</strong> if the message
172: * was created locally.
173: */
174:
175: public InetAddress getSenderAddress() {
176: return addr;
177: }
178:
179: /**
180: * Get the port number from which this message was emitted.
181: * @return A integer port number.
182: */
183:
184: public int getSenderPort() {
185: return port;
186: }
187:
188: }
|