View Javadoc

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  import java.util.List;
13  
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.NumberUtil;
18  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
19  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
20  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
21  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
22  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItem;
23  import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
24  
25  /**
26   * This class deals with serializing map notify from the java object to udp.
27   */
28  public final class MapNotifySerializer {
29  
30      private static final MapNotifySerializer INSTANCE = new MapNotifySerializer();
31  
32      // Private constructor prevents instantiation from other classes
33      private MapNotifySerializer() {
34      }
35  
36      public static MapNotifySerializer getInstance() {
37          return INSTANCE;
38      }
39  
40      public ByteBuffer serialize(MapNotify mapNotify) {
41          int size = Length.HEADER_SIZE;
42          if (mapNotify.getAuthenticationData() != null) {
43              size += mapNotify.getAuthenticationData().length;
44          }
45          if (mapNotify.isXtrSiteIdPresent() != null && mapNotify.isXtrSiteIdPresent()) {
46              size += org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer.Length.XTRID_SIZE +
47                      org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer.Length.SITEID_SIZE;
48          }
49          for (MappingRecordItem mappingRecord : mapNotify.getMappingRecordItem()) {
50              size += MappingRecordSerializer.getInstance().getSerializationSize(mappingRecord.getMappingRecord());
51          }
52  
53          ByteBuffer replyBuffer = ByteBuffer.allocate(size);
54          replyBuffer.put((byte) (MessageType.MapNotify.getIntValue() << 4));
55          replyBuffer.position(replyBuffer.position() + Length.RES);
56          replyBuffer.put(ByteUtil.boolToBit(BooleanUtils.isTrue(mapNotify.isMergeEnabled()), Flags.MERGE_ENABLED));
57          if (mapNotify.getMappingRecordItem() != null) {
58              replyBuffer.put((byte) mapNotify.getMappingRecordItem().size());
59          } else {
60              replyBuffer.put((byte) 0);
61          }
62          replyBuffer.putLong(NumberUtil.asLong(mapNotify.getNonce()));
63          replyBuffer.putShort(NumberUtil.asShort(mapNotify.getKeyId()));
64          if (mapNotify.getAuthenticationData() != null) {
65              replyBuffer.putShort((short) mapNotify.getAuthenticationData().length);
66              replyBuffer.put(mapNotify.getAuthenticationData());
67          } else {
68              replyBuffer.putShort((short) 0);
69          }
70  
71          if (mapNotify.getMappingRecordItem() != null) {
72              for (MappingRecordItem mappingRecord : mapNotify.getMappingRecordItem()) {
73                  MappingRecordSerializer.getInstance().serialize(replyBuffer, mappingRecord.getMappingRecord());
74              }
75          }
76  
77          if (mapNotify.isXtrSiteIdPresent() != null && mapNotify.isXtrSiteIdPresent()) {
78              replyBuffer.put(mapNotify.getXtrId());
79              replyBuffer.put(mapNotify.getSiteId());
80          }
81          replyBuffer.clear();
82          return replyBuffer;
83      }
84  
85      public MapNotify deserialize(ByteBuffer notifyBuffer) {
86          try {
87              MapNotifyBuilder builder = new MapNotifyBuilder();
88              builder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
89  
90              byte typeAndFlags = notifyBuffer.get();
91              boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, Flags.XTRSITEID);
92              builder.setXtrSiteIdPresent(xtrSiteIdPresent);
93  
94              notifyBuffer.position(notifyBuffer.position() + Length.RES);
95              builder.setMergeEnabled(ByteUtil.extractBit(notifyBuffer.get(), Flags.MERGE_ENABLED));
96  
97              byte recordCount = (byte) ByteUtil.getUnsignedByte(notifyBuffer);
98              builder.setNonce(notifyBuffer.getLong());
99              builder.setKeyId(notifyBuffer.getShort());
100             short authenticationLength = notifyBuffer.getShort();
101             byte[] authenticationData = new byte[authenticationLength];
102             notifyBuffer.get(authenticationData);
103             builder.setAuthenticationData(authenticationData);
104 
105             if (xtrSiteIdPresent) {
106                 List<MappingRecordBuilder> mrbs = new ArrayList<MappingRecordBuilder>();
107                 for (int i = 0; i < recordCount; i++) {
108                     mrbs.add(MappingRecordSerializer.getInstance().deserializeToBuilder(notifyBuffer));
109                 }
110                 byte[] xtrId  = new byte[MapRegisterSerializer.Length.XTRID_SIZE];
111                 notifyBuffer.get(xtrId);
112                 byte[] siteId = new byte[MapRegisterSerializer.Length.SITEID_SIZE];
113                 notifyBuffer.get(siteId);
114                 builder.setXtrId(xtrId);
115                 builder.setSiteId(siteId);
116                 for (MappingRecordBuilder mrb : mrbs) {
117                     mrb.setXtrId(xtrId);
118                     mrb.setSiteId(siteId);
119                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(
120                             mrb.build()).build());
121                 }
122             } else {
123                 for (int i = 0; i < recordCount; i++) {
124                     builder.getMappingRecordItem().add(new MappingRecordItemBuilder().setMappingRecord(
125                             MappingRecordSerializer.getInstance().deserialize(notifyBuffer)).build());
126                 }
127             }
128 
129             notifyBuffer.limit(notifyBuffer.position());
130             return builder.build();
131         } catch (RuntimeException re) {
132             throw new LispSerializationException("Couldn't deserialize Map-Notify (len=" + notifyBuffer.capacity() + ")", re);
133         }
134     }
135 
136     private interface Flags {
137         byte XTRSITEID = 0x08;
138         byte MERGE_ENABLED = 0x04;
139     }
140 
141     private interface Length {
142         int HEADER_SIZE = 16;
143         int RES = 1;
144     }
145 
146 }