Move integration tests to mdsal-it-parent
[lispflowmapping.git] / mappingservice / yangmodel / src / main / java / org / opendaylight / lispflowmapping / lisp / serializer / MapRequestSerializer.java
1 /*
2  * Copyright (c) 2014 Contextream, 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.lispflowmapping.lisp.serializer;
9
10 import java.nio.ByteBuffer;
11 import java.util.ArrayList;
12
13 import org.apache.commons.lang3.BooleanUtils;
14 import org.opendaylight.lispflowmapping.lisp.serializer.address.LispAddressSerializer;
15 import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
16 import org.opendaylight.lispflowmapping.lisp.type.LispMessageEnum;
17 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
18 import org.opendaylight.lispflowmapping.lisp.util.LispAFIConvertor;
19 import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.MapRequest;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidrecords.EidRecord;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.eidtolocatorrecords.EidToLocatorRecordBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequest.ItrRloc;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequest.ItrRlocBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequest.SourceEidBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequestnotification.MapRequestBuilder;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * This class deals with deserializing map request from udp to the java object.
32  */
33 public class MapRequestSerializer {
34
35     private static final MapRequestSerializer INSTANCE = new MapRequestSerializer();
36     protected static final Logger LOG = LoggerFactory.getLogger(MapRequestSerializer.class);
37
38     // Private constructor prevents instantiation from other classes
39     private MapRequestSerializer() {
40     }
41
42     public static MapRequestSerializer getInstance() {
43         return INSTANCE;
44     }
45
46     public ByteBuffer serialize(MapRequest mapRequest) {
47         int size = Length.HEADER_SIZE;
48         if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getLispAddressContainer() != null) {
49             size += LispAddressSerializer.getInstance().getAddressSize(
50                     LispAFIConvertor.toAFI(mapRequest.getSourceEid().getLispAddressContainer()));
51         } else {
52             size += 2;
53         }
54         if (mapRequest.getItrRloc() != null) {
55             for (ItrRloc address : mapRequest.getItrRloc()) {
56                 size += LispAddressSerializer.getInstance().getAddressSize(LispAFIConvertor.toAFI(address.getLispAddressContainer()));
57             }
58         }
59         if (mapRequest.getEidRecord() != null) {
60             for (EidRecord record : mapRequest.getEidRecord()) {
61                 size += 2 + LispAddressSerializer.getInstance().getAddressSize(LispAFIConvertor.toAFI(record.getLispAddressContainer()));
62             }
63         }
64         ByteBuffer requestBuffer = ByteBuffer.allocate(size);
65         requestBuffer.put((byte) ((byte) (LispMessageEnum.MapRequest.getValue() << 4)
66                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isAuthoritative()), Flags.AUTHORITATIVE)
67                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isMapDataPresent()), Flags.MAP_DATA_PRESENT)
68                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isProbe()), Flags.PROBE) | ByteUtil.boolToBit(
69                 BooleanUtils.isTrue(mapRequest.isSmr()), Flags.SMR)));
70         requestBuffer.put((byte) (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.isPitr()), Flags.PITR) | ByteUtil.boolToBit(
71                 BooleanUtils.isTrue(mapRequest.isSmrInvoked()), Flags.SMR_INVOKED)));
72         if (mapRequest.getItrRloc() != null) {
73             int IRC = mapRequest.getItrRloc().size();
74             if (IRC > 0) {
75                 IRC--;
76             }
77             requestBuffer.put((byte) (IRC));
78         } else {
79             requestBuffer.put((byte) 0);
80
81         }
82         if (mapRequest.getEidRecord() != null) {
83             requestBuffer.put((byte) mapRequest.getEidRecord().size());
84         } else {
85             requestBuffer.put((byte) 0);
86
87         }
88         requestBuffer.putLong(NumberUtil.asLong(mapRequest.getNonce()));
89         if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getLispAddressContainer() != null) {
90             LispAddressSerializer.getInstance().serialize(requestBuffer,
91                     LispAFIConvertor.toAFI(mapRequest.getSourceEid().getLispAddressContainer()));
92         } else {
93             requestBuffer.putShort((short) 0);
94         }
95         if (mapRequest.getItrRloc() != null) {
96             for (ItrRloc address : mapRequest.getItrRloc()) {
97                 LispAddressSerializer.getInstance().serialize(requestBuffer, LispAFIConvertor.toAFI(address.getLispAddressContainer()));
98             }
99         }
100         if (mapRequest.getEidRecord() != null) {
101             for (EidRecord record : mapRequest.getEidRecord()) {
102                 requestBuffer.put((byte) 0);
103                 requestBuffer.put((byte) record.getMask().byteValue());
104                 LispAddressSerializer.getInstance().serialize(requestBuffer, LispAFIConvertor.toAFI(record.getLispAddressContainer()));
105             }
106         }
107         if (mapRequest.getMapReply() != null) {
108             ByteBuffer replyBuffer = ByteBuffer.allocate(EidToLocatorRecordSerializer.getInstance().getSerializationSize(mapRequest.getMapReply()));
109             EidToLocatorRecordSerializer.getInstance().serialize(replyBuffer, mapRequest.getMapReply());
110             ByteBuffer combinedBuffer = ByteBuffer.allocate(requestBuffer.capacity() + replyBuffer.capacity());
111             combinedBuffer.put(requestBuffer.array());
112             combinedBuffer.put(replyBuffer.array());
113             return combinedBuffer;
114         }
115         return requestBuffer;
116     }
117
118     public MapRequest deserialize(ByteBuffer requestBuffer) {
119         try {
120             MapRequestBuilder builder = new MapRequestBuilder();
121
122             byte typeAndFlags = requestBuffer.get();
123             builder.setAuthoritative(ByteUtil.extractBit(typeAndFlags, Flags.AUTHORITATIVE));
124             builder.setMapDataPresent(ByteUtil.extractBit(typeAndFlags, Flags.MAP_DATA_PRESENT));
125             builder.setProbe(ByteUtil.extractBit(typeAndFlags, Flags.PROBE));
126             builder.setSmr(ByteUtil.extractBit(typeAndFlags, Flags.SMR));
127
128             byte moreFlags = requestBuffer.get();
129             builder.setPitr(ByteUtil.extractBit(moreFlags, Flags.PITR));
130             builder.setSmrInvoked(ByteUtil.extractBit(moreFlags, Flags.SMR_INVOKED));
131
132             int itrCount = ByteUtil.getUnsignedByte(requestBuffer) + 1;
133             int recordCount = ByteUtil.getUnsignedByte(requestBuffer);
134             builder.setNonce(requestBuffer.getLong());
135             builder.setSourceEid(new SourceEidBuilder().setLispAddressContainer(
136                     LispAFIConvertor.toContainer(LispAddressSerializer.getInstance().deserialize(requestBuffer)))
137                     .build());
138
139             if (builder.getItrRloc() == null) {
140                 builder.setItrRloc(new ArrayList<ItrRloc>());
141             }
142             for (int i = 0; i < itrCount; i++) {
143                 builder.getItrRloc().add(
144                         new ItrRlocBuilder().setLispAddressContainer(
145                                 LispAFIConvertor.toContainer(LispAddressSerializer.getInstance().deserialize(requestBuffer)))
146                                 .build());
147             }
148
149             if (builder.getEidRecord() == null) {
150                 builder.setEidRecord(new ArrayList<EidRecord>());
151             }
152             for (int i = 0; i < recordCount; i++) {
153                 builder.getEidRecord().add(EidRecordSerializer.getInstance().deserialize(requestBuffer));
154             }
155             if (builder.isMapDataPresent() && requestBuffer.hasRemaining()) {
156                 try {
157                     builder.setMapReply(new org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.maprequest.MapReplyBuilder(
158                             new EidToLocatorRecordBuilder(EidToLocatorRecordSerializer.getInstance().deserialize(requestBuffer)).build()).build());
159                 } catch (RuntimeException re) {
160                     LOG.warn("couldn't deserialize map reply encapsulated in map request. {}", re.getMessage());
161                 }
162             }
163             return builder.build();
164         } catch (RuntimeException re) {
165             throw new LispSerializationException("Couldn't deserialize Map-Request (len=" + requestBuffer.capacity() + ")", re);
166         }
167     }
168
169     public interface Flags {
170         byte AUTHORITATIVE = 0x08;
171         byte MAP_DATA_PRESENT = 0x04;
172         byte PROBE = 0x02;
173         byte SMR = 0x01;
174
175         byte PITR = (byte) 0x80;
176         byte SMR_INVOKED = 0x40;
177     }
178
179     private interface Length {
180         int HEADER_SIZE = 12;
181     }
182
183 }