001: /*
002: * Copyright (c) 2000 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.sandStorm.lib.Gnutella;
026:
027: import seda.sandStorm.api.*;
028: import seda.sandStorm.core.*;
029: import seda.sandStorm.lib.aSocket.*;
030: import java.util.*;
031: import java.io.*;
032: import java.net.*;
033:
034: /**
035: * This is the base class for all Gnutella network packets.
036: */
037: public abstract class GnutellaPacket implements GnutellaConst,
038: QueueElementIF {
039:
040: private static final boolean DEBUG = false;
041:
042: public static int NUM_ALLOC = 0;
043:
044: protected GnutellaConnection gc;
045: protected GnutellaGUID guid;
046: protected int function;
047: // These are public so they can be modified by user routing code
048: public int ttl;
049: public int hops;
050: protected int payload_length;
051: protected byte payload[];
052:
053: public void finalize() {
054: NUM_ALLOC--;
055: }
056:
057: protected GnutellaPacket(GnutellaGUID guid, int function, int ttl,
058: int hops, byte payload[]) {
059: NUM_ALLOC++;
060:
061: this .guid = guid;
062: this .function = function;
063: this .ttl = ttl;
064: this .hops = hops;
065: this .payload = payload;
066: }
067:
068: protected GnutellaPacket(int function, byte payload[]) {
069: this (new GnutellaGUID(), function, DEFAULT_TTL, DEFAULT_HOPS,
070: payload);
071: }
072:
073: protected GnutellaPacket(GnutellaGUID guid, int function,
074: byte payload[]) {
075: this (guid, function, DEFAULT_TTL, DEFAULT_HOPS, payload);
076: }
077:
078: /**
079: * Used by GnutellaServer when creating a new packet.
080: */
081: void setConnection(GnutellaConnection gc) {
082: this .gc = gc;
083: }
084:
085: /**
086: * Return the GnutellaConnection from which this packet arrived.
087: * In order to send a reply to this packet, you can call
088: * 'packet.send(origPacket.getConnection()'.
089: */
090: public GnutellaConnection getConnection() {
091: return gc;
092: }
093:
094: /**
095: * Return the GUID associated with this packet.
096: */
097: public GnutellaGUID getGUID() {
098: return guid;
099: }
100:
101: /**
102: * Implemented by subclasses to prepare for sending
103: */
104: protected void prepareForSend() {
105: // Do nothing in default case
106: }
107:
108: /**
109: * Render the packet as a BufferElement which can be pushed to an
110: * aSocket connection.
111: */
112: BufferElement getBuffer() {
113: if (DEBUG)
114: System.err.println("GnutellaPacket: doing prepareForSend");
115: prepareForSend();
116: if (payload == null)
117: payload_length = 0;
118: else
119: payload_length = payload.length;
120:
121: byte data[] = new byte[PACKET_HEADER_SIZE + payload_length];
122: guid.dump(data, 0);
123: data[16] = (byte) (function & 0xff);
124: data[17] = (byte) (ttl & 0xff);
125: data[18] = (byte) (hops & 0xff);
126: writeLEInt(payload_length, data, 19);
127: if (payload != null)
128: System.arraycopy(payload, 0, data, PACKET_HEADER_SIZE,
129: payload_length);
130: BufferElement buf = new BufferElement(data);
131: return buf;
132: }
133:
134: // Return size of packet in bytes
135: public int getSize() {
136: prepareForSend();
137: if (payload == null)
138: payload_length = 0;
139: else
140: payload_length = payload.length;
141: return PACKET_HEADER_SIZE + payload_length;
142: }
143:
144: protected static void writeLEInt(int i, byte barr[], int offset) {
145: barr[offset] = (byte) (i & 0xff);
146: barr[offset + 1] = (byte) ((i & 0xff00) >> 8);
147: barr[offset + 2] = (byte) ((i & 0xff0000) >> 16);
148: barr[offset + 3] = (byte) ((i & 0xff000000) >> 24);
149: }
150:
151: protected static int readLEInt(byte barr[], int offset) {
152: int tmp = (((int) barr[offset + 0]) & 0xff)
153: | (((int) barr[offset + 1] << 8) & 0xff00)
154: | (((int) barr[offset + 2] << 16) & 0xff0000)
155: | (((int) barr[offset + 3] << 24) & 0xff000000);
156: return tmp;
157: }
158:
159: protected static void writeLEShort(int i, byte barr[], int offset) {
160: barr[offset] = (byte) (i & 0xff);
161: barr[offset + 1] = (byte) ((i & 0xff00) >> 8);
162: }
163:
164: protected static int readLEShort(byte barr[], int offset) {
165: int tmp = (((int) barr[offset + 0]) & 0xff)
166: | (((int) barr[offset + 1] << 8) & 0xff00);
167: return tmp;
168: }
169:
170: public String toString() {
171: return "GnutellaPacket (generic)";
172: }
173:
174: }
|