Add LISP channel pipeline along with server bootstrap

Change-Id: I9ca12bbab5c4dad474bd6d7fa70e96a179bf4e50
diff --git a/protocols/lisp/ctl/BUCK b/protocols/lisp/ctl/BUCK
index 4de24ac..c6b463a 100644
--- a/protocols/lisp/ctl/BUCK
+++ b/protocols/lisp/ctl/BUCK
@@ -4,7 +4,8 @@
     '//protocols/lisp/msg:onos-protocols-lisp-msg',
     '//lib:netty-buffer',
     '//lib:netty-codec',
-    '//lib:netty-transport'
+    '//lib:netty-transport',
+    '//lib:netty-handler'
 ]
 
 TEST_DEPS = [
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
new file mode 100644
index 0000000..1cd8d0b
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelHandler.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import org.onosproject.lisp.msg.protocols.LispMapNotify;
+import org.onosproject.lisp.msg.protocols.LispMapRegister;
+import org.onosproject.lisp.msg.protocols.LispMapReply;
+import org.onosproject.lisp.msg.protocols.LispMapRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Channel handler deals with the xTR connection and dispatches xTR messages
+ * to the appropriate locations.
+ */
+public class LispChannelHandler extends ChannelInboundHandlerAdapter {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+
+        if (msg instanceof LispMapRegister) {
+            LispMapServer mapServer = new LispMapServer();
+            LispMapNotify mapNotify = (LispMapNotify) mapServer.process((LispMapRegister) msg);
+
+            // TODO: deserialize mapNotify message and write to channel
+        }
+
+        if (msg instanceof LispMapRequest) {
+            LispMapResolver mapResolver = new LispMapResolver();
+            LispMapReply mapReply = (LispMapReply) mapResolver.process((LispMapRequest) msg);
+
+            // TODO: deserialize mapReply message and write to channel
+        }
+    }
+
+    @Override
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
+            throws Exception {
+
+        if (evt instanceof IdleStateEvent) {
+            IdleStateEvent event = (IdleStateEvent) evt;
+            if (event.state() == IdleState.READER_IDLE) {
+                log.info("READER_IDLE read timeout");
+                ctx.disconnect();
+            } else if (event.state() == IdleState.WRITER_IDLE) {
+                log.info("WRITER_IDLE write timeout");
+                ctx.disconnect();
+            } else if (event.state() == IdleState.ALL_IDLE) {
+                log.info("ALL_IDLE total timeout");
+                ctx.disconnect();
+            }
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
+            throws Exception {
+        log.warn(cause.getMessage());
+        ctx.close();
+    }
+}
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelInitializer.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelInitializer.java
new file mode 100644
index 0000000..e0b7ab6
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispChannelInitializer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Creates a ChannelInitializer for a server-side LISP channel.
+ */
+public final class LispChannelInitializer extends ChannelInitializer<Channel> {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private IdleStateHandler idleHandler;
+    private ReadTimeoutHandler readTimeoutHandler;
+
+    private static final int READER_IDLE_TIME_SECOND = 20;
+    private static final int WRITER_IDLE_TIME_SECOND = 25;
+    private static final int ALL_IDLE_TIME_SECOND = 0;
+    private static final int READ_TIMEOUT_SECOND = 30;
+
+    @Override
+    protected void initChannel(Channel channel) throws Exception {
+        ChannelPipeline pipeline = channel.pipeline();
+
+        LispChannelHandler handler = new LispChannelHandler();
+
+        idleHandler = new IdleStateHandler(READER_IDLE_TIME_SECOND,
+                WRITER_IDLE_TIME_SECOND, ALL_IDLE_TIME_SECOND);
+        readTimeoutHandler = new ReadTimeoutHandler(READ_TIMEOUT_SECOND);
+
+        pipeline.addLast("lispmessagedecoder", new LispMessageDecoder());
+        pipeline.addLast("lispmessageencoder", new LispMessageEncoder());
+        pipeline.addLast("idle", idleHandler);
+        pipeline.addLast("readTimeout", readTimeoutHandler);
+        pipeline.addLast("handler", handler);
+    }
+}
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispController.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispController.java
new file mode 100644
index 0000000..01c87dbc
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispController.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+
+/**
+ * The main LISP controller class.
+ * Bootstraps LISP netty channel, handles all setup and network listeners.
+ */
+public class LispController {
+
+    protected static final Logger log = LoggerFactory.getLogger(LispController.class);
+
+    private static final int LISP_DATA_PORT = 4341;
+    private static final int LISP_CONTROL_PORT = 4342;
+
+    // Configuration options
+    protected List<Integer> lispPorts = ImmutableList.of(LISP_DATA_PORT, LISP_CONTROL_PORT);
+
+    protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
+
+    private EventLoopGroup bossGroup;
+    private EventLoopGroup workerGroup;
+
+    /**
+     * Stitches all channel handlers into server bootstrap.
+     */
+    public void run() {
+
+        try {
+            final ServerBootstrap bootstrap = createServerBootstrap();
+
+            configBootstrapOptions(bootstrap);
+
+            List<ChannelFuture> channelFutures = Lists.newArrayList();
+
+            lispPorts.forEach(p -> {
+                InetSocketAddress sa = new InetSocketAddress(p);
+                channelFutures.add(bootstrap.bind(sa));
+                log.info("Listening for LISP router connections on {}", sa);
+            });
+
+            for (ChannelFuture f : channelFutures) {
+                f.sync();
+            }
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Initializes server bootstrap with given LISP channel initializer.
+     *
+     * @return initialized server bootstrap
+     */
+    private ServerBootstrap createServerBootstrap() {
+        ServerBootstrap bootstrap = new ServerBootstrap();
+        bossGroup = new NioEventLoopGroup();
+        workerGroup = new NioEventLoopGroup();
+        bootstrap.group(bossGroup, workerGroup)
+                .channel(NioServerSocketChannel.class)
+                .childHandler(new LispChannelInitializer());
+
+        return bootstrap;
+    }
+
+    /**
+     * Configures bootstrap options to tune the communication performance.
+     *
+     * @param bootstrap LISP server bootstrap
+     */
+    private void configBootstrapOptions(ServerBootstrap bootstrap) {
+        bootstrap.option(ChannelOption.SO_REUSEADDR, true);
+        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
+        bootstrap.option(ChannelOption.SO_SNDBUF, SEND_BUFFER_SIZE);
+    }
+
+    /**
+     * Closes all open channels.
+     *
+     * @param channelFutures a collection of channel futures
+     */
+    private void closeChannels(List<ChannelFuture> channelFutures) {
+        try {
+            for (ChannelFuture f : channelFutures) {
+                f.channel().closeFuture().sync();
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Launches LISP controller to listen control channel.
+     */
+    public void start() {
+        log.info("Starting LISP control I/O");
+
+        this.run();
+    }
+
+    /**
+     * Terminates LISP controller and lease all occupied resources.
+     */
+    public void stop() {
+        log.info("Stopping LISP control I/O");
+
+        try {
+            // try to shutdown all open event groups
+            bossGroup.shutdownGracefully().sync();
+            workerGroup.shutdownGracefully().sync();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+}
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
new file mode 100644
index 0000000..01b654a
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapResolver.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import org.onosproject.lisp.msg.protocols.LispMessage;
+
+/**
+ * LISP map resolver class.
+ * Handles map-request message and acknowledges with map-reply message.
+ */
+public class LispMapResolver implements LispMapSystem {
+    @Override
+    public LispMessage process(LispMessage message) {
+        // TODO: need to implement map-register message processing logic
+        return null;
+    }
+}
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapServer.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapServer.java
new file mode 100644
index 0000000..145a4bb
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapServer.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import org.onosproject.lisp.msg.protocols.LispMessage;
+
+/**
+ * LISP map server class.
+ * Handles map-register message and acknowledges with map-notify message.
+ */
+public class LispMapServer implements LispMapSystem {
+    @Override
+    public LispMessage process(LispMessage message) {
+        // TODO: need to implement map-request message processing logic
+        return null;
+    }
+}
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapSystem.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapSystem.java
new file mode 100644
index 0000000..f321a6d
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/LispMapSystem.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.lisp.ctl;
+
+import org.onosproject.lisp.msg.protocols.LispMessage;
+
+/**
+ * LISP map system interface.
+ */
+public interface LispMapSystem {
+
+    /**
+     * Processes incoming LISP message, and results in corresponding LISP message.
+     *
+     * @param message input LISP message
+     * @return output LISP message
+     */
+    LispMessage process(LispMessage message);
+}