Switch source-rloc and transport-address to binary
[lispflowmapping.git] / mappingservice / southbound / src / main / java / org / opendaylight / lispflowmapping / southbound / lisp / LispXtrSouthboundHandler.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
9 package org.opendaylight.lispflowmapping.southbound.lisp;
10
11 import io.netty.buffer.ByteBufUtil;
12 import io.netty.channel.ChannelHandlerContext;
13 import io.netty.channel.SimpleChannelInboundHandler;
14 import io.netty.channel.socket.DatagramPacket;
15
16 import java.net.InetAddress;
17 import java.nio.ByteBuffer;
18
19 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
20 import org.opendaylight.lispflowmapping.southbound.util.LispNotificationHelper;
21 import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
22 import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
23 import org.opendaylight.lispflowmapping.lisp.util.MapRequestUtil;
24 import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
25 import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
26 import org.opendaylight.lispflowmapping.southbound.lisp.exception.LispMalformedPacketException;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRequest;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MessageType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrReplyMappingBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMappingBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddressBuilder;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 public class LispXtrSouthboundHandler extends SimpleChannelInboundHandler<DatagramPacket>
38         implements ILispSouthboundService {
39     private NotificationPublishService notificationPublishService;
40     protected static final Logger LOG = LoggerFactory.getLogger(LispXtrSouthboundHandler.class);
41
42     public void setNotificationProvider(NotificationPublishService nps) {
43         this.notificationPublishService = nps;
44     }
45
46     public void handlePacket(DatagramPacket packet) {
47         ByteBuffer inBuffer = packet.content().nioBuffer();
48         Object lispType = MessageType.forValue((int) (ByteUtil.getUnsignedByte(inBuffer, LispMessage.Pos.TYPE) >> 4));
49         if (lispType == MessageType.MapRequest) {
50             LOG.trace("Received packet of type MapRequest for xTR");
51             handleMapRequest(inBuffer);
52         } else if (lispType ==  MessageType.MapReply){
53             LOG.trace("Received packet of type MapReply for xTR");
54             handleMapReply(inBuffer);
55         } else {
56             LOG.warn("Received unknown packet type");
57         }
58     }
59
60     private void handleMapRequest(ByteBuffer inBuffer) {
61         try {
62             MapRequest request = MapRequestSerializer.getInstance().deserialize(inBuffer);
63             InetAddress finalSourceAddress = MapRequestUtil.selectItrRloc(request);
64             if (finalSourceAddress == null) {
65                 throw new LispMalformedPacketException("Couldn't deserialize Map-Request, no ITR Rloc found!");
66             }
67
68             XtrRequestMappingBuilder requestMappingBuilder = new XtrRequestMappingBuilder();
69             requestMappingBuilder.setMapRequest(LispNotificationHelper.convertMapRequest(request));
70             TransportAddressBuilder transportAddressBuilder = new TransportAddressBuilder();
71             transportAddressBuilder.setIpAddress(
72                     LispNotificationHelper.getIpAddressBinaryFromInetAddress(finalSourceAddress));
73             transportAddressBuilder.setPort(new PortNumber(LispMessage.PORT_NUM));
74             requestMappingBuilder.setTransportAddress(transportAddressBuilder.build());
75             if (notificationPublishService != null) {
76                 notificationPublishService.putNotification(requestMappingBuilder.build());
77                 LOG.trace("MapRequest was published!");
78             } else {
79                 LOG.warn("Notification Provider is null!");
80             }
81         } catch (RuntimeException re) {
82             throw new LispMalformedPacketException(
83                     "Couldn't deserialize Map-Request (len=" + inBuffer.capacity() + ")", re);
84         } catch (InterruptedException e) {
85             LOG.warn("Notification publication interrupted!");
86         }
87     }
88
89     private void handleMapReply(ByteBuffer buffer) {
90         try {
91             MapReply reply = MapReplySerializer.getInstance().deserialize(buffer);
92
93             XtrReplyMappingBuilder replyMappingBuilder = new XtrReplyMappingBuilder();
94             replyMappingBuilder.setMapReply(LispNotificationHelper.convertMapReply(reply));
95
96             if (notificationPublishService != null) {
97                 notificationPublishService.putNotification(replyMappingBuilder.build());
98                 LOG.trace("MapReply was published!");
99             } else {
100                 LOG.warn("Notification Provider is null!");
101             }
102         } catch (RuntimeException re) {
103             throw new LispMalformedPacketException(
104                     "Couldn't deserialize Map-Reply (len=" + buffer.capacity() + ")", re);
105         } catch (InterruptedException e) {
106             LOG.warn("Notification publication interrupted!");
107         }
108     }
109
110     @Override
111     protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
112         if (LOG.isTraceEnabled()) {
113             LOG.trace("Received UDP packet from {}:{} with content:\n{}", msg.sender().getHostString(),
114                     msg.sender().getPort(), ByteBufUtil.prettyHexDump(msg.content()));
115         }
116         handlePacket(msg);
117     }
118
119     @Override
120     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
121         ctx.flush();
122     }
123
124     @Override
125     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
126         LOG.error("Error on channel: " + cause, cause);
127     }
128 }