blob: c3449755ca1ecc8df96ee18fe27111451f3b82b2 [file] [log] [blame]
Jian Lic4d03912017-02-06 00:09:17 +09001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.lisp.msg.types.lcaf;
17
18import io.netty.buffer.ByteBuf;
19import org.onlab.util.ByteOperator;
20import org.onosproject.lisp.msg.exceptions.LispParseError;
21import org.onosproject.lisp.msg.exceptions.LispReaderException;
22import org.onosproject.lisp.msg.exceptions.LispWriterException;
23import org.onosproject.lisp.msg.types.LispAddressReader;
24import org.onosproject.lisp.msg.types.LispAddressWriter;
25import org.onosproject.lisp.msg.types.LispAfiAddress;
26
27import java.util.Objects;
28
29import static com.google.common.base.MoreObjects.toStringHelper;
30import static com.google.common.base.Preconditions.checkNotNull;
31
32/**
33 * Geo Coordinate type LCAF address class.
34 * <p>
35 * Geo Coordinate type is defined in draft-ietf-lisp-lcaf-22
36 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-11
Yuta HIGUCHId1ce4bc2017-06-03 01:05:33 -070037 *
Jian Lic4d03912017-02-06 00:09:17 +090038 * <pre>
39 * {@literal
40 * 0 1 2 3
41 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | AFI = 16387 | Rsvd1 | Flags |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Type = 5 | Rsvd2 | Length |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * |N| Latitude Degrees | Minutes | Seconds |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * |E| Longitude Degrees | Minutes | Seconds |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | Altitude |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * | AFI = x | Address ... |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * }</pre>
56 */
57public final class LispGeoCoordinateLcafAddress extends LispLcafAddress {
58
59 private final boolean north;
60 private final short latitudeDegree;
61 private final byte latitudeMinute;
62 private final byte latitudeSecond;
63 private final boolean east;
64 private final short longitudeDegree;
65 private final byte longitudeMinute;
66 private final byte longitudeSecond;
67 private final int altitude;
68 private final LispAfiAddress address;
69
70 /**
71 * Initializes geo coordinate type LCAF address.
72 *
73 * @param north north flag
74 * @param latitudeDegree latitude degree
75 * @param latitudeMinute latitude minute
76 * @param latitudeSecond latitude second
77 * @param east east flag
78 * @param longitudeDegree longitude degree
79 * @param longitudeMinute longitude minute
80 * @param longitudeSecond longitude second
81 * @param altitude altitude
82 * @param address AFI address
83 */
84 private LispGeoCoordinateLcafAddress(boolean north, short latitudeDegree,
85 byte latitudeMinute, byte latitudeSecond,
86 boolean east, short longitudeDegree,
87 byte longitudeMinute, byte longitudeSecond,
88 int altitude, LispAfiAddress address) {
89 super(LispCanonicalAddressFormatEnum.GEO_COORDINATE);
90 this.north = north;
91 this.latitudeDegree = latitudeDegree;
92 this.latitudeMinute = latitudeMinute;
93 this.latitudeSecond = latitudeSecond;
94 this.east = east;
95 this.longitudeDegree = longitudeDegree;
96 this.longitudeMinute = longitudeMinute;
97 this.longitudeSecond = longitudeSecond;
98 this.altitude = altitude;
99 this.address = address;
100 }
101
102 /**
103 * Obtains north flag value.
104 *
105 * @return north flag value
106 */
107 public boolean isNorth() {
108 return north;
109 }
110
111 /**
112 * Obtains latitude degree.
113 *
114 * @return latitude degree
115 */
116 public short getLatitudeDegree() {
117 return latitudeDegree;
118 }
119
120 /**
121 * Obtains latitude minute.
122 *
123 * @return latitude minute
124 */
125 public byte getLatitudeMinute() {
126 return latitudeMinute;
127 }
128
129 /**
130 * Obtains latitude second.
131 *
132 * @return latitude second
133 */
134 public byte getLatitudeSecond() {
135 return latitudeSecond;
136 }
137
138 /**
139 * Obtains east flag value.
140 *
141 * @return east flag vlaue
142 */
143 public boolean isEast() {
144 return east;
145 }
146
147 /**
148 * Obtains longitude degree.
149 *
150 * @return longitude degree
151 */
152 public short getLongitudeDegree() {
153 return longitudeDegree;
154 }
155
156 /**
157 * Obtains longitude minute.
158 *
159 * @return longitude minute
160 */
161 public byte getLongitudeMinute() {
162 return longitudeMinute;
163 }
164
165 /**
166 * Obtains longitude second.
167 *
168 * @return longitude second
169 */
170 public byte getLongitudeSecond() {
171 return longitudeSecond;
172 }
173
174 /**
175 * Obtains altitude.
176 *
177 * @return altitude
178 */
179 public int getAltitude() {
180 return altitude;
181 }
182
183 /**
184 * Obtains AFI address.
185 *
186 * @return AFI address
187 */
188 public LispAfiAddress getAddress() {
189 return address;
190 }
191
192 @Override
193 public int hashCode() {
194 return Objects.hash(north, latitudeDegree, latitudeMinute, latitudeSecond,
195 east, longitudeDegree, longitudeMinute, longitudeSecond,
196 altitude, address);
197 }
198
199 @Override
200 public boolean equals(Object obj) {
201 if (this == obj) {
202 return true;
203 }
204
205 if (obj instanceof LispGeoCoordinateLcafAddress) {
206 final LispGeoCoordinateLcafAddress other =
207 (LispGeoCoordinateLcafAddress) obj;
208 return Objects.equals(this.north, other.north) &&
209 Objects.equals(this.latitudeDegree, other.latitudeDegree) &&
210 Objects.equals(this.latitudeMinute, other.latitudeMinute) &&
211 Objects.equals(this.latitudeSecond, other.latitudeSecond) &&
212 Objects.equals(this.east, other.east) &&
213 Objects.equals(this.longitudeDegree, other.longitudeDegree) &&
214 Objects.equals(this.longitudeMinute, other.longitudeMinute) &&
215 Objects.equals(this.longitudeSecond, other.longitudeSecond) &&
216 Objects.equals(this.altitude, other.altitude) &&
217 Objects.equals(this.address, other.address);
218 }
219 return false;
220 }
221
222 @Override
223 public String toString() {
224 return toStringHelper(this)
225 .add("north", north)
226 .add("latitude degree", latitudeDegree)
227 .add("latitude minute", latitudeMinute)
228 .add("latitude second", latitudeSecond)
229 .add("east", east)
230 .add("longitude degree", longitudeDegree)
231 .add("longitude minute", longitudeMinute)
232 .add("longitude second", longitudeSecond)
233 .add("altitude", altitude)
234 .add("address", address)
235 .toString();
236 }
237
238 public static final class GeoCoordinateAddressBuilder
239 extends LcafAddressBuilder<GeoCoordinateAddressBuilder> {
240 private boolean north;
241 private short latitudeDegree;
242 private byte latitudeMinute;
243 private byte latitudeSecond;
244 private boolean east;
245 private short longitudeDegree;
246 private byte longitudeMinute;
247 private byte longitudeSecond;
248 private int altitude;
249 private LispAfiAddress address;
250
251 /**
252 * Sets north flag value.
253 *
254 * @param north north flag value
255 * @return GeoCoordinateAddressBuilder object
256 */
257 public GeoCoordinateAddressBuilder withIsNorth(boolean north) {
258 this.north = north;
259 return this;
260 }
261
262 /**
263 * Sets latitude degree.
264 *
265 * @param latitudeDegree latitude degree
266 * @return GeoCoordinateAddressBuilder object
267 */
268 public GeoCoordinateAddressBuilder withLatitudeDegree(short latitudeDegree) {
269 this.latitudeDegree = latitudeDegree;
270 return this;
271 }
272
273 /**
274 * Sets latitude minute.
275 *
276 * @param latitudeMinute latitude minute
277 * @return GeoCoordinateAddressBuilder object
278 */
279 public GeoCoordinateAddressBuilder withLatitudeMinute(byte latitudeMinute) {
280 this.latitudeMinute = latitudeMinute;
281 return this;
282 }
283
284 /**
285 * Sets latitude second.
286 *
287 * @param latitudeSecond latitude second
288 * @return GeoCoordinateAddressBuilder object
289 */
290 public GeoCoordinateAddressBuilder withLatitudeSecond(byte latitudeSecond) {
291 this.latitudeSecond = latitudeSecond;
292 return this;
293 }
294
295 /**
296 * Sets east flag value.
297 *
298 * @param east east flag
299 * @return GeoCoordinateAddressBuilder object
300 */
301 public GeoCoordinateAddressBuilder withIsEast(boolean east) {
302 this.east = east;
303 return this;
304 }
305
306 /**
307 * Sets longitude degree.
308 *
309 * @param longitudeDegree longitude degree
310 * @return GeoCoordinateAddressBuilder object
311 */
312 public GeoCoordinateAddressBuilder withLongitudeDegree(short longitudeDegree) {
313 this.longitudeDegree = longitudeDegree;
314 return this;
315 }
316
317 /**
318 * Sets longitude minute.
319 *
320 * @param longitudeMinute longitude minute
321 * @return GeoCoordinateAddressBuilder object
322 */
323 public GeoCoordinateAddressBuilder withLongitudeMinute(byte longitudeMinute) {
324 this.longitudeMinute = longitudeMinute;
325 return this;
326 }
327
328 /**
329 * Sets longitude second.
330 *
331 * @param longitudeSecond longitude second
332 * @return GeoCoordinateAddressBuilder object
333 */
334 public GeoCoordinateAddressBuilder withLongitudeSecond(byte longitudeSecond) {
335 this.longitudeSecond = longitudeSecond;
336 return this;
337 }
338
339 /**
340 * Sets altitude.
341 *
342 * @param altitude altitude
343 * @return GeoCoordinateAddressBuilder object
344 */
345 public GeoCoordinateAddressBuilder withAltitude(int altitude) {
346 this.altitude = altitude;
347 return this;
348 }
349
350 /**
351 * Sets AFI address.
352 *
353 * @param address AFI address
354 * @return GeoCoordinateAddressBuilder object
355 */
356 public GeoCoordinateAddressBuilder withAddress(LispAfiAddress address) {
357 this.address = address;
358 return this;
359 }
360
361 /**
362 * Builds LispGeoCoordinateLcafAddress instance.
363 *
364 * @return LispGeoCoordinateLcafAddress instance
365 */
Yuta HIGUCHId1ce4bc2017-06-03 01:05:33 -0700366 @Override
Jian Lic4d03912017-02-06 00:09:17 +0900367 public LispGeoCoordinateLcafAddress build() {
368
369 checkNotNull(address, "Must specify an AFI address");
370
371 return new LispGeoCoordinateLcafAddress(north, latitudeDegree,
372 latitudeMinute, latitudeSecond, east, longitudeDegree,
373 longitudeMinute, longitudeSecond, altitude, address);
374 }
375 }
376
377 /**
378 * GeoCoordinate LCAF address reader class.
379 */
380 public static class GeoCoordinateLcafAddressReader
381 implements LispAddressReader<LispGeoCoordinateLcafAddress> {
382
383 private static final int NORTH_INDEX = 7;
384 private static final int EAST_INDEX = 7;
385 private static final int FLAG_SHIFT = 8;
386
387 @Override
388 public LispGeoCoordinateLcafAddress readFrom(ByteBuf byteBuf)
389 throws LispParseError, LispReaderException {
390
391 LispLcafAddress.deserializeCommon(byteBuf);
392
393 // north flag -> 1 bit
394 byte flagWithLatitude = byteBuf.readByte();
395
396 boolean north = ByteOperator.getBit(flagWithLatitude, NORTH_INDEX);
397
398 // latitude degree -> 15 bits
399 short latitudeFirst = flagWithLatitude;
400 if (north) {
401 latitudeFirst = (short) (flagWithLatitude & 0x7F);
402 }
403 short latitude = (short) ((latitudeFirst << FLAG_SHIFT) + byteBuf.readByte());
404
405 // latitude minute -> 8 bits
406 byte latitudeMinute = byteBuf.readByte();
407
408 // latitude second -> 8 bits
409 byte latitudeSecond = byteBuf.readByte();
410
411 // east flag -> 1 bit
412 byte flagWithLongitude = byteBuf.readByte();
413
414 boolean east = ByteOperator.getBit(flagWithLongitude, EAST_INDEX);
415
416 // longitude degree -> 15 bits
417 short longitudeFirst = flagWithLongitude;
418 if (east) {
419 longitudeFirst = (short) (flagWithLongitude & 0x7F);
420 }
421 short longitude = (short) ((longitudeFirst << FLAG_SHIFT) + byteBuf.readByte());
422
423 // longitude minute -> 8 bits
424 byte longitudeMinute = byteBuf.readByte();
425
426 // longitude second -> 8 bits
427 byte longitudeSecond = byteBuf.readByte();
428
429 // altitude -> 32 bits
430 int altitude = byteBuf.readInt();
431
432 LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf);
433
434 return new GeoCoordinateAddressBuilder()
435 .withIsNorth(north)
436 .withLatitudeDegree(latitude)
437 .withLatitudeMinute(latitudeMinute)
438 .withLatitudeSecond(latitudeSecond)
439 .withIsEast(east)
440 .withLongitudeDegree(longitude)
441 .withLongitudeMinute(longitudeMinute)
442 .withLongitudeSecond(longitudeSecond)
443 .withAltitude(altitude)
444 .withAddress(address)
445 .build();
446 }
447 }
448
449 /**
450 * GeoCoordinate LCAF address writer class.
451 */
452 public static class GeoCoordinateLcafAddressWriter
453 implements LispAddressWriter<LispGeoCoordinateLcafAddress> {
454
455 private static final int NORTH_SHIFT_BIT = 15;
456 private static final int EAST_SHIFT_BIT = 15;
457
458 private static final int ENABLE_BIT = 1;
459 private static final int DISABLE_BIT = 0;
460
461 @Override
462 public void writeTo(ByteBuf byteBuf, LispGeoCoordinateLcafAddress address)
463 throws LispWriterException {
464
465 int lcafIndex = byteBuf.writerIndex();
466 LispLcafAddress.serializeCommon(byteBuf, address);
467
468 // north flag + latitude degree
469 short north = DISABLE_BIT;
470 if (address.isNorth()) {
471 north = (short) (ENABLE_BIT << NORTH_SHIFT_BIT);
472 }
473
474 byteBuf.writeShort(north + address.latitudeDegree);
475
476 // latitude minute
477 byteBuf.writeByte(address.latitudeMinute);
478
479 // latitude second
480 byteBuf.writeByte(address.latitudeSecond);
481
482 // east flag + longitude degree
483 short east = DISABLE_BIT;
484 if (address.isEast()) {
485 east = (short) (ENABLE_BIT << EAST_SHIFT_BIT);
486 }
487
488 byteBuf.writeShort(east + address.longitudeDegree);
489
490 // longitude minute
491 byteBuf.writeByte(address.longitudeMinute);
492
493 // longitude second
494 byteBuf.writeByte(address.longitudeSecond);
495
496 // altitude
497 byteBuf.writeInt(address.altitude);
498
499 // address
500 AfiAddressWriter writer = new AfiAddressWriter();
501 writer.writeTo(byteBuf, address.getAddress());
502
503 LispLcafAddress.updateLength(lcafIndex, byteBuf);
504 }
505 }
506}