package org.limewire.net.address;
import java.util.Comparator;
import java.util.Set;
import org.limewire.io.Address;
import org.limewire.io.Connectable;
import org.limewire.io.GUID;
import org.limewire.io.NetworkUtils;
import org.limewire.util.Objects;
import org.limewire.util.StringUtils;
/**
* Provides the data needed to connect to a firewalled peer.
* Can be compared to other {@link FirewalledAddress firewalled address objects}
* using {@link #equals(Object)}.
*/
public class FirewalledAddress implements Address {
private final Connectable publicAddress;
private final Connectable privateAddress;
private final Set<Connectable> pushProxies;
private final int fwtVersion;
private final GUID clientGuid;
private int hashCode;
public FirewalledAddress(Connectable publicAddress, Connectable privateAddress, GUID clientGuid, Set<Connectable> pushProxies, int fwtVersion) {
this.publicAddress = Objects.nonNull(publicAddress, "publicAddress");
this.privateAddress = Objects.nonNull(privateAddress, "privateAddress");
this.clientGuid = clientGuid;
this.pushProxies = pushProxies;
this.fwtVersion = fwtVersion;
if (fwtVersion > 0) {
if (!NetworkUtils.isValidIpPort(publicAddress)) {
throw new IllegalArgumentException("inconsistent firewalled address: " + this);
}
}
}
@Override
public String getAddressDescription() {
if(NetworkUtils.isValidIpPort(getPublicAddress())) {
return publicAddress.getAddressDescription();
} else {
return privateAddress.getAddressDescription();
}
}
/**
* @return an invalid address if public address it not known
*/
public Connectable getPublicAddress() {
return publicAddress;
}
public Connectable getPrivateAddress() {
return privateAddress;
}
/**
* @return a set of push proxy addresses, which may be empty
*/
public Set<Connectable> getPushProxies() {
return pushProxies;
}
/**
* Returns the version for reliable udp or 0 if it is not supported.
*
* See {@link RUDPUtils#VERSION}.
*/
public int getFwtVersion() {
return fwtVersion;
}
public GUID getClientGuid() {
return clientGuid;
}
@Override
public String toString() {
return StringUtils.toString(this, publicAddress, privateAddress, clientGuid, pushProxies, fwtVersion);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof FirewalledAddress)) {
return false;
}
FirewalledAddress other = (FirewalledAddress)obj;
if (!equals(Connectable.COMPARATOR, publicAddress, other.getPublicAddress())) {
return false;
}
if (!equals(Connectable.COMPARATOR, privateAddress, other.getPrivateAddress())) {
return false;
}
if (!Objects.equalOrNull(pushProxies, other.getPushProxies())) {
return false;
}
if (!Objects.equalOrNull(clientGuid, other.getClientGuid())) {
return false;
}
if (fwtVersion != other.getFwtVersion()) {
return false;
}
return true;
}
private int hashCode(Connectable connectable) {
if (connectable == null) {
return 0;
}
return connectable.getInetSocketAddress().hashCode() + (connectable.isTLSCapable() ? 1 : 0);
}
private int hashCode(Set<Connectable> set) {
int hashCode = 0;
for (Connectable connectable : set) {
hashCode = 31 * hashCode + hashCode(connectable);
}
return hashCode;
}
private int hashCode(Object obj) {
return obj != null ? obj.hashCode() : 0;
}
@Override
public int hashCode() {
if (hashCode == 0) {
int hash = hashCode(publicAddress);
hash = 31 * hash + hashCode(privateAddress);
hash = 31 * hash + hashCode(pushProxies);
hash = 31 * hash + hashCode(clientGuid);
hash = 31 * hash + fwtVersion;
hashCode = hash;
}
return hashCode;
}
private <T> boolean equals(Comparator<T> comparator, T t1, T t2) {
if (t1 == t2) {
return true;
}
if (t1 == null || t2 == null) {
return false;
}
return comparator.compare(t1, t2) == 0;
}
}