package com.limegroup.gnutella.dht.db;
import java.util.Arrays;
import org.limewire.io.GGEP;
import org.limewire.io.GUID;
import org.limewire.mojito.db.DHTValueType;
import org.limewire.mojito.routing.Version;
import org.limewire.mojito.util.ArrayUtils;
import org.limewire.util.ByteUtils;
/**
* An implementation of DHTValue for for Gnutella Alternate Locations.
*/
public abstract class AbstractAltLocValue implements AltLocValue {
/**
* DHTValueType for AltLocs.
*/
public static final DHTValueType ALT_LOC = DHTValueType.valueOf("Gnutella Alternate Location", "ALOC");
/*
* AltLocValue version history
*
* Version 0:
* GUID
* Port
* Firewalled
*
* Version 1:
* File Length
* TigerTree root hash (optional)
* Incoming TLS support (optional)
*/
public static final Version VERSION_ONE = Version.valueOf(1);
/**
* Version of AltLocDHTValue.
*/
public static final Version VERSION = VERSION_ONE;
static final String CLIENT_ID = "client-id";
static final String PORT = "port";
static final String FIREWALLED = "firewalled";
static final String LENGTH = "length";
static final String TTROOT = "ttroot";
static final String TLS = "tls";
protected final Version version;
public AbstractAltLocValue(Version version) {
this.version = version;
}
/*
* (non-Javadoc)
* @see org.limewire.mojito.db.DHTValue#getVersion()
*/
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getVersion()
*/
public Version getVersion() {
return version;
}
/*
* (non-Javadoc)
* @see org.limewire.mojito.db.DHTValue#getValueType()
*/
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getValueType()
*/
public DHTValueType getValueType() {
return ALT_LOC;
}
/*
* (non-Javadoc)
* @see org.limewire.mojito.db.DHTValue#size()
*/
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#size()
*/
public int size() {
return getValue().length;
}
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getGUID()
*/
public abstract byte[] getGUID();
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getPort()
*/
public abstract int getPort();
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getFileSize()
*/
public abstract long getFileSize();
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#getRootHash()
*/
public abstract byte[] getRootHash();
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#isFirewalled()
*/
public abstract boolean isFirewalled();
/* (non-Javadoc)
* @see com.limegroup.gnutella.dht.db.AltLocValue#supportsTLS()
*/
public abstract boolean supportsTLS();
@Override
public boolean equals(Object obj) {
if(!(obj instanceof AltLocValue)) {
return false;
}
AltLocValue other = (AltLocValue)obj;
return getFileSize() == other.getFileSize() && Arrays.equals(getGUID(), other.getGUID())
&& getPort() == other.getPort() && Arrays.equals(getRootHash(), other.getRootHash())
&& Arrays.equals(getValue(), other.getValue()) && getValueType().equals(other.getValueType())
&& getVersion().equals(other.getVersion());
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + (int)getFileSize();
hash = 31 * hash + getPort();
hash = 31 * hash + getGUID().hashCode();
hash = 31 * hash + getRootHash().hashCode();
hash = 31 * hash + getValue().hashCode();
hash = 31 * hash + getValueType().hashCode();
hash = 31 * hash + getVersion().hashCode();
return hash;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("AltLoc: guid=").append(new GUID(getGUID()))
.append(", port=").append(getPort())
.append(", firewalled=").append(isFirewalled())
.append(", tls=").append(supportsTLS())
.append(", fileSize=").append(getFileSize())
.append(", ttroot=").append(getRootHash() != null
? ArrayUtils.toHexString(getRootHash()) : "null");
if (this instanceof AltLocValueForSelf) {
buffer.append(", local=true");
}
return buffer.toString();
}
/**
* A helper method to serialize AltLocValues.
*/
protected static byte[] serialize(AbstractAltLocValue value) {
Version version = value.getVersion();
GGEP ggep = new GGEP();
ggep.put(CLIENT_ID, value.getGUID());
byte[] port = new byte[2];
ByteUtils.short2beb((short)value.getPort(), port, 0);
ggep.put(PORT, port);
byte[] firewalled = { (byte)(value.isFirewalled() ? 1 : 0) };
ggep.put(FIREWALLED, firewalled);
if (version.compareTo(VERSION_ONE) >= 0) {
ggep.put(LENGTH, /* long */ value.getFileSize());
byte[] ttroot = value.getRootHash();
if (ttroot != null) {
ggep.put(TTROOT, ttroot);
}
if (value.supportsTLS())
ggep.put(TLS);
}
return ggep.toByteArray();
}
}