blob: 87167fb22f1eb58092b79f6d2dabbef1ed1677db [file] [log] [blame]
Yotam Harcholf3f11152013-09-05 16:47:16 -07001package org.projectfloodlight.openflow.types;
2
Andreas Wundsam85c961f2013-09-29 21:22:12 -07003import java.util.Arrays;
4
Yotam Harcholf3f11152013-09-05 16:47:16 -07005import org.jboss.netty.buffer.ChannelBuffer;
6
Andreas Wundsam22ba3af2013-10-04 16:00:30 -07007import com.google.common.hash.PrimitiveSink;
Andreas Wundsam85c961f2013-09-29 21:22:12 -07008import com.google.common.primitives.UnsignedInts;
9
Yotam Harcholf3f11152013-09-05 16:47:16 -070010
11
12/**
Yotam Harchola289d552013-09-16 10:10:40 -070013 * Wrapper around an IPv4Address address
Yotam Harcholf3f11152013-09-05 16:47:16 -070014 *
15 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
16 */
Yotam Harchol4d634682013-09-26 13:21:06 -070017public class IPv4Address extends IPAddress<IPv4Address> {
Yotam Harcholf3f11152013-09-05 16:47:16 -070018 static final int LENGTH = 4;
19 private final int rawValue;
Yotam Harcholf3f11152013-09-05 16:47:16 -070020
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070021 private final static int NONE_VAL = 0x0;
22 public final static IPv4Address NONE = new IPv4Address(NONE_VAL);
23
Yotam Harchola289d552013-09-16 10:10:40 -070024 public static final IPv4Address NO_MASK = IPv4Address.of(0xFFFFFFFF);
25 public static final IPv4Address FULL_MASK = IPv4Address.of(0x00000000);
26
27 private IPv4Address(final int rawValue) {
Yotam Harcholf3f11152013-09-05 16:47:16 -070028 this.rawValue = rawValue;
29 }
30
Yotam Harchol4d634682013-09-26 13:21:06 -070031 @Override
Yotam Harcholeb023dc2013-09-26 15:45:44 -070032 public IPVersion getIpVersion() {
33 return IPVersion.IPv4;
Yotam Harchol4d634682013-09-26 13:21:06 -070034 }
35
Gregor Maier7f987e62013-12-10 19:34:18 -080036
37 @Override
38 public int asCidrMaskLength() {
39 int maskint = getInt();
40 if (maskint == 0)
41 return 0;
42 else if (Integer.bitCount((~maskint) + 1) == 1) {
43 // IP represents a true CIDR prefix length
44 return Integer.bitCount(maskint);
45 } else {
46 // IP is not a true prefix.
47 return -1;
48 }
49 }
50
Yotam Harchola289d552013-09-16 10:10:40 -070051 public static IPv4Address of(final byte[] address) {
Gregor Maier1ff55972013-12-11 02:22:56 -080052 if (address == null) {
53 throw new NullPointerException("Address must not be null");
54 }
Yotam Harcholf3f11152013-09-05 16:47:16 -070055 if (address.length != LENGTH) {
56 throw new IllegalArgumentException(
Andreas Wundsamc85b5c52013-09-24 13:01:43 -070057 "Invalid byte array length for IPv4Address address: " + address.length);
Yotam Harcholf3f11152013-09-05 16:47:16 -070058 }
59
60 int raw =
61 (address[0] & 0xFF) << 24 | (address[1] & 0xFF) << 16
62 | (address[2] & 0xFF) << 8 | (address[3] & 0xFF) << 0;
Yotam Harchola289d552013-09-16 10:10:40 -070063 return IPv4Address.of(raw);
Yotam Harcholf3f11152013-09-05 16:47:16 -070064 }
65
Yotam Harchola289d552013-09-16 10:10:40 -070066 public static IPv4Address of(final int raw) {
Andreas Wundsamb75c4ad2013-09-23 14:45:35 -070067 if(raw == NONE_VAL)
68 return NONE;
Yotam Harchola289d552013-09-16 10:10:40 -070069 return new IPv4Address(raw);
Yotam Harcholf3f11152013-09-05 16:47:16 -070070 }
71
Yotam Harchola289d552013-09-16 10:10:40 -070072 public static IPv4Address of(final String string) {
Gregor Maier1ff55972013-12-11 02:22:56 -080073 if (string == null) {
74 throw new NullPointerException("String must not be null");
75 }
Yotam Harcholf3f11152013-09-05 16:47:16 -070076 int start = 0;
77 int shift = 24;
78
79 int raw = 0;
80 while (shift >= 0) {
81 int end = string.indexOf('.', start);
82 if (end == start || !((shift > 0) ^ (end < 0)))
83 throw new IllegalArgumentException("IP Address not well formed: " + string);
84
85 String substr =
86 end > 0 ? string.substring(start, end) : string.substring(start);
87 int val = Integer.parseInt(substr);
88 if (val < 0 || val > 255)
89 throw new IllegalArgumentException("IP Address not well formed: " + string);
90
91 raw |= val << shift;
92
93 shift -= 8;
94 start = end + 1;
95 }
Yotam Harchola289d552013-09-16 10:10:40 -070096 return IPv4Address.of(raw);
Yotam Harcholf3f11152013-09-05 16:47:16 -070097 }
98
99 public int getInt() {
100 return rawValue;
101 }
102
103 volatile byte[] bytesCache = null;
104
105 public byte[] getBytes() {
106 if (bytesCache == null) {
107 synchronized (this) {
108 if (bytesCache == null) {
109 bytesCache =
110 new byte[] { (byte) ((rawValue >>> 24) & 0xFF),
111 (byte) ((rawValue >>> 16) & 0xFF),
112 (byte) ((rawValue >>> 8) & 0xFF),
113 (byte) ((rawValue >>> 0) & 0xFF) };
114 }
115 }
116 }
117 return bytesCache;
118 }
119
120 @Override
121 public int getLength() {
122 return LENGTH;
123 }
124
125 @Override
126 public String toString() {
127 StringBuilder res = new StringBuilder();
128 res.append((rawValue >> 24) & 0xFF).append('.');
129 res.append((rawValue >> 16) & 0xFF).append('.');
130 res.append((rawValue >> 8) & 0xFF).append('.');
131 res.append((rawValue >> 0) & 0xFF);
132 return res.toString();
133 }
134
Yotam Harcholf3f11152013-09-05 16:47:16 -0700135 public void write4Bytes(ChannelBuffer c) {
136 c.writeInt(rawValue);
137 }
Yotam Harchola289d552013-09-16 10:10:40 -0700138
139 public static IPv4Address read4Bytes(ChannelBuffer c) {
140 return IPv4Address.of(c.readInt());
Yotam Harcholf3f11152013-09-05 16:47:16 -0700141 }
142
143 @Override
Yotam Harchola289d552013-09-16 10:10:40 -0700144 public IPv4Address applyMask(IPv4Address mask) {
145 return IPv4Address.of(this.rawValue & mask.rawValue);
Yotam Harcholf3f11152013-09-05 16:47:16 -0700146 }
147
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700148 @Override
149 public int hashCode() {
150 final int prime = 31;
151 int result = 1;
152 result = prime * result + Arrays.hashCode(bytesCache);
153 result = prime * result + rawValue;
154 return result;
155 }
Yotam Harchola289d552013-09-16 10:10:40 -0700156
Andreas Wundsam85c961f2013-09-29 21:22:12 -0700157 @Override
158 public boolean equals(Object obj) {
159 if (this == obj)
160 return true;
161 if (obj == null)
162 return false;
163 if (getClass() != obj.getClass())
164 return false;
165 IPv4Address other = (IPv4Address) obj;
166 if (!Arrays.equals(bytesCache, other.bytesCache))
167 return false;
168 if (rawValue != other.rawValue)
169 return false;
170 return true;
171 }
172
173 @Override
174 public int compareTo(IPv4Address o) {
175 return UnsignedInts.compare(rawValue, o.rawValue);
176 }
Andreas Wundsam22ba3af2013-10-04 16:00:30 -0700177
178 @Override
179 public void putTo(PrimitiveSink sink) {
180 sink.putInt(rawValue);
181 }
182
Yotam Harcholf3f11152013-09-05 16:47:16 -0700183}