/*
* Copyright 2009-2014 Jagornet Technologies, LLC. All Rights Reserved.
*
* This software is the proprietary information of Jagornet Technologies, LLC.
* Use is subject to license terms.
*
*/
/*
* This file Util.java is part of Jagornet DHCP.
*
* Jagornet DHCP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jagornet DHCP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jagornet DHCP. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.jagornet.dhcp.util;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.TimeZone;
/**
* Title: Util
* Description: Utility class for converting byte arrays to/from hex strings.
*
* @author A. Gregory Rabil
*/
public class Util
{
public static boolean IS_WINDOWS =
System.getProperty("os.name", "").startsWith("Windows") ? true : false;
public static String LINE_SEPARATOR = System.getProperty("line.separator");
public static TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
public static Calendar GMT_CALENDAR = Calendar.getInstance(GMT_TIMEZONE);
public static DateFormat GMT_DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
/**
* To hex string.
*
* @param binary the byte array to convert
*
* @return the string the converted hex string
*/
public static String toHexString(byte[] binary)
{
if(binary != null) {
StringBuffer str = new StringBuffer(binary.length * 2);
for(int i=0; i < binary.length; i++) {
int v = (binary[i] << 24) >>> 24;
str.append((v < 0x10 ? "0" : "") + Integer.toHexString(v));
}
return str.toString();
}
return null;
}
/**
* From hex string.
*
* @param hexString the hex string to convert
*
* @return the byte[] the converted byte array
*/
public static byte[] fromHexString(String hexString)
{
if(hexString != null) {
int strlen = hexString.length();
int blen = strlen/2 +
strlen%2;
byte[] barray = new byte[blen];
int i=0;
int j=0;
if(strlen%2 > 0) {
// if odd number of characters, prepend a zero
hexString = "0" + hexString;
}
while(i < hexString.length()) {
int hex = Integer.parseInt(hexString.substring(i, i+2), 16);
barray[j] = (byte)hex;
i += 2;
j++;
}
return barray;
}
return null;
}
/**
* Reads one unsigned byte as a short integer.
* @see org.apache.mina.core.buffer.IoBuffer.getUnsigned
*/
public static final short getUnsignedByte(ByteBuffer buf) {
return (short) (buf.get() & 0xff);
}
/**
* Reads two bytes unsigned integer.
* @see org.apache.mina.core.buffer.IoBuffer.getUnsignedShort
*/
public static final int getUnsignedShort(ByteBuffer buf) {
return (buf.getShort() & 0xffff);
}
/**
* Reads four bytes unsigned integer.
* @see org.apache.mina.core.buffer.IoBuffer.getUnsignedInt
*/
public static final long getUnsignedInt(ByteBuffer buf) {
return (buf.getInt() & 0xffffffffL);
}
public static final BigInteger getUnsignedLong(ByteBuffer buf) {
byte[] data = new byte[8];
buf.get(data);
return new BigInteger(data);
}
/**
* Relative <i>get</i> method for reading an unsigned medium int value.
*
* <p> Reads the next three bytes at this buffer's current position,
* composing them into an int value according to the current byte order,
* and then increments the position by three.</p>
*
* @return The unsigned medium int value at the buffer's current position
*
* @see org.apache.mina.core.buffer.IoBuffer.getUnsignedMediumInt
*/
public static final int getUnsignedMediumInt(ByteBuffer buf) {
int b1 = getUnsignedByte(buf);
int b2 = getUnsignedByte(buf);
int b3 = getUnsignedByte(buf);
if (ByteOrder.BIG_ENDIAN.equals(buf.order())) {
return b1 << 16 | b2 << 8 | b3;
} else {
return b3 << 16 | b2 << 8 | b1;
}
}
/**
* Relative <i>put</i> method for writing a medium int
* value.
*
* <p> Writes three bytes containing the given int value, in the
* current byte order, into this buffer at the current position, and then
* increments the position by three.</p>
*
* @param value
* The medium int value to be written
*
* @return This buffer
*
* @throws BufferOverflowException
* If there are fewer than three bytes
* remaining in this buffer
*
* @throws ReadOnlyBufferException
* If this buffer is read-only
*
* @see org.apache.mina.core.buffer.IoBuffer.putMediumInt
*/
public static final ByteBuffer putMediumInt(ByteBuffer buf, int value) {
byte b1 = (byte) (value >> 16);
byte b2 = (byte) (value >> 8);
byte b3 = (byte) value;
if (ByteOrder.BIG_ENDIAN.equals(buf.order())) {
buf.put(b1).put(b2).put(b3);
} else {
buf.put(b3).put(b2).put(b1);
}
return buf;
}
/**
* Compare IP addresses to determine order
*
* @param ip1
* @param ip2
* @return -1 if ip1<ip2, 0 if ip1=ip2, 1 if ip1>ip2
*/
public static int compareInetAddrs(InetAddress ip1, InetAddress ip2)
{
BigInteger bi1 = new BigInteger(ip1.getAddress());
BigInteger bi2 = new BigInteger(ip2.getAddress());
return bi1.compareTo(bi2);
}
/**
* Use this instead of InetSocketAddress.toString() to avoid
* DNS lookup - i.e. faster.
* @param saddr
* @return
*/
public static String socketAddressAsString(InetSocketAddress saddr) {
if (saddr == null)
return null;
else
return saddr.getAddress().getHostAddress() +
":" + saddr.getPort();
}
/**
* Get the IPv6 link-local address for the given network interface.
*
* @param netIf the network interface
* @return the first IPv6 link-local address recorded on the interface
*/
public static InetAddress netIfIPv6LinkLocalAddress(NetworkInterface netIf)
{
InetAddress v6Addr = null;
Enumeration<InetAddress> ifAddrs = netIf.getInetAddresses();
while (ifAddrs.hasMoreElements()) {
InetAddress addr = ifAddrs.nextElement();
if ((addr instanceof Inet6Address) && addr.isLinkLocalAddress()) {
// choose the link-local IPv6 address, which should be unique
// because it it must be the EUI-64 auto-configured address
v6Addr = addr;
}
}
return v6Addr;
}
}