BUG-6647 Increase code coverage and clean up II
[bgpcep.git] / util / src / main / java / org / opendaylight / protocol / util / Ipv4Util.java
index 79c4e8aa297de3c486fdb5b2195dd979edd2633f..4eb674387feea4a05a4a1602af45f6282487b512 100644 (file)
@@ -8,47 +8,35 @@
 package org.opendaylight.protocol.util;
 
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
 import com.google.common.net.InetAddresses;
-import com.google.common.primitives.Bytes;
 import com.google.common.primitives.UnsignedBytes;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
-import java.net.Inet4Address;
 import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import java.util.Map;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 
 /**
  * Util class for creating generated Ipv4Address.
  */
 public final class Ipv4Util {
+    public static final int IP4_LENGTH = 4;
+    public static final int IP4_BITS_LENGTH = 32;
+    private static final Ipv4Prefix EMPTY_PREFIX = new Ipv4Prefix("0.0.0.0/0");
 
     private Ipv4Util() {
         throw new UnsupportedOperationException();
     }
 
-    public static final int IP4_LENGTH = 4;
-
-    /**
-     * Converts byte array to Inet4Address.
-     *
-     * @param bytes to be converted
-     * @return InetAddress instance
-     * @throws IllegalArgumentException if {@link UnknownHostException} is thrown.
-     */
-    private static InetAddress getAddress(final byte[] bytes) {
-        try {
-            return Inet4Address.getByAddress(bytes);
-        } catch (final UnknownHostException e) {
-            throw new IllegalArgumentException("Failed to construct IPv4 address", e);
-        }
-    }
-
     /**
      * Reads from ByteBuf buffer and converts bytes to Ipv4Address.
      *
@@ -56,7 +44,7 @@ public final class Ipv4Util {
      * @return Ipv4Address
      */
     public static Ipv4Address addressForByteBuf(final ByteBuf buffer) {
-        return new Ipv4Address(InetAddresses.toAddrString(getAddress(ByteArray.readBytes(buffer, IP4_LENGTH))));
+        return IetfInetUtil.INSTANCE.ipv4AddressFor(ByteArray.readBytes(buffer, IP4_LENGTH));
     }
 
     /**
@@ -75,9 +63,14 @@ public final class Ipv4Util {
      * @return byte array
      */
     public static byte[] bytesForAddress(final Ipv4Address address) {
-        final InetAddress a = InetAddresses.forString(address.getValue());
-        Preconditions.checkArgument(a instanceof Inet4Address);
-        return a.getAddress();
+        return IetfInetUtil.INSTANCE.ipv4AddressBytes(address);
+    }
+
+    public static int prefixBitsToBytes(final int bits) {
+        if (bits % Byte.SIZE != 0) {
+            return (bits / Byte.SIZE) + 1;
+        }
+        return bits / Byte.SIZE;
     }
 
     /**
@@ -86,12 +79,8 @@ public final class Ipv4Util {
      * @param prefix
      * @return
      */
-    protected static int getPrefixLengthBytes(final String prefix) {
-        final int bits = Ipv4Util.getPrefixLength(prefix);
-        if (bits % Byte.SIZE != 0) {
-            return (bits / Byte.SIZE) + 1;
-        }
-        return bits / Byte.SIZE;
+    public static int getPrefixLengthBytes(final String prefix) {
+        return prefixBitsToBytes(Ipv4Util.getPrefixLength(prefix));
     }
 
     /**
@@ -101,12 +90,7 @@ public final class Ipv4Util {
      * @return byte array with prefix length at the end
      */
     public static byte[] bytesForPrefix(final Ipv4Prefix prefix) {
-        final String p = prefix.getValue();
-        final int sep = p.indexOf('/');
-        final InetAddress a = InetAddresses.forString(p.substring(0, sep));
-        Preconditions.checkArgument(a instanceof Inet4Address);
-        final byte[] bytes = a.getAddress();
-        return Bytes.concat(bytes, new byte[] { Byte.valueOf(p.substring(sep + 1, p.length())) });
+        return IetfInetUtil.INSTANCE.ipv4PrefixToBytes(prefix);
     }
 
     /**
@@ -115,15 +99,26 @@ public final class Ipv4Util {
      *
      * @param prefix Ipv4Prefix to be converted
      * @return byte array with the prefix length at the beginning
+     *
+     * @deprecated This is inefficient, refactor code to use {@link #bytesForAddress(Ipv4Address)} or
+     *             {@link ByteBufWriteUtil#writeMinimalPrefix(Ipv4Prefix, ByteBuf)}.
      */
+    @Deprecated
     public static byte[] bytesForPrefixBegin(final Ipv4Prefix prefix) {
-        final String p = prefix.getValue();
-        final int sep = p.indexOf('/');
-        final InetAddress a = InetAddresses.forString(p.substring(0, sep));
-        Preconditions.checkArgument(a instanceof Inet4Address);
-        final byte[] bytes = a.getAddress();
-        final int length = getPrefixLength(p);
-        return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(length) }, ByteArray.subByte(bytes, 0 , getPrefixLengthBytes(p)));
+        final byte[] addrWithPrefix = bytesForPrefix(prefix);
+        return prefixedBytes(addrWithPrefix[IP4_LENGTH], addrWithPrefix);
+    }
+
+    static byte[] prefixedBytes(final byte prefixBits, final byte[] address) {
+        if (prefixBits != 0) {
+            final int prefixBytes = prefixBitsToBytes(Byte.toUnsignedInt(prefixBits));
+            final byte[] ret = new byte[prefixBytes + 1];
+            ret[0] = prefixBits;
+            System.arraycopy(address, 0, ret, 1, prefixBytes);
+            return ret;
+        } else {
+            return new byte[] { 0 };
+        }
     }
 
     /**
@@ -135,23 +130,33 @@ public final class Ipv4Util {
      */
     public static Ipv4Prefix prefixForBytes(final byte[] bytes, final int length) {
         Preconditions.checkArgument(length <= bytes.length * Byte.SIZE);
-        final byte[] tmp = Arrays.copyOfRange(bytes, 0, IP4_LENGTH);
-        final InetAddress a = getAddress(tmp);
-        return new Ipv4Prefix(InetAddresses.toAddrString(a) + '/' + length);
+
+        final byte[] tmp;
+        if (bytes.length != IP4_LENGTH) {
+            tmp = Arrays.copyOfRange(bytes, 0, IP4_LENGTH);
+        } else {
+            tmp = bytes;
+        }
+
+        return IetfInetUtil.INSTANCE.ipv4PrefixFor(tmp, length);
     }
 
     /**
      * Creates an Ipv4Prefix object from given ByteBuf. Prefix length is assumed to
      * be in the left most byte of the buffer.
      *
-     * @param bytes IPv4 address
+     * @param buf Buffer containing serialized prefix
      * @return Ipv4Prefix object
      */
-    public static Ipv4Prefix prefixForByteBuf(final ByteBuf bytes) {
-        final int prefixLength = bytes.readByte();
+    public static Ipv4Prefix prefixForByteBuf(final ByteBuf buf) {
+        final int prefixLength = buf.readByte();
         final int size = prefixLength / Byte.SIZE + ((prefixLength % Byte.SIZE == 0) ? 0 : 1);
-        Preconditions.checkArgument(size <= bytes.readableBytes(), "Illegal length of IP prefix: " + (bytes.readableBytes()));
-        return Ipv4Util.prefixForBytes(ByteArray.readBytes(bytes, size), prefixLength);
+        final int readable = buf.readableBytes();
+        Preconditions.checkArgument(size <= readable, "Illegal length of IP prefix: %s/%s", size, readable);
+
+        final byte[] bytes = new byte[IP4_LENGTH];
+        buf.readBytes(bytes, 0, size);
+        return IetfInetUtil.INSTANCE.ipv4PrefixFor(bytes, prefixLength);
     }
 
     /**
@@ -164,14 +169,23 @@ public final class Ipv4Util {
         if (bytes.length == 0) {
             return Collections.emptyList();
         }
-        final List<Ipv4Prefix> list = Lists.newArrayList();
+        final List<Ipv4Prefix> list = new ArrayList<>();
         int byteOffset = 0;
         while (byteOffset < bytes.length) {
-            final int bitLength = UnsignedBytes.toInt(ByteArray.subByte(bytes, byteOffset, 1)[0]);
+            final int bitLength = UnsignedBytes.toInt(bytes[byteOffset]);
             byteOffset += 1;
-            final int byteCount = (bitLength % Byte.SIZE != 0) ? (bitLength / Byte.SIZE) + 1 : bitLength / Byte.SIZE;
-            list.add(prefixForBytes(ByteArray.subByte(bytes, byteOffset, byteCount), bitLength));
-            byteOffset += byteCount;
+            // if length == 0, default route will be added
+            if (bitLength == 0) {
+                list.add(EMPTY_PREFIX);
+                continue;
+            }
+
+            list.add(IetfInetUtil.INSTANCE.ipv4PrefixForShort(bytes, byteOffset, bitLength));
+            byteOffset += bitLength / Byte.SIZE;
+            if (bitLength % Byte.SIZE != 0) {
+                byteOffset++;
+            }
+
         }
         return list;
     }
@@ -186,4 +200,63 @@ public final class Ipv4Util {
         final int sep = prefixValue.indexOf('/');
         return Integer.parseInt(prefixValue.substring(sep + 1, prefixValue.length()));
     }
+
+    /**
+     * Converts InetAddress to IpAddress.
+     *
+     * @param inetAddress
+     * @return IpAddress
+     */
+    public static IpAddress getIpAddress(final InetAddress inetAddress) {
+        return IetfInetUtil.INSTANCE.ipAddressFor(inetAddress);
+    }
+
+    /**
+     * Converts IpAddress and PortNumber to InetSocketAddress
+     *
+     * @param ipAddress
+     * @param port
+     * @return InetSocketAddress
+     */
+    public static InetSocketAddress toInetSocketAddress(final IpAddress ipAddress, final PortNumber port) {
+        final String ipString = toStringIP(ipAddress);
+        return new InetSocketAddress(InetAddresses.forString(ipString), port.getValue());
+    }
+
+    /**
+     * Increment Address
+     *
+     * @param ipv4Address String containing Ipv4Address
+     * @return String containing Ipv4Address incremented by 1
+     */
+    public static String incrementIpv4Address(final String ipv4Address) {
+        return InetAddresses.increment(InetAddresses.forString(ipv4Address)).getHostAddress();
+    }
+
+    /**
+     * Increment Address
+     *
+     * @param ipv4Address ipv4 address to be incremented
+     * @return new ipv4 address
+     */
+    public static Ipv4Address incrementIpv4Address(final Ipv4Address ipv4Address) {
+        return new Ipv4Address(incrementIpv4Address(ipv4Address.getValue()));
+    }
+
+    public static Ipv4Prefix incrementIpv4Prefix(final Ipv4Prefix ipv4Prefix) {
+        final Map.Entry<Ipv4Address, Integer> splitIpv4Prefix = IetfInetUtil.INSTANCE.splitIpv4Prefix(ipv4Prefix);
+        return IetfInetUtil.INSTANCE.ipv4PrefixFor(incrementIpv4Address(splitIpv4Prefix.getKey()), splitIpv4Prefix.getValue());
+    }
+
+    /**
+     * Get string representation of IpAddress
+     * @param ipAddress
+     * @return String value of Ipv4Address or Ipv6Address
+     */
+    public static String toStringIP(final IpAddress ipAddress) {
+        if (ipAddress.getIpv4Address() != null) {
+            return ipAddress.getIpv4Address().getValue();
+        }
+        return ipAddress.getIpv6Address().getValue();
+    }
 }