package org.jgroups.stack; import org.jgroups.logging.Log; import org.jgroups.logging.LogFactory; import org.jgroups.Address; import org.jgroups.Global; import org.jgroups.PhysicalAddress; import org.jgroups.util.Util; import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.net.Inet6Address; /** * Network-dependent address (Internet). Generated by the bottommost layer of the protocol * stack (UDP). Contains an InetAddress and port. * @author Bela Ban */ public class IpAddress implements PhysicalAddress { private static final long serialVersionUID=5877146630213185651L; private InetAddress ip_addr; private int port; protected static final Log log=LogFactory.getLog(IpAddress.class); static boolean resolve_dns; protected int size=-1; static { /* Trying to get value of resolve_dns. PropertyPermission not granted if * running in an untrusted environment with JNLP */ try { String tmp=Util.getProperty(new String[]{Global.RESOLVE_DNS, "resolve.dns"}, null, null, false, "false"); resolve_dns=Boolean.valueOf(tmp).booleanValue(); } catch (SecurityException ex){ resolve_dns=false; } } // Used only by Externalization public IpAddress() { } public IpAddress(String i, int p) throws UnknownHostException { port=p; ip_addr=InetAddress.getByName(i); } public IpAddress(InetAddress i, int p) { ip_addr=i; port=p; if(this.ip_addr == null) setAddressToLocalHost(); } private void setAddressToLocalHost() { try { ip_addr=InetAddress.getLocalHost(); // get first NIC found (on multi-homed systems) } catch(Exception e) { } if(ip_addr == null) { try { ip_addr=InetAddress.getByName(null); } catch(UnknownHostException e) { if(log.isWarnEnabled()) log.warn("exception: " + e); } } } public IpAddress(int port) { this(port, true); } public IpAddress(int port, boolean set_default_host) { this.port=port; if(set_default_host) setAddressToLocalHost(); } public IpAddress(InetSocketAddress sock_addr) { port=sock_addr.getPort(); ip_addr=sock_addr.getAddress(); } public final InetAddress getIpAddress() {return ip_addr;} public final int getPort() {return port;} /** * implements the java.lang.Comparable interface * @see java.lang.Comparable * @param o - the Object to be compared * @return a negative integer, zero, or a positive integer as this object is less than, * equal to, or greater than the specified object. * @exception java.lang.ClassCastException - if the specified object's type prevents it * from being compared to this Object. */ public final int compareTo(Address o) { int h1, h2, rc; // added Nov 7 2005, makes sense with canonical addresses if(this == o) return 0; if(!(o instanceof IpAddress)) throw new ClassCastException("comparison between different classes: the other object is " + (o != null? o.getClass() : o)); IpAddress other = (IpAddress) o; if(ip_addr == null) if (other.ip_addr == null) return port < other.port ? -1 : (port > other.port ? 1 : 0); else return -1; h1=ip_addr.hashCode(); h2=other.ip_addr.hashCode(); rc=h1 < h2? -1 : h1 > h2? 1 : 0; return rc != 0 ? rc : port < other.port ? -1 : (port > other.port ? 1 : 0); } public final boolean equals(Object obj) { if(this == obj) return true; // added Nov 7 2005, makes sense with canonical addresses if(!(obj instanceof IpAddress)) return false; IpAddress other=(IpAddress)obj; boolean sameIP; if(this.ip_addr != null) sameIP=this.ip_addr.equals(other.ip_addr); else sameIP=(other.ip_addr == null); return sameIP && (this.port == other.port); } public final int hashCode() { return ip_addr != null ? ip_addr.hashCode() + port : port; } public String toString() { StringBuilder sb=new StringBuilder(); if(ip_addr == null) sb.append("<null>"); else { if(ip_addr.isMulticastAddress()) sb.append(ip_addr.getHostAddress()); else { String host_name; if(resolve_dns) { host_name=ip_addr.getHostName(); } else { host_name=ip_addr.getHostAddress(); } sb.append(host_name); } } sb.append(":").append(port); return sb.toString(); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { try { readFrom(in); } catch(Exception e) { throw new IOException(e); } } public void writeExternal(ObjectOutput out) throws IOException { try { writeTo(out); } catch(Exception e) { throw new IOException(e); } } public void writeTo(DataOutput out) throws Exception { if(ip_addr != null) { byte[] address=ip_addr.getAddress(); // 4 bytes (IPv4) or 16 bytes (IPv6) out.writeByte(address.length); // 1 byte out.write(address, 0, address.length); if(ip_addr instanceof Inet6Address) out.writeInt(((Inet6Address)ip_addr).getScopeId()); } else { out.writeByte(0); } out.writeShort(port); } public void readFrom(DataInput in) throws Exception { int len=in.readByte(); if(len > 0 && (len != Global.IPV4_SIZE && len != Global.IPV6_SIZE)) throw new IOException("length has to be " + Global.IPV4_SIZE + " or " + Global.IPV6_SIZE + " bytes (was " + len + " bytes)"); byte[] a = new byte[len]; // 4 bytes (IPv4) or 16 bytes (IPv6) in.readFully(a); if(len == Global.IPV6_SIZE) { int scope_id=in.readInt(); this.ip_addr=Inet6Address.getByAddress(null, a, scope_id); } else { this.ip_addr=InetAddress.getByAddress(a); } // changed from readShort(): we need the full 65535, with a short we'd only get up to 32K ! port=in.readUnsignedShort(); } public int size() { if(size >= 0) return size; // length (1 bytes) + 4 bytes for port int tmp_size=Global.BYTE_SIZE+ Global.SHORT_SIZE; if(ip_addr != null) { tmp_size+=ip_addr.getAddress().length; // 4 bytes for IPv4 if(ip_addr instanceof Inet6Address) tmp_size+=Global.INT_SIZE; } size=tmp_size; return tmp_size; } public IpAddress copy() { return new IpAddress(ip_addr, port); } }