org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer Maven / Gradle / Ivy
/*
* Copyright (c) 2014 Contextream, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.lispflowmapping.lisp.serializer;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import org.apache.commons.lang3.BooleanUtils;
import org.opendaylight.lispflowmapping.lisp.serializer.address.LispAddressSerializer;
import org.opendaylight.lispflowmapping.lisp.serializer.address.LispAddressSerializerContext;
import org.opendaylight.lispflowmapping.lisp.serializer.exception.LispSerializationException;
import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
import org.opendaylight.lispflowmapping.lisp.util.NumberUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRloc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.ItrRlocKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequestBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class deals with deserializing map request from udp to the java object.
*/
public final class MapRequestSerializer {
private static final MapRequestSerializer INSTANCE = new MapRequestSerializer();
protected static final Logger LOG = LoggerFactory.getLogger(MapRequestSerializer.class);
// Private constructor prevents instantiation from other classes
private MapRequestSerializer() {
}
public static MapRequestSerializer getInstance() {
return INSTANCE;
}
public ByteBuffer serialize(MapRequest mapRequest) {
int size = Length.HEADER_SIZE;
if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
size += LispAddressSerializer.getInstance().getAddressSize(mapRequest.getSourceEid().getEid());
} else {
size += 2;
}
if (mapRequest.getItrRloc() != null) {
for (ItrRloc address : mapRequest.getItrRloc()) {
size += LispAddressSerializer.getInstance().getAddressSize(address.getRloc());
}
}
if (mapRequest.getEidItem() != null) {
for (EidItem record : mapRequest.getEidItem()) {
size += 2 + LispAddressSerializer.getInstance().getAddressSize(record.getEid());
}
}
ByteBuffer requestBuffer = ByteBuffer.allocate(size);
requestBuffer.put((byte) ((byte) (MessageType.MapRequest.getIntValue() << 4)
| ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.getAuthoritative()), Flags.AUTHORITATIVE)
| ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.getMapDataPresent()), Flags.MAP_DATA_PRESENT)
| ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.getProbe()), Flags.PROBE) | ByteUtil.boolToBit(
BooleanUtils.isTrue(mapRequest.getSmr()), Flags.SMR)));
requestBuffer.put((byte) (ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.getPitr()), Flags.PITR)
| ByteUtil.boolToBit(BooleanUtils.isTrue(mapRequest.getSmrInvoked()), Flags.SMR_INVOKED)));
if (mapRequest.getItrRloc() != null) {
int irc = mapRequest.getItrRloc().size();
if (irc > 0) {
irc--;
}
requestBuffer.put((byte) irc);
} else {
requestBuffer.put((byte) 0);
}
if (mapRequest.getEidItem() != null) {
requestBuffer.put((byte) mapRequest.getEidItem().size());
} else {
requestBuffer.put((byte) 0);
}
requestBuffer.putLong(NumberUtil.asLong(mapRequest.getNonce()));
if (mapRequest.getSourceEid() != null && mapRequest.getSourceEid().getEid() != null) {
LispAddressSerializer.getInstance().serialize(requestBuffer, mapRequest.getSourceEid().getEid());
} else {
requestBuffer.putShort((short) 0);
}
if (mapRequest.getItrRloc() != null) {
for (ItrRloc address : mapRequest.getItrRloc()) {
LispAddressSerializer.getInstance().serialize(requestBuffer, address.getRloc());
}
}
if (mapRequest.getEidItem() != null) {
for (EidItem record : mapRequest.getEidItem()) {
requestBuffer.put((byte) 0);
requestBuffer.put((byte) MaskUtil.getMaskForAddress(record.getEid().getAddress()));
LispAddressSerializer.getInstance().serialize(requestBuffer, record.getEid());
}
}
if (mapRequest.getMapReply() != null) {
ByteBuffer replyBuffer = ByteBuffer.allocate(MappingRecordSerializer.getInstance()
.getSerializationSize(mapRequest.getMapReply().getMappingRecord()));
MappingRecordSerializer.getInstance().serialize(replyBuffer, mapRequest.getMapReply().getMappingRecord());
ByteBuffer combinedBuffer = ByteBuffer.allocate(requestBuffer.capacity() + replyBuffer.capacity());
combinedBuffer.put(requestBuffer.array());
combinedBuffer.put(replyBuffer.array());
return combinedBuffer;
}
return requestBuffer;
}
@SuppressWarnings("checkstyle:IllegalCatch")
public MapRequest deserialize(ByteBuffer requestBuffer, InetAddress sourceRloc) {
try {
final byte typeAndFlags = requestBuffer.get();
final int type = typeAndFlags >> 4;
if (MessageType.forValue(type) != MessageType.MapRequest) {
throw new LispSerializationException("Expected Map-Request packet (type 1), but was type " + type);
}
MapRequestBuilder builder = new MapRequestBuilder();
builder.setAuthoritative(ByteUtil.extractBit(typeAndFlags, Flags.AUTHORITATIVE));
builder.setMapDataPresent(ByteUtil.extractBit(typeAndFlags, Flags.MAP_DATA_PRESENT));
builder.setProbe(ByteUtil.extractBit(typeAndFlags, Flags.PROBE));
builder.setSmr(ByteUtil.extractBit(typeAndFlags, Flags.SMR));
final byte moreFlags = requestBuffer.get();
builder.setPitr(ByteUtil.extractBit(moreFlags, Flags.PITR));
builder.setSmrInvoked(ByteUtil.extractBit(moreFlags, Flags.SMR_INVOKED));
final int itrCount = ByteUtil.getUnsignedByte(requestBuffer) + 1;
final int recordCount = ByteUtil.getUnsignedByte(requestBuffer);
builder.setNonce(requestBuffer.getLong());
LispAddressSerializerContext ctx = new LispAddressSerializerContext(
LispAddressSerializerContext.MASK_LEN_MISSING);
builder.setSourceEid(new SourceEidBuilder().setEid(
LispAddressSerializer.getInstance().deserializeEid(requestBuffer, ctx)).build());
if (builder.getItrRloc() == null) {
builder.setItrRloc(new ArrayList());
}
for (int i = 0; i < itrCount; i++) {
Rloc rloc = LispAddressSerializer.getInstance().deserializeRloc(requestBuffer);
builder.getItrRloc().add(new ItrRlocBuilder()
.withKey(new ItrRlocKey(LispAddressStringifier.getString(rloc)))
.setRloc(rloc).build());
}
if (builder.getEidItem() == null) {
builder.setEidItem(new ArrayList());
}
for (int i = 0; i < recordCount; i++) {
Eid eid = EidRecordSerializer.getInstance().deserialize(requestBuffer);
builder.getEidItem().add(new EidItemBuilder()
.withKey(new EidItemKey(LispAddressStringifier.getString(eid)))
.setEid(eid).build());
}
if (builder.getMapDataPresent() && requestBuffer.hasRemaining()) {
try {
builder.setMapReply(new org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
.maprequest.MapReplyBuilder().setMappingRecord(
MappingRecordSerializer.getInstance().deserialize(requestBuffer)).build()).build();
} catch (RuntimeException re) {
LOG.warn("Couldn't deserialize Map-Reply encapsulated in Map-Request", re);
}
}
builder.setSourceRloc(LispAddressUtil.addressBinaryFromInet(sourceRloc));
return builder.build();
} catch (RuntimeException re) {
throw new LispSerializationException("Couldn't deserialize Map-Request (len="
+ requestBuffer.capacity() + ")", re);
}
}
public interface Flags {
byte AUTHORITATIVE = 0x08;
byte MAP_DATA_PRESENT = 0x04;
byte PROBE = 0x02;
byte SMR = 0x01;
byte PITR = (byte) 0x80;
byte SMR_INVOKED = 0x40;
}
private interface Length {
int HEADER_SIZE = 12;
}
}