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: * A GnutellaConnection represents a virtual connection to the
036: * Gnutella network. It may implement a single point-to-point connection
037: * between two peers, or a one-to-many connection to multiple peers.
038: *
039: * @author Matt Welsh (mdw@cs.berkeley.edu)
040: */
041: public class GnutellaConnection extends SimpleSink implements
042: QueueElementIF, GnutellaConst {
043:
044: private static final boolean DEBUG = false;
045:
046: private GnutellaServer gs;
047: private GnutellaPacketReader gpr;
048: private ATcpConnection conn;
049: private InetAddress addr;
050: private int port;
051: private boolean closed;
052:
053: GnutellaConnection(GnutellaServer gs, ATcpConnection conn) {
054: this .gs = gs;
055: this .conn = conn;
056: this .gpr = new GnutellaPacketReader();
057: addr = conn.getAddress();
058: port = conn.getPort();
059: closed = false;
060: }
061:
062: /**
063: * Return the InetAddress of the peer. Returns null if this is a
064: * 'virtual' connection.
065: */
066: public InetAddress getAddress() {
067: return addr;
068: }
069:
070: /**
071: * Return the port of the peer. Returns -1 if this is a 'virtual'
072: * connection.
073: */
074: public int getPort() {
075: return port;
076: }
077:
078: /**
079: * Send a ping to this connection.
080: */
081: public void sendPing() {
082: GnutellaPingPacket ping = new GnutellaPingPacket();
083: enqueue_lossy(ping);
084: }
085:
086: /**
087: * Send a ping to this connection with the given TTL.
088: */
089: public void sendPing(int ttl) {
090: GnutellaPingPacket ping = new GnutellaPingPacket(
091: new GnutellaGUID(), ttl, 0);
092: enqueue_lossy(ping);
093: }
094:
095: // Package access only
096: ATcpConnection getConnection() {
097: return conn;
098: }
099:
100: // Package access only
101: GnutellaPacketReader getReader() {
102: return gpr;
103: }
104:
105: /* SinkIF methods ******************************************************/
106:
107: public void enqueue(QueueElementIF element) throws SinkException {
108: GnutellaPacket packet = (GnutellaPacket) element;
109: BufferElement buf = packet.getBuffer();
110: buf.compQ = gs.getSink();
111: conn.enqueue(buf);
112: }
113:
114: public boolean enqueue_lossy(QueueElementIF element) {
115: GnutellaPacket packet = (GnutellaPacket) element;
116: BufferElement buf = packet.getBuffer();
117: buf.compQ = gs.getSink();
118: return conn.enqueue_lossy(buf);
119: }
120:
121: public void enqueue_many(QueueElementIF elements[])
122: throws SinkException {
123: for (int i = 0; i < elements.length; i++) {
124: enqueue(elements[i]);
125: }
126: }
127:
128: public int size() {
129: return conn.size();
130: }
131:
132: public void close(SinkIF compQ) throws SinkClosedException {
133: // XXX For now, allow a connection to be closed multiple times
134: // This is because clogged connections may push multiple
135: // clogged events up, causing the server to attempt to close
136: // multiple times
137: //if (closed) throw new SinkClosedException("GnutellaConnection already closed!");
138: gs.cleanupConnection(conn, this );
139: gs.closeConnection(conn, compQ);
140: closed = true;
141: }
142:
143: public void flush(SinkIF compQ) throws SinkClosedException {
144: conn.flush(compQ);
145: }
146:
147: public Object enqueue_prepare(QueueElementIF enqueueMe[])
148: throws SinkException {
149: return conn.enqueue_prepare(enqueueMe);
150: }
151:
152: public void enqueue_commit(Object key) {
153: conn.enqueue_commit(key);
154: }
155:
156: public void enqueue_abort(Object key) {
157: conn.enqueue_abort(key);
158: }
159:
160: public String toString() {
161: return "GnutellaConnection [" + addr.getHostAddress() + ":"
162: + port + "]";
163: }
164:
165: }
|