[ONOS-5267] Initial implementation of MapResolver

Change-Id: I1438b0cc71b8fcb88064830d890ffc38ff9abd42
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelHandler.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelHandler.java
index 6c723a6..d1ad800 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelHandler.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelHandler.java
@@ -24,7 +24,6 @@
 import org.onosproject.lisp.msg.protocols.LispMapNotify;
 import org.onosproject.lisp.msg.protocols.LispMapRegister;
 import org.onosproject.lisp.msg.protocols.LispMapRequest;
-import org.onosproject.lisp.msg.protocols.LispMapReply;
 import org.onosproject.lisp.msg.protocols.LispMessage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,7 +41,16 @@
 
         // first we need to check whether this is an ECM
         if (msg instanceof LispEncapsulatedControl) {
-            msg = extractMapRequest((LispEncapsulatedControl) msg);
+            LispMessage innerMsg = extractLispMessage((LispEncapsulatedControl) msg);
+            if (innerMsg instanceof LispMapRequest) {
+                LispMapResolver mapResolver = new LispMapResolver();
+                LispMessage lispMessage = mapResolver.processMapRequest((LispEncapsulatedControl) msg);
+
+                // try to remove the received map-request message from buffer
+                ReferenceCountUtil.release(msg);
+
+                ctx.writeAndFlush(lispMessage);
+            }
         }
 
         if (msg instanceof LispMapRegister) {
@@ -54,14 +62,6 @@
 
             ctx.writeAndFlush(mapNotify);
         }
-
-        if (msg instanceof LispMapRequest) {
-            LispMapResolver mapResolver = new LispMapResolver();
-            LispMapReply mapReply =
-                    (LispMapReply) mapResolver.processMapRequest((LispMapRequest) msg);
-
-            // TODO: serialize mapReply message and write to channel
-        }
     }
 
     @Override
@@ -96,7 +96,9 @@
      * @param ecm Encapsulated Control Message
      * @return extracted LISP message
      */
-    private LispMessage extractMapRequest(LispEncapsulatedControl ecm) {
-        return ecm.getControlMessage();
+    private LispMessage extractLispMessage(LispEncapsulatedControl ecm) {
+        LispMessage message = ecm.getControlMessage();
+        message.configSender(ecm.getSender());
+        return message;
     }
 }
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispEidRlocMap.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispEidRlocMap.java
index d85ff97..0593366 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispEidRlocMap.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispEidRlocMap.java
@@ -15,11 +15,14 @@
  */
 package org.onosproject.lisp.ctl;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.onosproject.lisp.msg.protocols.LispEidRecord;
 import org.onosproject.lisp.msg.protocols.LispMapRecord;
 import org.onosproject.lisp.msg.types.LispAfiAddress;
 
+import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentMap;
 
@@ -69,6 +72,23 @@
     }
 
     /**
+     * Obtains a collection of EID-RLOC mapping records with given EID records.
+     *
+     * @param eids endpoint identifier records
+     * @return a collection of EID-RLOC mapping records
+     */
+    public List<LispMapRecord> getMapRecordByEidRecords(List<LispEidRecord> eids) {
+        List<LispMapRecord> mapRecords = Lists.newArrayList();
+        eids.forEach(eidRecord -> {
+            LispMapRecord mapRecord = getMapRecordByEidRecord(eidRecord);
+            if (mapRecord != null) {
+                mapRecords.add(mapRecord);
+            }
+        });
+        return ImmutableList.copyOf(mapRecords);
+    }
+
+    /**
      * Obtains an EID-RLOC mapping record with given EID address.
      *
      * @param address endpoint identifier address
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapResolver.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapResolver.java
index 9f6ab35..5661681 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapResolver.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapResolver.java
@@ -15,8 +15,19 @@
  */
 package org.onosproject.lisp.ctl;
 
+import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl;
+import org.onosproject.lisp.msg.protocols.LispMapRecord;
 import org.onosproject.lisp.msg.protocols.LispMapReply;
+import org.onosproject.lisp.msg.protocols.LispMapRequest;
+import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
+
 import org.onosproject.lisp.msg.protocols.LispMessage;
+import org.onosproject.lisp.msg.types.LispIpAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetSocketAddress;
+import java.util.List;
 
 /**
  * LISP map resolver class.
@@ -24,8 +35,54 @@
  */
 public class LispMapResolver {
 
-    public LispMapReply processMapRequest(LispMessage message) {
-        // TODO: need to implement map-request message processing logic
-        return null;
+    private static final Logger log = LoggerFactory.getLogger(LispMapResolver.class);
+
+    private LispEidRlocMap eidRlocMap;
+
+    LispMapResolver() {
+        eidRlocMap = LispEidRlocMap.getInstance();
+    }
+
+    /**
+     * Handles encapsulated control message and replies with map-reply message.
+     *
+     * @param message encapsulated control message
+     * @return map-reply message
+     */
+    public LispMessage processMapRequest(LispMessage message) {
+
+        LispEncapsulatedControl ecm = (LispEncapsulatedControl) message;
+        LispMapRequest request = (LispMapRequest) ecm.getControlMessage();
+
+        // TODO: for now we always generate map-notify message and send to ITR
+        // no matter proxy bit is set or not
+
+        // build map-reply message
+        LispMapReply.ReplyBuilder replyBuilder = new DefaultReplyBuilder();
+        replyBuilder.withNonce(request.getNonce());
+        replyBuilder.withIsEtr(false);
+        replyBuilder.withIsSecurity(false);
+        replyBuilder.withIsProbe(request.isProbe());
+
+        List<LispMapRecord> mapRecords = eidRlocMap.getMapRecordByEidRecords(request.getEids());
+
+        if (mapRecords.size() == 0) {
+            log.warn("Map information is not found.");
+        } else {
+            replyBuilder.withMapRecords(mapRecords);
+        }
+
+        LispMapReply reply = replyBuilder.build();
+
+        if (request.getItrRlocs() != null && request.getItrRlocs().size() > 0) {
+            LispIpAddress itr = (LispIpAddress) request.getItrRlocs().get(0);
+            InetSocketAddress address = new InetSocketAddress(itr.getAddress().toInetAddress(),
+                    ecm.innerUdp().getSourcePort());
+            reply.configSender(address);
+        } else {
+            log.warn("No ITR RLOC is found, cannot respond back to ITR.");
+        }
+
+        return reply;
     }
 }
diff --git a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
index e4ea7db..d933783 100644
--- a/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
+++ b/protocols/lisp/msg/src/main/java/org/onosproject/lisp/msg/protocols/LispEidRecord.java
@@ -16,11 +16,13 @@
 package org.onosproject.lisp.msg.protocols;
 
 import io.netty.buffer.ByteBuf;
+import com.google.common.base.Objects;
 import org.onosproject.lisp.msg.exceptions.LispParseError;
 import org.onosproject.lisp.msg.exceptions.LispReaderException;
 import org.onosproject.lisp.msg.exceptions.LispWriterException;
 import org.onosproject.lisp.msg.types.LispAfiAddress;
 
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
 
@@ -64,6 +66,32 @@
         return prefix;
     }
 
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("maskLength", maskLength)
+                .add("prefix", prefix).toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        LispEidRecord that = (LispEidRecord) o;
+        return Objects.equal(maskLength, that.maskLength) &&
+                Objects.equal(prefix, that.prefix);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(maskLength, prefix);
+    }
+
     /**
      * A LISP message reader for EidRecord portion.
      */