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