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