From 9440f9d734e32a96e7c242c382635ac3c1b6c27d Mon Sep 17 00:00:00 2001
From: kearney <chris.kearney@urbanairship.com>
Date: Mon, 18 Aug 2014 17:05:06 -0700
Subject: [PATCH] checking in some codes

---
 .gitignore                                    |   8 +
 pom.xml                                       |  29 ++++
 .../com/comandante/GameAuthenticator.java     |   9 ++
 src/main/java/com/comandante/Main.java        |  23 +++
 src/main/java/com/comandante/Movement.java    |  26 ++++
 src/main/java/com/comandante/Player.java      |  31 ++++
 src/main/java/com/comandante/Room.java        |  63 ++++++++
 src/main/java/com/comandante/RoomManager.java | 107 +++++++++++++
 .../comandante/SimpleGameAuthenticator.java   |  39 +++++
 .../comandante/telnetserver/TelnetServer.java |  28 ++++
 .../telnetserver/TelnetServerAuthState.java   |  50 +++++++
 .../telnetserver/TelnetServerHandler.java     | 141 ++++++++++++++++++
 .../TelnetServerPipelineFactory.java          |  30 ++++
 13 files changed, 584 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 pom.xml
 create mode 100644 src/main/java/com/comandante/GameAuthenticator.java
 create mode 100644 src/main/java/com/comandante/Main.java
 create mode 100644 src/main/java/com/comandante/Movement.java
 create mode 100644 src/main/java/com/comandante/Player.java
 create mode 100644 src/main/java/com/comandante/Room.java
 create mode 100644 src/main/java/com/comandante/RoomManager.java
 create mode 100644 src/main/java/com/comandante/SimpleGameAuthenticator.java
 create mode 100644 src/main/java/com/comandante/telnetserver/TelnetServer.java
 create mode 100644 src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java
 create mode 100644 src/main/java/com/comandante/telnetserver/TelnetServerHandler.java
 create mode 100644 src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..90e7fb64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+target
+*.swp
+*.iml
+*.ipr
+*.iws
+*.pyc
+*.bak
+.idea/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..4d1a6be7
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>com.comandante</groupId>
+  <artifactId>creeper</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <dependencies>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>16.0.1</version>
+    </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty</artifactId>
+      <version>3.6.2.Final</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+      <version>20041127.091804</version>
+    </dependency>
+  </dependencies>
+
+
+</project>
diff --git a/src/main/java/com/comandante/GameAuthenticator.java b/src/main/java/com/comandante/GameAuthenticator.java
new file mode 100644
index 00000000..e55ea168
--- /dev/null
+++ b/src/main/java/com/comandante/GameAuthenticator.java
@@ -0,0 +1,9 @@
+package com.comandante;
+
+import org.jboss.netty.channel.Channel;
+
+public interface GameAuthenticator {
+
+    public boolean authenticatePlayer(String userName, String passWord, Channel channel);
+
+}
diff --git a/src/main/java/com/comandante/Main.java b/src/main/java/com/comandante/Main.java
new file mode 100644
index 00000000..50677f1b
--- /dev/null
+++ b/src/main/java/com/comandante/Main.java
@@ -0,0 +1,23 @@
+package com.comandante;
+
+import com.comandante.telnetserver.TelnetServer;
+import com.google.common.base.Optional;
+
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+        Room lobby = new Room(1, Optional.of(2), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), "This is the lobby.");
+        Room hallway = new Room(2, Optional.of(3), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(1), "This is the hallway.");
+        Room bedroom = new Room(3, Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(2), "This is the bedroom");
+
+        RoomManager roomManager = new RoomManager();
+        roomManager.startUp();
+
+        roomManager.addRoom(lobby);
+        roomManager.addRoom(hallway);
+        roomManager.addRoom(bedroom);
+
+        TelnetServer telnetServer = new TelnetServer(8080);
+        telnetServer.run(roomManager);
+    }
+}
diff --git a/src/main/java/com/comandante/Movement.java b/src/main/java/com/comandante/Movement.java
new file mode 100644
index 00000000..4f8e01cd
--- /dev/null
+++ b/src/main/java/com/comandante/Movement.java
@@ -0,0 +1,26 @@
+package com.comandante;
+
+public class Movement {
+
+    private final Player player;
+    private final Integer sourceRoomId;
+    private final Integer destinationRoomId;
+
+    public Movement(Player player, Integer sourceRoomId, Integer destinationRoomId) {
+        this.player = player;
+        this.sourceRoomId = sourceRoomId;
+        this.destinationRoomId = destinationRoomId;
+    }
+
+    public Integer getSourceRoomId() {
+        return sourceRoomId;
+    }
+
+    public Integer getDestinationRoomId() {
+        return destinationRoomId;
+    }
+
+    public Player getPlayer() {
+        return player;
+    }
+}
diff --git a/src/main/java/com/comandante/Player.java b/src/main/java/com/comandante/Player.java
new file mode 100644
index 00000000..ae9b9164
--- /dev/null
+++ b/src/main/java/com/comandante/Player.java
@@ -0,0 +1,31 @@
+package com.comandante;
+
+
+import org.apache.commons.codec.binary.Base64;
+import org.jboss.netty.channel.Channel;
+
+public class Player {
+
+    private String playerName;
+    private Channel channel;
+
+    public Player(String playerName) {
+        this.playerName = playerName;
+    }
+
+    public String getPlayerName() {
+        return playerName;
+    }
+
+    public String getPlayerId() {
+        return new String(Base64.encodeBase64(playerName.getBytes()));
+    }
+
+    public Channel getChannel() {
+        return channel;
+    }
+
+    public void setChannel(Channel channel) {
+        this.channel = channel;
+    }
+}
diff --git a/src/main/java/com/comandante/Room.java b/src/main/java/com/comandante/Room.java
new file mode 100644
index 00000000..2bbbf5a2
--- /dev/null
+++ b/src/main/java/com/comandante/Room.java
@@ -0,0 +1,63 @@
+package com.comandante;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.Set;
+
+public class Room {
+
+    public Integer roomId;
+    public Optional<Integer> northId;
+    public Optional<Integer> westId;
+    public Optional<Integer> eastId;
+    public Optional<Integer> southId;
+    public String roomDescription;
+    private Set<Player> presentPlayers = Sets.<Player>newConcurrentHashSet();
+
+    public Room(Integer roomId, Optional<Integer> northId, Optional<Integer> westId, Optional<Integer> eastId, Optional<Integer> southId, String roomDescription) {
+        this.roomId = roomId;
+        this.northId = northId;
+        this.westId = westId;
+        this.eastId = eastId;
+        this.southId = southId;
+        this.roomDescription = roomDescription;
+    }
+
+    public java.util.Set<Player> getPresentPlayers()  {
+        return ImmutableSet.<Player>builder().addAll(presentPlayers.iterator()).build();
+    }
+
+    public void addPresentPlayer(Player player) {
+        presentPlayers.add(player);
+    }
+
+    public void removePresentPlayer(Player player) {
+        presentPlayers.remove(player);
+    }
+
+    public String getRoomDescription() {
+        return roomDescription;
+    }
+
+    public Integer getRoomId() {
+        return roomId;
+    }
+
+    public Optional<Integer> getNorthId() {
+        return northId;
+    }
+
+    public Optional<Integer> getWestId() {
+        return westId;
+    }
+
+    public Optional<Integer> getEastId() {
+        return eastId;
+    }
+
+    public Optional<Integer> getSouthId() {
+        return southId;
+    }
+}
diff --git a/src/main/java/com/comandante/RoomManager.java b/src/main/java/com/comandante/RoomManager.java
new file mode 100644
index 00000000..85739a53
--- /dev/null
+++ b/src/main/java/com/comandante/RoomManager.java
@@ -0,0 +1,107 @@
+package com.comandante;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Interners;
+import com.google.common.util.concurrent.AbstractExecutionThreadService;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class RoomManager extends AbstractExecutionThreadService {
+
+    ArrayBlockingQueue<Movement> movements = new ArrayBlockingQueue<Movement>(10000);
+
+    private ConcurrentHashMap<Integer, Room> rooms = new ConcurrentHashMap<Integer, Room>();
+    private ConcurrentHashMap<String, Player> players = new ConcurrentHashMap<String, Player>();
+
+    private AtomicBoolean isRunning = new AtomicBoolean(false);
+
+    public void addRoom(Room room) {
+        rooms.put(room.roomId, room);
+    }
+
+    public Player addPlayer(Player player) {
+        return players.putIfAbsent(player.getPlayerId(), player);
+    }
+
+    public void removePlayer(Player player) {
+        if (getPlayer(player).getChannel() != null) {
+            getPlayer(player).getChannel().disconnect();
+        }
+        players.remove(player);
+        Iterator<Integer> iterator = rooms.keySet().iterator();
+        while (iterator.hasNext()) {
+            Integer next = iterator.next();
+            rooms.get(next).removePresentPlayer(player);
+        }
+    }
+
+    public boolean doesPlayerExist(Player player) {
+        for (Map.Entry<String, Player> stringPlayerEntry : players.entrySet()) {
+            Map.Entry pairs = (Map.Entry) stringPlayerEntry;
+            Player playerRetrieved = (Player) pairs.getValue();
+            if (playerRetrieved.getPlayerId().equals(player.getPlayerId())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void updatePlayerMovement(Movement movement) throws InterruptedException {
+        movements.put(movement);
+    }
+
+    public void _processMovment(Movement movement) {
+        synchronized (Interners.newStrongInterner()) {
+            rooms.get(movement.getSourceRoomId()).removePresentPlayer(movement.getPlayer());
+            rooms.get(movement.getDestinationRoomId()).addPresentPlayer(movement.getPlayer());
+        }
+    }
+
+    public void addPlayerToLobby(Player player) {
+        rooms.get(1).addPresentPlayer(player);
+    }
+
+    public Player getPlayer(Player player) {
+        return players.get(player.getPlayerId());
+    }
+
+    public Optional<Room> getPlayerCurrentRoom(Player player) {
+        Iterator<Map.Entry<Integer, Room>> iterator = rooms.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<Integer, Room> next = iterator.next();
+            Set<Player> presentPlayers = next.getValue().getPresentPlayers();
+            Iterator<Player> iterator1 = presentPlayers.iterator();
+            while (iterator1.hasNext()) {
+                Player next1 = iterator1.next();
+                if (next1.getPlayerId().equals(player.getPlayerId())) {
+                    return Optional.of(next.getValue());
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    @Override
+    protected void startUp() throws Exception {
+        isRunning.set(true);
+    }
+
+    @Override
+    protected void shutDown() throws Exception {
+        isRunning.set(false);
+
+    }
+
+    @Override
+    protected void run() throws Exception {
+        while (isRunning.get()) {
+            Movement take = movements.take();
+            _processMovment(take);
+        }
+    }
+}
diff --git a/src/main/java/com/comandante/SimpleGameAuthenticator.java b/src/main/java/com/comandante/SimpleGameAuthenticator.java
new file mode 100644
index 00000000..ae4dc969
--- /dev/null
+++ b/src/main/java/com/comandante/SimpleGameAuthenticator.java
@@ -0,0 +1,39 @@
+package com.comandante;
+
+import org.jboss.netty.channel.Channel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SimpleGameAuthenticator implements GameAuthenticator {
+
+    RoomManager roomManager;
+
+    public SimpleGameAuthenticator(RoomManager roomManager) {
+        this.roomManager = roomManager;
+    }
+
+    private static final Map<String, String> userMap;
+    static {
+        userMap = new HashMap<String, String>();
+        userMap.put("chris", "poop");
+    }
+
+    @Override
+    public boolean authenticatePlayer(String userName, String passWord, Channel channel) {
+        String userPassword = userMap.get(userName);
+        if (userPassword == null) {
+            return false;
+        }
+        if (!userPassword.equals(passWord)) {
+            return false;
+        }
+        Player player = new Player(userName);
+        if (roomManager.doesPlayerExist(player)) {
+            roomManager.removePlayer(player);
+        }
+        player.setChannel(channel);
+        roomManager.addPlayer(player);
+        return true;
+    }
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServer.java b/src/main/java/com/comandante/telnetserver/TelnetServer.java
new file mode 100644
index 00000000..2c3e15de
--- /dev/null
+++ b/src/main/java/com/comandante/telnetserver/TelnetServer.java
@@ -0,0 +1,28 @@
+package com.comandante.telnetserver;
+
+
+import com.comandante.RoomManager;
+import com.comandante.SimpleGameAuthenticator;
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executors;
+
+public class TelnetServer {
+
+    private final int port;
+
+    public TelnetServer(int port) {
+        this.port = port;
+    }
+
+    public void run(RoomManager roomManager) throws Exception {
+        ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
+
+        TelnetServerHandler handler = new TelnetServerHandler(new SimpleGameAuthenticator(roomManager), roomManager);
+        bootstrap.setPipelineFactory(new TelnetServerPipelineFactory(handler));
+        bootstrap.bind(new InetSocketAddress(8080));
+
+    }
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java b/src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java
new file mode 100644
index 00000000..f84f891a
--- /dev/null
+++ b/src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java
@@ -0,0 +1,50 @@
+package com.comandante.telnetserver;
+
+import com.google.common.base.Optional;
+
+public class TelnetServerAuthState {
+
+    private Optional<String> username = Optional.absent();
+    private Optional<String> password = Optional.absent();
+    private boolean isAuthed = false;
+    State state;
+
+    enum State {
+        promptedForPassword,
+        promptedForUsername,
+        failed,
+        authed
+    }
+
+    public Optional<String> getUsername() {
+        return username;
+    }
+
+    public void setUsername(Optional<String> username) {
+        this.username = username;
+    }
+
+    public Optional<String> getPassword() {
+        return password;
+    }
+
+    public void setPassword(Optional<String> password) {
+        this.password = password;
+    }
+
+    public boolean isAuthed() {
+        return isAuthed;
+    }
+
+    public void setAuthed(boolean isAuthed) {
+        this.isAuthed = isAuthed;
+    }
+
+    public void setState(State state) {
+        this.state = state;
+    }
+
+    public State getState() {
+        return state;
+    }
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java b/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java
new file mode 100644
index 00000000..8719793f
--- /dev/null
+++ b/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java
@@ -0,0 +1,141 @@
+package com.comandante.telnetserver;
+
+import com.comandante.GameAuthenticator;
+import com.comandante.Movement;
+import com.comandante.Player;
+import com.comandante.Room;
+import com.comandante.RoomManager;
+import com.google.common.base.Optional;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelEvent;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+
+public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
+
+    GameAuthenticator gameAuthenticator;
+    RoomManager roomManager;
+
+    public TelnetServerHandler(GameAuthenticator gameAuthenticator, RoomManager roomManager) {
+        this.gameAuthenticator = gameAuthenticator;
+        this.roomManager = roomManager;
+    }
+
+    @Override
+    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
+        if (e instanceof ChannelStateEvent) {
+            System.err.println(e);
+        }
+        super.handleUpstream(ctx, e);
+    }
+
+    @Override
+    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+        // Send greeting for a new connection.
+        e.getChannel().write("username: ");
+        TelnetServerAuthState telnetServerAuthState = new TelnetServerAuthState();
+        telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForUsername);
+        ctx.setAttachment(telnetServerAuthState);
+    }
+
+    @Override
+    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
+        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
+        if(!telnetServerAuthState.isAuthed()) {
+            doAuthentication(ctx, e);
+            if (telnetServerAuthState.isAuthed()) {
+                currentRoomLogic(ctx, e);
+            }
+        } else {
+            processCommand(ctx, e);
+            currentRoomLogic(ctx, e);
+        }
+
+    }
+
+    private void processCommand(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
+        String command = (String) e.getMessage();
+        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
+        Player player = roomManager.getPlayer(new Player(telnetServerAuthState.getUsername().get()));
+        Room room = roomManager.getPlayerCurrentRoom(player).get();
+        if (command.equals("n")) {
+            if (room.getNorthId().isPresent()) {
+                Movement movement = new Movement(player, room.getRoomId(), room.getNorthId().get());
+                roomManager._processMovment(movement);
+            } else {
+                e.getChannel().write("There's no northern exit.\r\n");
+            }
+        }
+        if (command.equals("s")) {
+            if (room.getSouthId().isPresent()) {
+                Movement movement = new Movement(player, room.getRoomId(), room.getSouthId().get());
+                roomManager._processMovment(movement);
+            } else {
+                e.getChannel().write("There's no southern exit.\r\n");
+            }
+        }
+    }
+
+    private void printExits(Room room, Channel channel) {
+        channel.write("Exits: ");
+        if (room.getEastId().isPresent()) {
+            channel.write("e(ast) ");
+        }
+        if (room.getNorthId().isPresent()) {
+            channel.write("n(orth) ");
+        }
+        if (room.getSouthId().isPresent()) {
+            channel.write("s(outh). ");
+        }
+        if (room.getWestId().isPresent()) {
+            channel.write("w(est). ");
+        }
+        channel.write("\r\n");
+    }
+
+    private void currentRoomLogic(ChannelHandlerContext ctx, MessageEvent e) {
+        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
+        Player player = new Player(telnetServerAuthState.getUsername().get());
+        Optional<Room> playerCurrentRoom = roomManager.getPlayerCurrentRoom(player);
+        if (!playerCurrentRoom.isPresent()) {
+            roomManager.addPlayerToLobby(roomManager.getPlayer(player));
+            playerCurrentRoom = roomManager.getPlayerCurrentRoom(player);
+        }
+        e.getChannel().write(playerCurrentRoom.get().getRoomDescription() + "\r\n");
+        printExits(playerCurrentRoom.get(), e.getChannel());
+    }
+
+    private void doAuthentication(ChannelHandlerContext ctx, MessageEvent e) {
+        String message = (String) e.getMessage();
+        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
+        if (telnetServerAuthState.getState().equals(TelnetServerAuthState.State.promptedForUsername)) {
+            telnetServerAuthState.setUsername(Optional.of(message));
+            telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForPassword);
+            e.getChannel().write("password: ");
+            return;
+        }
+        if (telnetServerAuthState.getState().equals(TelnetServerAuthState.State.promptedForPassword)) {
+            telnetServerAuthState.setPassword(Optional.of(message));
+        }
+        boolean b = gameAuthenticator.authenticatePlayer(telnetServerAuthState.getUsername().get(), telnetServerAuthState.getPassword().get(), e.getChannel());
+        if (!b) {
+            e.getChannel().write("Auth failed.\r\n");
+            e.getChannel().write("username: ");
+            telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForUsername);
+        } else {
+            telnetServerAuthState.setAuthed(true);
+            telnetServerAuthState.setState(TelnetServerAuthState.State.authed);
+            e.getChannel().write("Welcome to bertha.\r\n");
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
+        e.getCause().printStackTrace();
+        e.getChannel().close();
+    }
+
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java b/src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java
new file mode 100644
index 00000000..5f7b5739
--- /dev/null
+++ b/src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java
@@ -0,0 +1,30 @@
+package com.comandante.telnetserver;
+
+
+import org.jboss.netty.channel.ChannelHandler;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.DefaultChannelPipeline;
+import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
+import org.jboss.netty.handler.codec.frame.Delimiters;
+import org.jboss.netty.handler.codec.string.StringDecoder;
+import org.jboss.netty.handler.codec.string.StringEncoder;
+
+public class TelnetServerPipelineFactory implements ChannelPipelineFactory {
+
+    private final ChannelHandler handler;
+
+    public TelnetServerPipelineFactory(ChannelHandler handler) {
+        this.handler = handler;
+    }
+
+    public ChannelPipeline getPipeline() {
+        ChannelPipeline pipeline = new DefaultChannelPipeline();
+        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
+        pipeline.addLast("decoder", new StringDecoder());
+        pipeline.addLast("encoder", new StringEncoder());
+        pipeline.addLast("handler", handler);
+
+        return pipeline;
+    }
+}
-- 
GitLab