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: /**
026: * This is a convenience library which makes use of "gnutellahosts.com"
027: * to establish initial connections to the Gnutella network. (It can
028: * also make use of any other well-known host.) It simply connects to
029: * the given host and sends a single ping packet. Connections are then
030: * opened to a given number of hosts returned from the resulting pongs.
031: *
032: * @author Matt Welsh
033: */package seda.sandStorm.lib.Gnutella;
034:
035: import seda.sandStorm.api.*;
036: import seda.sandStorm.core.*;
037: import seda.sandStorm.lib.aSocket.*;
038: import java.io.*;
039: import java.net.*;
040: import java.util.*;
041:
042: public class GnutellaCatcher implements EventHandlerIF {
043:
044: private static final boolean DEBUG = false;
045:
046: // Maximum number of levels of 'pong' packets before we forward
047: // connection to user
048: private static final int SEARCH_DEPTH = 2;
049:
050: private ManagerIF mgr;
051: private GnutellaServer gs;
052: private GnutellaServer mygs;
053: private int total, num_established;
054: private Hashtable searchTbl;
055:
056: /**
057: * Create a GnutellaCatcher in the context of the given vSpace clone,
058: * using the given GnutellaServer to establish new outgoing
059: * connections.
060: */
061: public GnutellaCatcher(ManagerIF mgr, GnutellaServer gs)
062: throws Exception {
063: this .mgr = mgr;
064: this .gs = gs;
065: this .total = 0;
066: this .num_established = 0;
067: this .searchTbl = new Hashtable(1);
068: mgr.createStage("GnutellaCatcher", this , null);
069: }
070:
071: public void init(ConfigDataIF config) throws Exception {
072: this .mygs = new GnutellaServer(mgr,
073: config.getStage().getSink(), 0);
074: }
075:
076: public void destroy() {
077: }
078:
079: /**
080: * Create 'numconns' new connections to the Gnutella network, using the
081: * given hostname:port as the bootstrapping host.
082: */
083: public void doCatch(int numconns, String hostname, int port)
084: throws UnknownHostException {
085: this .total += numconns;
086: InetAddress addr = InetAddress.getByName(hostname);
087: searchDepth sd = new searchDepth();
088: searchTbl.put(addr, sd);
089: mygs.openConnection(addr, port);
090: }
091:
092: /**
093: * Create 'numconns' new connections to the Gnutella network, using
094: * "gnutellahosts.com:6346" as the bootstrapping host.
095: */
096: public void doCatch(int numconns) throws UnknownHostException {
097: doCatch(numconns, "gnutellahosts.com",
098: GnutellaConst.DEFAULT_GNUTELLA_PORT);
099: }
100:
101: public void handleEvent(QueueElementIF item) {
102: if (DEBUG)
103: System.err.println("GnutellaCatcher got: " + item);
104: if (item instanceof GnutellaConnection) {
105: GnutellaConnection gc = (GnutellaConnection) item;
106: GnutellaPingPacket ping = new GnutellaPingPacket();
107: if (DEBUG)
108: System.err.println("GnutellaCatcher sending ping");
109: gc.enqueue_lossy(ping);
110:
111: } else if (item instanceof GnutellaPongPacket) {
112: GnutellaPongPacket pong = (GnutellaPongPacket) item;
113: GnutellaConnection ponggc = pong.getConnection();
114: InetAddress addr = ponggc.getAddress();
115: searchDepth sd = (searchDepth) searchTbl.get(addr);
116: if (sd == null) {
117: System.err
118: .println("GnutellaCatcher: Warning: Got pong packet from unknown address "
119: + addr + " (" + ponggc + ")");
120: }
121:
122: if (sd.depth >= SEARCH_DEPTH) {
123: if (num_established < total) {
124: System.err
125: .println("GnutellaCatcher: Opening user connection to "
126: + pong.getInetAddress()
127: .getHostAddress()
128: + ":"
129: + pong.getPort());
130: gs.openConnection(pong.getInetAddress(), pong
131: .getPort());
132: num_established++;
133: }
134: } else {
135: searchDepth sd2 = new searchDepth(sd);
136: searchTbl.put(pong.getInetAddress(), sd2);
137: if (DEBUG)
138: System.err
139: .println("GnutellaCatcher: Opening depth "
140: + sd2.depth
141: + " connection to "
142: + pong.getInetAddress()
143: .getHostAddress() + ":"
144: + pong.getPort());
145: mygs.openConnection(pong.getInetAddress(), pong
146: .getPort());
147: }
148:
149: }
150: }
151:
152: public void handleEvents(QueueElementIF qelarr[]) {
153: for (int i = 0; i < qelarr.length; i++) {
154: handleEvent(qelarr[i]);
155: }
156: }
157:
158: private class searchDepth {
159: int depth;
160:
161: searchDepth() {
162: this .depth = 1;
163: }
164:
165: searchDepth(searchDepth sd) {
166: this .depth = sd.depth + 1;
167: }
168: }
169:
170: }
|