Merge "Bug-612: Added ByteBufWriteUtil class"
[bgpcep.git] / util / src / main / java / org / opendaylight / protocol / util / Ipv4Util.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.util;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Lists;
12 import com.google.common.net.InetAddresses;
13 import com.google.common.primitives.Bytes;
14 import com.google.common.primitives.UnsignedBytes;
15
16 import io.netty.buffer.ByteBuf;
17
18 import java.net.Inet4Address;
19 import java.net.InetAddress;
20 import java.net.UnknownHostException;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.List;
24
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
28
29 /**
30  * Util class for creating generated Ipv4Address.
31  */
32 public final class Ipv4Util {
33
34     private Ipv4Util() {
35     }
36
37     public static final int IP4_LENGTH = 4;
38
39     /**
40      * Converts byte array to Inet4Address.
41      *
42      * @param bytes to be converted
43      * @return InetAddress instance
44      * @throws IllegalArgumentException if {@link UnknownHostException} is thrown.
45      */
46     private static InetAddress getAddress(final byte[] bytes) {
47         try {
48             return Inet4Address.getByAddress(bytes);
49         } catch (final UnknownHostException e) {
50             throw new IllegalArgumentException("Failed to construct IPv4 address", e);
51         }
52     }
53
54     /**
55      * Converts byte array to Ipv4Address.
56      *
57      * @param bytes to be converted to Ipv4Address
58      * @return Ipv4Address
59      */
60     public static Ipv4Address addressForBytes(final byte[] bytes) {
61         return new Ipv4Address(InetAddresses.toAddrString(getAddress(bytes)));
62     }
63
64     /**
65      * Reads from ByteBuf buffer and converts bytes to Ipv4Address.
66      *
67      * @param buffer containing Ipv4 address, starting at reader index
68      * @return Ipv4Address
69      */
70     public static Ipv4Address addressForByteBuf(final ByteBuf buffer) {
71         return addressForBytes(ByteArray.readBytes(buffer, IP4_LENGTH));
72     }
73
74     /**
75      * Converts Ipv4Address to byte array.
76      *
77      * @param address Ipv4Address to be converted
78      * @return byte array
79      */
80     public static byte[] bytesForAddress(final Ipv4Address address) {
81         final InetAddress a = InetAddresses.forString(address.getValue());
82         Preconditions.checkArgument(a instanceof Inet4Address);
83         return a.getAddress();
84     }
85
86     /**
87      * Returns number of minimum bytes needed to cover all bits of prefix.
88      *
89      * @param prefix
90      * @return
91      */
92     public static int getPrefixLengthBytes(final String prefix) {
93         int bits = Ipv4Util.getPrefixLength(prefix);
94         if (bits % 8 != 0) {
95             return (bits / 8) + 1;
96         }
97         return bits / 8;
98     }
99
100     /**
101      * Converts Ipv4Prefix to byte array of length equal to prefix length value.
102      *
103      * @param ipv4Prefix Ipv4Prefix to be converted
104      * @return byte array
105      */
106     public static byte[] bytesForPrefixByPrefixLength(Ipv4Prefix ipv4Prefix) {
107         return ByteArray.subByte(bytesForPrefix(ipv4Prefix), 0,
108                 getPrefixLengthBytes(ipv4Prefix.getValue()));
109     }
110
111     /**
112      * Converts Ipv4Prefix to byte array. Prefix length at the end.
113      *
114      * @param prefix Ipv4Prefix to be converted
115      * @return byte array with prefix length at the end
116      */
117     public static byte[] bytesForPrefix(final Ipv4Prefix prefix) {
118         final String p = prefix.getValue();
119         final int sep = p.indexOf('/');
120         final InetAddress a = InetAddresses.forString(p.substring(0, sep));
121         Preconditions.checkArgument(a instanceof Inet4Address);
122         final byte[] bytes = a.getAddress();
123         return Bytes.concat(bytes, new byte[] { Byte.valueOf(p.substring(sep + 1, p.length())) });
124     }
125
126     /**
127      * Converts Ipv4Prefix to byte array. Prefix length at the beginning.
128      * Prefix bytes are trimmed from the end to match prefix length.
129      *
130      * @param prefix Ipv4Prefix to be converted
131      * @return byte array with the prefix length at the beginning
132      */
133     public static byte[] bytesForPrefixBegin(final Ipv4Prefix prefix) {
134         final String p = prefix.getValue();
135         final int sep = p.indexOf('/');
136         final InetAddress a = InetAddresses.forString(p.substring(0, sep));
137         Preconditions.checkArgument(a instanceof Inet4Address);
138         final byte[] bytes = a.getAddress();
139         final int length = getPrefixLength(p);
140         return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(length) }, ByteArray.subByte(bytes, 0 , getPrefixLengthBytes(p)));
141     }
142
143     /**
144      * Creates an Ipv4Prefix object from given byte array.
145      *
146      * @param bytes  IPv4 address
147      * @param length prefix length
148      * @return Ipv4Prefix object
149      */
150     public static Ipv4Prefix prefixForBytes(final byte[] bytes, final int length) {
151         Preconditions.checkArgument(length <= bytes.length * Byte.SIZE);
152         final byte[] tmp = Arrays.copyOfRange(bytes, 0, IP4_LENGTH);
153         final InetAddress a = getAddress(tmp);
154         return new Ipv4Prefix(InetAddresses.toAddrString(a) + '/' + length);
155     }
156
157     /**
158      * Creates a list of Ipv4 Prefixes from given byte array.
159      *
160      * @param bytes to be converted to List of Ipv4Prefixes.
161      * @return List<Ipv4Prefix>
162      */
163     public static List<Ipv4Prefix> prefixListForBytes(final byte[] bytes) {
164         if (bytes.length == 0) {
165             return Collections.emptyList();
166         }
167         final List<Ipv4Prefix> list = Lists.newArrayList();
168         int byteOffset = 0;
169         while (byteOffset < bytes.length) {
170             final int bitLength = UnsignedBytes.toInt(ByteArray.subByte(bytes, byteOffset, 1)[0]);
171             byteOffset += 1;
172             final int byteCount = (bitLength % Byte.SIZE != 0) ? (bitLength / Byte.SIZE) + 1 : bitLength / Byte.SIZE;
173             list.add(prefixForBytes(ByteArray.subByte(bytes, byteOffset, byteCount), bitLength));
174             byteOffset += byteCount;
175         }
176         return list;
177     }
178
179     /**
180      * Obtains prefix length from given prefix.
181      *
182      * @param prefix
183      * @return prefix length
184      */
185     public static int getPrefixLength(final IpPrefix prefix) {
186         String p = "";
187         if (prefix.getIpv4Prefix() != null) {
188             p = prefix.getIpv4Prefix().getValue();
189         } else {
190             p = prefix.getIpv6Prefix().getValue();
191         }
192         return getPrefixLength(p);
193     }
194
195     /**
196      * Obtains prefix length from given string prefix.
197      *
198      * @param prefixValue value of prefix
199      * @return prefix length
200      */
201     public static int getPrefixLength(final String prefixValue) {
202         final int sep = prefixValue.indexOf('/');
203         return Integer.valueOf(prefixValue.substring(sep + 1, prefixValue.length()));
204     }
205 }