package com.limegroup.gnutella; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Collections; import java.util.Set; import org.limewire.io.GUID; import org.limewire.io.IpPort; import org.limewire.io.IpPortSet; import org.limewire.io.NetworkInstanceUtils; import org.limewire.service.ErrorService; public class PushEndpointImpl extends AbstractPushEndpoint { /** * the client guid of the endpoint */ private final byte [] _clientGUID; /** * the guid as an object to avoid recreating * If there are other PushEnpoint objects, they all will ultimately * point to the same GUID object. This ensures that as long as * there is at least one PE object for a remote host, the set of * proxies will not be gc-ed. */ private GUID _guid; /** * the various features this PE supports. */ private final int _features; /** * the version of firewall to firewall transfer protocol * this endpoint supports. */ private final int _fwtVersion; /** * the set of proxies this has immediately after creating the endpoint * cleared after registering in the map. This is used only to * hold the parsed proxies until they are put in the map. */ private Set<? extends IpPort> _proxies; /** * the external address of this PE. Needed for firewall-to-firewall * transfers, but can be null. */ private final IpPort _externalAddr; private final PushEndpointCache pushEndpointCache; private final NetworkInstanceUtils networkInstanceUtils; public PushEndpointImpl(byte[] guid, Set<? extends IpPort> proxies, byte features, int fwtVersion, IpPort addr, PushEndpointCache pushEndpointCache, NetworkInstanceUtils networkInstanceUtils) { this.pushEndpointCache = pushEndpointCache; this.networkInstanceUtils = networkInstanceUtils; _features = ((features & FEATURES_MASK) | (fwtVersion << 3)); _fwtVersion=fwtVersion; _clientGUID=guid; _guid = new GUID(_clientGUID); if (proxies != null) { if (proxies instanceof IpPortSet) _proxies = Collections.unmodifiableSet(proxies); else _proxies = Collections.unmodifiableSet(new IpPortSet(proxies)); } else _proxies = Collections.emptySet(); _externalAddr = addr; if(addr != null && addr.getAddress().equals(RemoteFileDesc.BOGUS_IP)) ErrorService.error(new IllegalStateException("constructing PEI w/ bogus IP!")); } /** * * @return an IpPort representing our valid external * address, or null if we don't have such. */ public IpPort getValidExternalAddress() { IpPort ret = getIpPort(); if (ret == null || !networkInstanceUtils.isValidExternalIpPort(ret)) return null; // This shouldn't be possible... but we can workaround it. if(ret.getAddress().equals(RemoteFileDesc.BOGUS_IP)) return null; return ret; } public byte [] getClientGUID() { return _clientGUID; } public Set<? extends IpPort> getProxies() { synchronized(this) { if (_proxies!=null) return _proxies; } PushEndpoint current = pushEndpointCache.getCached(_guid); if (current == null) return Collections.emptySet(); return current.getProxies(); } public int getFWTVersion() { PushEndpoint current = pushEndpointCache.getCached(_guid); int currentVersion = current == null ? _fwtVersion : current.getFWTVersion(); return currentVersion; } public byte getFeatures() { PushEndpoint current = pushEndpointCache.getCached(_guid); int currentFeatures = current==null ? _features : current.getFeatures(); return (byte)(currentFeatures & FEATURES_MASK); } private IpPort getIpPort() { PushEndpoint current = pushEndpointCache.getCached(_guid); return current == null || current.getValidExternalAddress() == null ? _externalAddr : current.getValidExternalAddress(); } /** * Implements the IpPort interface, returning a bogus ip if we don't know * it. * * @return the external address if known otherwise {@link RemoteFileDesc#BOGUS_IP} */ public String getAddress() { IpPort addr = getIpPort(); return addr != null ? addr.getAddress() : RemoteFileDesc.BOGUS_IP; } public InetAddress getInetAddress() { IpPort addr = getIpPort(); return addr != null ? addr.getInetAddress() : null; } /** * Implements the IpPort interface, returning a bogus port if we don't know it * * @return the port of the external address if known otherwise 6346 */ public int getPort() { IpPort addr = getIpPort(); return addr != null ? addr.getPort() : 6346; } public InetSocketAddress getInetSocketAddress() { IpPort addr = getIpPort(); return addr != null ? addr.getInetSocketAddress() : null; } @Override public String getAddressDescription() { IpPort addr = getIpPort(); return addr != null ? addr.getAddress() : null; } public boolean isLocal() { return false; } public synchronized void updateProxies(boolean good) { _guid = pushEndpointCache.updateProxiesFor(_guid, this, good); _proxies = null; } public PushEndpoint createClone() { return new PushEndpointImpl(_guid.bytes(), getProxies(), getFeatures(), getFWTVersion(), getIpPort(), pushEndpointCache, networkInstanceUtils); } }