2 * Copyright (c) 2014 Contextream, Inc. and others. All rights reserved.
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
8 package org.opendaylight.lispflowmapping.lisp.serializer;
10 import java.nio.ByteBuffer;
11 import java.util.ArrayList;
12 import java.util.List;
13 import org.apache.commons.lang3.BooleanUtils;
14 import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
15 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
16 import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItem;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.list.MappingRecordItemKey;
28 * This class deals with serializing map notify from the java object to udp.
30 public final class MapNotifySerializer {
32 private static final MapNotifySerializer INSTANCE = new MapNotifySerializer();
34 // Private constructor prevents instantiation from other classes
35 private MapNotifySerializer() {
38 public static MapNotifySerializer getInstance() {
42 public ByteBuffer serialize(MapNotify mapNotify) {
43 int size = Length.HEADER_SIZE;
44 if (mapNotify.getAuthenticationData() != null) {
45 size += mapNotify.getAuthenticationData().length;
47 if (mapNotify.isXtrSiteIdPresent() != null && mapNotify.isXtrSiteIdPresent()) {
48 size += org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer.Length.XTRID_SIZE
49 + org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer.Length.SITEID_SIZE;
51 for (MappingRecordItem mappingRecord : mapNotify.getMappingRecordItem()) {
52 size += MappingRecordSerializer.getInstance().getSerializationSize(mappingRecord.getMappingRecord());
55 ByteBuffer replyBuffer = ByteBuffer.allocate(size);
56 replyBuffer.put((byte) ((byte) (MessageType.MapNotify.getIntValue() << 4)
57 | ByteUtil.boolToBit(BooleanUtils.isTrue(mapNotify.isXtrSiteIdPresent()), Flags.XTRSITEID)));
58 replyBuffer.position(replyBuffer.position() + Length.RES);
59 replyBuffer.put(ByteUtil.boolToBit(BooleanUtils.isTrue(mapNotify.isMergeEnabled()), Flags.MERGE_ENABLED));
60 if (mapNotify.getMappingRecordItem() != null) {
61 replyBuffer.put((byte) mapNotify.getMappingRecordItem().size());
63 replyBuffer.put((byte) 0);
65 replyBuffer.putLong(NumberUtil.asLong(mapNotify.getNonce()));
66 replyBuffer.putShort(NumberUtil.asShort(mapNotify.getKeyId()));
67 if (mapNotify.getAuthenticationData() != null) {
68 replyBuffer.putShort((short) mapNotify.getAuthenticationData().length);
69 replyBuffer.put(mapNotify.getAuthenticationData());
71 replyBuffer.putShort((short) 0);
74 if (mapNotify.getMappingRecordItem() != null) {
75 for (MappingRecordItem mappingRecord : mapNotify.getMappingRecordItem()) {
76 MappingRecordSerializer.getInstance().serialize(replyBuffer, mappingRecord.getMappingRecord());
80 if (mapNotify.isXtrSiteIdPresent() != null && mapNotify.isXtrSiteIdPresent()) {
81 replyBuffer.put(mapNotify.getXtrId().getValue());
82 replyBuffer.put(mapNotify.getSiteId().getValue());
88 @SuppressWarnings("checkstyle:IllegalCatch")
89 public MapNotify deserialize(ByteBuffer notifyBuffer) {
91 final byte typeAndFlags = notifyBuffer.get();
92 final int type = typeAndFlags >> 4;
93 if (MessageType.forValue(type) != MessageType.MapNotify) {
94 throw new LispSerializationException("Expected Map-Notify packet (type 4), but was type " + type);
97 MapNotifyBuilder builder = new MapNotifyBuilder();
98 builder.setMappingRecordItem(new ArrayList<MappingRecordItem>());
100 boolean xtrSiteIdPresent = ByteUtil.extractBit(typeAndFlags, Flags.XTRSITEID);
101 builder.setXtrSiteIdPresent(xtrSiteIdPresent);
103 notifyBuffer.position(notifyBuffer.position() + Length.RES);
104 builder.setMergeEnabled(ByteUtil.extractBit(notifyBuffer.get(), Flags.MERGE_ENABLED));
106 byte recordCount = (byte) ByteUtil.getUnsignedByte(notifyBuffer);
107 builder.setNonce(notifyBuffer.getLong());
108 builder.setKeyId(notifyBuffer.getShort());
109 short authenticationLength = notifyBuffer.getShort();
110 byte[] authenticationData = new byte[authenticationLength];
111 notifyBuffer.get(authenticationData);
112 builder.setAuthenticationData(authenticationData);
114 if (xtrSiteIdPresent) {
115 List<MappingRecordBuilder> mrbs = new ArrayList<MappingRecordBuilder>();
116 for (int i = 0; i < recordCount; i++) {
117 mrbs.add(MappingRecordSerializer.getInstance().deserializeToBuilder(notifyBuffer));
119 byte[] xtrIdBuf = new byte[MapRegisterSerializer.Length.XTRID_SIZE];
120 notifyBuffer.get(xtrIdBuf);
121 XtrId xtrId = new XtrId(xtrIdBuf);
122 byte[] siteIdBuf = new byte[MapRegisterSerializer.Length.SITEID_SIZE];
123 notifyBuffer.get(siteIdBuf);
124 SiteId siteId = new SiteId(siteIdBuf);
125 builder.setXtrId(xtrId);
126 builder.setSiteId(siteId);
128 for (MappingRecordBuilder mrb : mrbs) {
130 mrb.setSiteId(siteId);
131 builder.getMappingRecordItem().add(new MappingRecordItemBuilder()
132 .withKey(new MappingRecordItemKey(Integer.toString(idx)))
133 .setMappingRecord(mrb.build()).build());
137 for (int i = 0; i < recordCount; i++) {
138 builder.getMappingRecordItem().add(new MappingRecordItemBuilder()
139 .withKey(new MappingRecordItemKey(Integer.toString(i)))
140 .setMappingRecord(MappingRecordSerializer.getInstance().deserialize(notifyBuffer))
145 notifyBuffer.limit(notifyBuffer.position());
146 return builder.build();
147 } catch (RuntimeException re) {
148 throw new LispSerializationException("Couldn't deserialize Map-Notify (len="
149 + notifyBuffer.capacity() + ")", re);
153 private interface Flags {
154 byte XTRSITEID = 0x08;
155 byte MERGE_ENABLED = 0x04;
158 private interface Length {
159 int HEADER_SIZE = 16;