package com.limegroup.gnutella.altlocs; import java.io.IOException; import java.net.URL; import java.util.HashSet; import java.util.Set; import com.limegroup.gnutella.http.HTTPConstants; import com.limegroup.gnutella.util.IpPort; import com.limegroup.gnutella.Endpoint; import com.limegroup.gnutella.ErrorService; import com.limegroup.gnutella.RemoteFileDesc; import com.limegroup.gnutella.RouterService; import com.limegroup.gnutella.URN; import com.limegroup.gnutella.util.DataUtils; import com.limegroup.gnutella.util.IpPortForSelf; import com.limegroup.gnutella.util.IpPortImpl; import com.limegroup.gnutella.util.NetworkUtils; /** * An alternate location that is directly reachable, i.e. not firewalled. */ public class DirectAltLoc extends AlternateLocation { private final IpPort _node; /** * Remembers if this AltLoc ever failed, if it did _demoted is set. If this * succeeds, it may be promoted again resetting the value of _demoted. The * _count attribute does does take into account the case of a good alternate * location with a high count, which has recently failed. * <p> * Note that demotion in not intrinsic to the use of this class, some * modules like the download may not want to demote an AlternatLocation, * other like the uploader may rely on it. */ protected volatile boolean _demoted = false; /** * Creates a new <tt>AlternateLocation</tt> with the specified <tt>URL</tt> * and <tt>Date</tt> timestamp. * * @param url the <tt>URL</tt> for the <tt>AlternateLocation</tt> * @param date the <tt>Date</tt> timestamp for the * <tt>AlternateLocation</tt> */ protected DirectAltLoc(final URL url, final URN sha1) throws IOException { this(new IpPortImpl(url.getHost(),url.getPort()),sha1); } /** * creates an altloc for myself. */ protected DirectAltLoc(final URN sha1) throws IOException{ this(new Endpoint( RouterService.getAddress(), RouterService.getPort()) ,sha1); } protected DirectAltLoc(IpPort address, URN sha1) throws IOException{ super(sha1); if (!NetworkUtils.isValidExternalIpPort(address)) throw new IOException("not a valid external address:port in direct altloc "+address); _node=address; if (_node == IpPortForSelf.instance()) hashCode = IpPortForSelf.instance().hashCode(); } protected String generateHTTPString() { String ret = _node.getInetAddress().getHostAddress(); if (_node.getPort()!=6346) ret = ret+":"+_node.getPort(); return ret; } public RemoteFileDesc createRemoteFileDesc(int size) { Set urnSet = new HashSet(); urnSet.add(getSHA1Urn()); int quality = 3; RemoteFileDesc ret = new RemoteFileDesc(_node.getAddress(), _node.getPort(), 0, HTTPConstants.URI_RES_N2R+SHA1_URN, size, DataUtils.EMPTY_GUID, 1000, true, quality, false, null, urnSet, false, false, //assume altLoc is not firewalled ALT_VENDOR,//Never displayed, and we don't know System.currentTimeMillis(), null, -1); return ret; } public synchronized AlternateLocation createClone() { DirectAltLoc ret = null; try { ret = new DirectAltLoc(_node, this.SHA1_URN); } catch(IOException ioe) { ErrorService.error(ioe); return null; } ret._demoted = this._demoted; ret._count = this._count; return ret; } public boolean isMe(){ return NetworkUtils.isMe(_node); } /** * Returns the host/port of this alternate location as an endpoint. */ public IpPort getHost() { return _node; } public boolean equals(Object o){ if (o==null || !(o instanceof DirectAltLoc)) return false; if (!super.equals(o)) return false; DirectAltLoc other = (DirectAltLoc)o; if (_node == other._node) return true; return (_node.getInetAddress().equals(other._node.getInetAddress()) && _node.getPort() == other._node.getPort()); } synchronized void demote() { _demoted = true;} synchronized void promote() { _demoted = false; } public synchronized boolean isDemoted() { return _demoted; } public int compareTo(Object o) { if (this==o) //equal return 0; int ret = super.compareTo(o); // if comparing to PushLocs count is all we need. // if that is the same, compare by hashCode() if (!(o instanceof DirectAltLoc)) { if (ret!=0) return ret; else return -1; } DirectAltLoc other = (DirectAltLoc)o; // if I'm demoted, I'm bigger. Otherwise I'm smaller if (_demoted != other._demoted) { if (_demoted) return 1; return -1; } // ret still holds the count difference if (ret != 0) return ret; // if we are both altlocs for myself if (_node == other._node) return 0; ret = _node.getAddress().compareTo(other._node.getAddress()); if (ret != 0) return ret; ret = (_node.getPort() - other._node.getPort()); // if we got here and ret is still 0, we are the same as the other // DirectLoc. return ret; } public int hashCode() { if (hashCode ==0) { int result = super.hashCode(); result = (37* result)+_node.getInetAddress().hashCode(); result = (37* result)+_node.getPort(); hashCode=result; } return hashCode; } /** * Overrides toString to return a string representation of this * <tt>AlternateLocation</tt>, namely the url and the date. * * @return the string representation of this alternate location */ public String toString() { return _node+","+_count+","+_demoted; } }