/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/***************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division(ANTD). *
**************************************************************************/
package gov.nist.core;
import java.net.*;
/*
* IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)<br/>
* Network Research Team (http://www-r2.u-strasbg.fr))<br/>
* Louis Pasteur University - Strasbourg - France<br/>
*
* Frank Feif reported a bug.
*
*
*/
/**
* Stores hostname.
* @version 1.2
*
* @author M. Ranganathan
* @author Emil Ivov <emil_ivov@yahoo.com> IPV6 Support. <br/>
*
*
*
* Marc Bednarek <bednarek@nist.gov> (Bugfixes).<br/>
*
*/
public class Host extends GenericObject {
/**
* Determines whether or not we should tolerate and strip address scope
* zones from IPv6 addresses. Address scope zones are sometimes returned
* at the end of IPv6 addresses generated by InetAddress.getHostAddress().
* They are however not part of the SIP semantics so basically this method
* determines whether or not the parser should be stripping them (as
* opposed simply being blunt and throwing an exception).
*/
private boolean stripAddressScopeZones = false;
private static final long serialVersionUID = -7233564517978323344L;
protected static final int HOSTNAME = 1;
protected static final int IPV4ADDRESS = 2;
protected static final int IPV6ADDRESS = 3;
/** hostName field
*/
protected String hostname;
/** address field
*/
protected int addressType;
private InetAddress inetAddress;
/** default constructor
*/
public Host() {
addressType = HOSTNAME;
stripAddressScopeZones
= Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
}
/** Constructor given host name or IP address.
*/
public Host(String hostName) throws IllegalArgumentException {
if (hostName == null)
throw new IllegalArgumentException("null host name");
stripAddressScopeZones
= Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
setHost(hostName, IPV4ADDRESS);
}
/** constructor
* @param name String to set
* @param addrType int to set
*/
public Host(String name, int addrType) {
stripAddressScopeZones
= Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES");
setHost(name, addrType);
}
/**
* Return the host name in encoded form.
* @return String
*/
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
if (addressType == IPV6ADDRESS && !isIPv6Reference(hostname)) {
buffer.append('[').append(hostname).append(']');
} else {
buffer.append(hostname);
}
return buffer;
}
/**
* Compare for equality of hosts.
* Host names are compared by textual equality. No dns lookup
* is performed.
* @param obj Object to set
* @return boolean
*/
public boolean equals(Object obj) {
if ( obj == null ) return false;
if (!this.getClass().equals(obj.getClass())) {
return false;
}
Host otherHost = (Host) obj;
return otherHost.hostname.equals(hostname);
}
/** get the HostName field
* @return String
*/
public String getHostname() {
return hostname;
}
/** get the Address field
* @return String
*/
public String getAddress() {
return hostname;
}
/**
* Convenience function to get the raw IP destination address
* of a SIP message as a String.
* @return String
*/
public String getIpAddress() {
String rawIpAddress = null;
if (hostname == null)
return null;
if (addressType == HOSTNAME) {
try {
if (inetAddress == null)
inetAddress = InetAddress.getByName(hostname);
rawIpAddress = inetAddress.getHostAddress();
} catch (UnknownHostException ex) {
dbgPrint("Could not resolve hostname " + ex);
}
} else {
rawIpAddress = hostname;
}
return rawIpAddress;
}
/**
* Set the hostname member.
* @param h String to set
*/
public void setHostname(String h) {
setHost(h, HOSTNAME);
}
/** Set the IP Address.
*@param address is the address string to set.
*/
public void setHostAddress(String address) {
setHost(address, IPV4ADDRESS);
}
/**
* Sets the host address or name of this object.
*
* @param host that host address/name value
* @param type determines whether host is an address or a host name
*/
private void setHost(String host, int type){
//set inetAddress to null so that it would be reinited
//upon next call to getInetAddress()
inetAddress = null;
if (isIPv6Address(host))
addressType = IPV6ADDRESS;
else
addressType = type;
// Null check bug fix sent in by jpaulo@ipb.pt
if (host != null){
hostname = host.trim();
//if this is an FQDN, make it lowercase to simplify processing
if(addressType == HOSTNAME)
hostname = hostname.toLowerCase();
//remove address scope zones if this is an IPv6 address as they
//are not allowed by the RFC
int zoneStart = -1;
if(addressType == IPV6ADDRESS
&& stripAddressScopeZones
&& (zoneStart = hostname.indexOf('%'))!= -1){
hostname = hostname.substring(0, zoneStart);
}
}
}
/**
* Set the address member
* @param address address String to set
*/
public void setAddress(String address) {
this.setHostAddress(address);
}
/** Return true if the address is a DNS host name
* (and not an IPV4 address)
*@return true if the hostname is a DNS name
*/
public boolean isHostname() {
return addressType == HOSTNAME;
}
/** Return true if the address is a DNS host name
* (and not an IPV4 address)
*@return true if the hostname is host address.
*/
public boolean isIPAddress() {
return addressType != HOSTNAME;
}
/** Get the inet address from this host.
* Caches the inet address returned from dns lookup to avoid
* lookup delays.
*
*@throws UnkownHostexception when the host name cannot be resolved.
*/
public InetAddress getInetAddress() throws java.net.UnknownHostException {
if (hostname == null)
return null;
if (inetAddress != null)
return inetAddress;
inetAddress = InetAddress.getByName(hostname);
return inetAddress;
}
//----- IPv6
/**
* Verifies whether the <code>address</code> could
* be an IPv6 address
*/
private boolean isIPv6Address(String address) {
return (address != null && address.indexOf(':') != -1);
}
/**
* Verifies whether the ipv6reference, i.e. whether it enclosed in
* square brackets
*/
public static boolean isIPv6Reference(String address) {
return address.charAt(0) == '['
&& address.charAt(address.length() - 1) == ']';
}
@Override
public int hashCode() {
return this.getHostname().hashCode();
}
}