package com.limegroup.gnutella.altlocs;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import org.limewire.io.GUID;
import com.limegroup.gnutella.ApplicationServices;
import com.limegroup.gnutella.PushEndpoint;
import com.limegroup.gnutella.RemoteFileDesc;
import com.limegroup.gnutella.URN;
import com.limegroup.gnutella.UrnSet;
import com.limegroup.gnutella.downloader.RemoteFileDescFactory;
import com.limegroup.gnutella.http.HTTPConstants;
/**
* A firewalled altloc.
*/
public class PushAltLoc extends AbstractAlternateLocation {
/**
* the host we would send push to. Null if not firewalled.
*/
private final PushEndpoint _pushAddress;
private final ApplicationServices applicationServices;
/**
* Creates a new AlternateLocation for a firewalled host.
*
* @throws IOException
*/
protected PushAltLoc(final PushEndpoint address, final URN sha1,
ApplicationServices applicationServices) {
super(sha1);
if (address == null)
throw new NullPointerException("null address");
_pushAddress = address;
this.applicationServices = applicationServices;
}
@Override
protected String generateHTTPString() {
return _pushAddress.httpStringValue();
}
@Override
public RemoteFileDesc createRemoteFileDesc(long size,
RemoteFileDescFactory remoteFileDescFactory) {
Set<URN> urnSet = new UrnSet(getSHA1Urn());
int quality = 3;
RemoteFileDesc ret = remoteFileDescFactory.createRemoteFileDesc(_pushAddress, 0,
HTTPConstants.URI_RES_N2R + SHA1_URN, size, _pushAddress.getClientGUID(), 1000,
quality, false, null, urnSet, false, ALT_VENDOR, -1);
return ret;
}
@Override
public synchronized AlternateLocation createClone() {
PushAltLoc ret = new PushAltLoc(_pushAddress.createClone(), SHA1_URN, applicationServices);
ret._count = this._count;
return ret;
}
@Override
public boolean isMe() {
return Arrays.equals(_pushAddress.getClientGUID(), applicationServices.getMyGUID());
}
/**
* Updates the proxies in this PushEndpoint. If this method is called, the
* PE of this PushLoc will always point to the current set of proxies we
* know the remote host has. Otherwise, the PE will point to the set of
* proxies we knew the host had when it was created.
* <p>
* Note: it is a really good idea to call this method before adding this
* pushloc to a AlternateLocationCollection which may already contain a
* pushloc for the same host.
*/
public void updateProxies(boolean isGood) {
_pushAddress.updateProxies(isGood);
}
/**
* @return the PushAddress.
*/
public PushEndpoint getPushAddress() {
return _pushAddress;
}
/**
* @return the Firewall transfer protocol version this altloc supports. 0 if
* its not supported.
*/
public int supportsFWTVersion() {
return _pushAddress.getFWTVersion();
}
// stubbed out -- no demotion or promotion for push locs.
@Override
void promote() {
}
// stubbed out -- no demotion or promotion for push locs.
@Override
void demote() {
}
/**
* PushLocs are considered demoted once all their proxies are empty. This
* ensures that the PE will stay alive until it has exhausted all possible
* proxies.
*/
@Override
public boolean isDemoted() {
return _pushAddress.getProxies().isEmpty();
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof PushAltLoc))
return false;
if (!super.equals(o)) {
return false;
}
PushAltLoc other = (PushAltLoc) o;
return _pushAddress.equals(other._pushAddress);
}
@Override
public int compareTo(AlternateLocation obj) {
if (this == obj) // equal
return 0;
int ret = super.compareTo(obj);
if (ret != 0)
return ret;
if (!(obj instanceof PushAltLoc))
return 1;
PushAltLoc pal = (PushAltLoc) obj;
return GUID.GUID_BYTE_COMPARATOR.compare(_pushAddress.getClientGUID(), pal.getPushAddress()
.getClientGUID());
}
@Override
public int hashCode() {
if (hashCode == 0) {
int result = super.hashCode();
result = (37 * result) + this._pushAddress.hashCode();
hashCode = result;
}
return hashCode;
}
/**
* Overrides toString to return a string representation of this
* <tt>AlternateLocation</tt>, namely the pushAddress and the date.
*
* @return the string representation of this alternate location
*/
@Override
public String toString() {
return _pushAddress + "," + _count;
}
}