Add missing list keys where necessary
[lispflowmapping.git] / mappingservice / lisp-proto / src / main / java / org / opendaylight / lispflowmapping / lisp / serializer / MapRegisterSerializer.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.net.InetAddress;
11 import java.nio.ByteBuffer;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.apache.commons.lang3.BooleanUtils;
15 import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
16 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
17 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
18 import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItem;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregisternotification.MapRegisterBuilder;
28
29 /**
30  * This class deals with deserializing map register from udp to the java object.
31  */
32 public final class MapRegisterSerializer {
33
34     private static final MapRegisterSerializer INSTANCE = new MapRegisterSerializer();
35
36     // Private constructor prevents instantiation from other classes
37     private MapRegisterSerializer() {
38     }
39
40     public static MapRegisterSerializer getInstance() {
41         return INSTANCE;
42     }
43
44     public ByteBuffer serialize(MapRegister mapRegister) {
45         int size = Length.HEADER_SIZE;
46         if (mapRegister.getAuthenticationData() != null) {
47             size += mapRegister.getAuthenticationData().length;
48         }
49         if (mapRegister.isXtrSiteIdPresent() != null && mapRegister.isXtrSiteIdPresent()) {
50             size += Length.XTRID_SIZE + Length.SITEID_SIZE;
51         }
52         for (MappingRecordItem eidToLocatorRecord : mapRegister.getMappingRecordItem()) {
53             size += MappingRecordSerializer.getInstance().getSerializationSize(eidToLocatorRecord.getMappingRecord());
54         }
55
56         ByteBuffer registerBuffer = ByteBuffer.allocate(size);
57         registerBuffer.put((byte) ((byte) (MessageType.MapRegister.getIntValue() << 4)
58                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isProxyMapReply()), Flags.PROXY)
59                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isXtrSiteIdPresent()), Flags.XTRSITEID)));
60         registerBuffer.position(registerBuffer.position() + Length.RES);
61         registerBuffer.put((byte)
62                 (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isMergeEnabled()), Flags.MERGE_ENABLED)
63                 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapRegister.isWantMapNotify()), Flags.WANT_MAP_NOTIFY)));
64         registerBuffer.put((byte) mapRegister.getMappingRecordItem().size());
65         registerBuffer.putLong(NumberUtil.asLong(mapRegister.getNonce()));
66         registerBuffer.putShort(NumberUtil.asShort(mapRegister.getKeyId()));
67
68         if (mapRegister.getAuthenticationData() != null) {
69             registerBuffer.putShort((short) mapRegister.getAuthenticationData().length);
70             registerBuffer.put(mapRegister.getAuthenticationData());
71         } else {
72             registerBuffer.putShort((short) 0);
73         }
74         for (MappingRecordItem eidToLocatorRecord : mapRegister.getMappingRecordItem()) {
75             MappingRecordSerializer.getInstance().serialize(registerBuffer, eidToLocatorRecord.getMappingRecord());
76         }
77
78         if (mapRegister.isXtrSiteIdPresent() != null && mapRegister.isXtrSiteIdPresent()) {
79             registerBuffer.put(mapRegister.getXtrId().getValue());
80             registerBuffer.put(mapRegister.getSiteId().getValue());
81         }
82         registerBuffer.clear();
83         return registerBuffer;
84     }
85
86     @SuppressWarnings("checkstyle:IllegalCatch")
87     public MapRegister deserialize(ByteBuffer registerBuffer, InetAddress sourceRloc) {
88         try {
89             final byte typeAndFlags = registerBuffer.get();
90             final int type = typeAndFlags >> 4;
91             if (MessageType.forValue(type) != MessageType.MapRegister) {
92                 throw new LispSerializationException("Expected Map-Register packet (type 3), but was type " + type);
93             }
94
95             MapRegisterBuilder builder = new MapRegisterBuilder();
96             builder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
97
98             boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, Flags.XTRSITEID);
99             builder.setProxyMapReply(ByteUtil.extractBit(typeAndFlags, Flags.PROXY));
100             builder.setXtrSiteIdPresent(xtrSiteIdPresent);
101
102             registerBuffer.position(registerBuffer.position() + Length.RES);
103             byte mergeAndMapReply = registerBuffer.get();
104             builder.setWantMapNotify(ByteUtil.extractBit(mergeAndMapReply, Flags.WANT_MAP_NOTIFY));
105             builder.setMergeEnabled(ByteUtil.extractBit(mergeAndMapReply, Flags.MERGE_ENABLED));
106             byte recordCount = (byte) ByteUtil.getUnsignedByte(registerBuffer);
107             builder.setNonce(registerBuffer.getLong());
108             builder.setKeyId(registerBuffer.getShort());
109             short authenticationLength = registerBuffer.getShort();
110             byte[] authenticationData = new byte[authenticationLength];
111             registerBuffer.get(authenticationData);
112             builder.setAuthenticationData(authenticationData);
113
114             if (xtrSiteIdPresent) {
115                 List<MappingRecordBuilder> mrbs = new ArrayList<MappingRecordBuilder>();
116                 for (int i = 0; i < recordCount; i++) {
117                     mrbs.add(MappingRecordSerializer.getInstance().deserializeToBuilder(registerBuffer));
118                 }
119                 byte[] xtrIdBuf  = new byte[Length.XTRID_SIZE];
120                 registerBuffer.get(xtrIdBuf);
121                 XtrId xtrId = new XtrId(xtrIdBuf);
122                 byte[] siteIdBuf = new byte[Length.SITEID_SIZE];
123                 registerBuffer.get(siteIdBuf);
124                 SiteId siteId = new SiteId(siteIdBuf);
125                 builder.setXtrId(xtrId);
126                 builder.setSiteId(siteId);
127                 int idx = 0;
128                 for (MappingRecordBuilder mrb : mrbs) {
129                     mrb.setXtrId(xtrId);
130                     mrb.setSiteId(siteId);
131                     mrb.setSourceRloc(LispAddressUtil.addressBinaryFromInet(sourceRloc));
132                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder()
133                             .withKey(new MappingRecordItemKey(Integer.toString(idx)))
134                             .setMappingRecord(mrb.build()).build());
135                     idx++;
136                 }
137             } else {
138                 for (int i = 0; i < recordCount; i++) {
139                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder()
140                             .withKey(new MappingRecordItemKey(Integer.toString(i)))
141                             .setMappingRecord(MappingRecordSerializer.getInstance().deserialize(registerBuffer))
142                             .build());
143                 }
144             }
145
146             registerBuffer.limit(registerBuffer.position());
147             byte[] mapRegisterBytes = new byte[registerBuffer.position()];
148             registerBuffer.position(0);
149             registerBuffer.get(mapRegisterBytes);
150             return builder.build();
151         } catch (RuntimeException re) {
152             throw new LispSerializationException("Couldn't deserialize Map-Register (len="
153                     + registerBuffer.capacity() + ")", re);
154         }
155     }
156
157     private interface Flags {
158         byte PROXY = 0x08;
159         byte XTRSITEID = 0x02;
160         byte MERGE_ENABLED = 0x04;
161         byte WANT_MAP_NOTIFY = 0x01;
162     }
163
164     public interface Length {
165         int HEADER_SIZE = 16;
166         int XTRID_SIZE = 16;
167         int SITEID_SIZE = 8;
168         int RES = 1;
169     }
170 }