package com.limegroup.gnutella.messages; import java.net.InetAddress; import java.net.UnknownHostException; import com.limegroup.gnutella.ByteOrder; import com.limegroup.gnutella.util.IpPort; import com.limegroup.gnutella.util.NetworkUtils; /** Another utility class the encapsulates some complexity. * Keep in mind that I very well could have used Endpoint here, but I * decided against it mainly so I could do validity checking. * This may be a bad decision. I'm sure someone will let me know during * code review. */ public class IPPortCombo implements IpPort { private int _port; private InetAddress _addr; public static final String DELIM = ":"; /** * Used for reading data from the network. Throws BadPacketException * if the data is invalid. * @param fromNetwork 6 bytes - first 4 are IP, next 2 are port */ public static IPPortCombo getCombo(byte[] fromNetwork) throws BadPacketException { return new IPPortCombo(fromNetwork); } /** * Constructor used for data read from the network. * Throws BadPacketException on errors. */ private IPPortCombo(byte[] networkData) throws BadPacketException { if (networkData.length != 6) throw new BadPacketException("Weird Input"); String host = NetworkUtils.ip2string(networkData, 0); int port = ByteOrder.ushort2int(ByteOrder.leb2short(networkData, 4)); if (!NetworkUtils.isValidPort(port)) throw new BadPacketException("Bad Port: " + port); _port = port; try { _addr = InetAddress.getByName(host); } catch(UnknownHostException uhe) { throw new BadPacketException("bad host."); } if (!NetworkUtils.isValidAddress(_addr)) throw new BadPacketException("invalid addr: " + _addr); } /** * Constructor used for local data. * Throws IllegalArgumentException on errors. */ public IPPortCombo(String hostAddress, int port) throws UnknownHostException, IllegalArgumentException { if (!NetworkUtils.isValidPort(port)) throw new IllegalArgumentException("Bad Port: " + port); _port = port; _addr = InetAddress.getByName(hostAddress); if (!NetworkUtils.isValidAddress(_addr)) throw new IllegalArgumentException("invalid addr: " + _addr); } // Implements IpPort interface public int getPort() { return _port; } // Implements IpPort interface public InetAddress getInetAddress() { return _addr; } // Implements IpPort interface public String getAddress() { return _addr.getHostAddress(); } /** @return the ip and port encoded in 6 bytes (4 ip, 2 port). * //TODO if IPv6 kicks in, this may fail, don't worry so much now. */ public byte[] toBytes() { byte[] retVal = new byte[6]; for (int i=0; i < 4; i++) retVal[i] = _addr.getAddress()[i]; ByteOrder.short2leb((short)_port, retVal, 4); return retVal; } public boolean equals(Object other) { if (other instanceof IPPortCombo) { IPPortCombo combo = (IPPortCombo) other; return _addr.equals(combo._addr) && (_port == combo._port); } return false; } // overridden to fulfill contract with equals for hash-based // collections public int hashCode() { return _addr.hashCode() * _port; } public String toString() { return getAddress() + ":" + getPort(); } }