Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.lang.Object;
- import java.lang.Character;
- import java.lang.String;
- import java.io.*;
- import java.util.*;
- import java.net.*;
- import java.nio.channels.SelectionKey;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- import java.nio.channels.spi.SelectorProvider;
- import java.nio.channels.Selector;
- import java.nio.ByteBuffer;
- import java.lang.Byte;
- import java.lang.Thread;
- import java.util.Date;
- import java.text.SimpleDateFormat;
- /**
- * @author Sam Jones
- * @version 2010.11.06
- *
- * This will hold: String characterName, boolean loggedIn, SocketChannel mySocket
- * String[] recentCommands[10], ByteBuffer newLine
- * And whatever else is necessary
- *
- * It will constantly loop, grabbing a byte at a time in to newLine until \n\r (13, 10)
- * is received, where it will execute that command and then push it onto recentCommands[0]
- *
- * If special characters like, Cursor UP, Cursor DOWN, HOME, END, etc are sent. It will send
- * (255) plus whatever telnet command is necessary at that point.
- *
- */
- public class inputBufferHandler {
- private dataPerSocket[] myData = new dataPerSocket[1]; // Increase as necessary
- public inputBufferHandler() throws IOException {
- myData[0] = new dataPerSocket();
- }
- public String getCharacterName(int index) {
- if (myData[index].loggedIn) return myData[index].characterName;
- return "";
- }
- public boolean isLoggedIn(int index) {
- return myData[index].loggedIn;
- }
- public boolean isConnected(int index) {
- if (myData[index].mySocket != null) return true;
- return false;
- }
- public int getTotal() {
- return myData.length;
- }
- public synchronized void addClient(SelectionKey key) throws IOException {
- // Create a reference to our listen socket so we can accept the
- // connection to a new selector (this objects selector)
- ServerSocketChannel dummyServerReference = (ServerSocketChannel) key.channel();
- SocketChannel newClient = dummyServerReference.accept();
- newClient.configureBlocking(false);
- // Makes sure the first space gets filled after initialisation
- if (isConnected(0)) {
- System.out.println("Extending myData to add new client.");
- dataPerSocket[] newData = new dataPerSocket[myData.length + 1];
- System.arraycopy(myData, 0, newData, 0, myData.length);
- newData[myData.length] = new dataPerSocket();
- newData[myData.length].beginLife(newClient);
- myData = newData;
- myData[myData.length - 1].initLogin(newClient);
- } else {
- System.out.println("Filling first client slot.");
- myData[0] = new dataPerSocket();
- myData[0].beginLife(newClient);
- myData[0].initLogin(newClient);
- }
- }
- public synchronized void delClient(SocketChannel oldClient) throws IOException {
- // TODO - this parameter is an example. might pass other stuff
- }
- // Write functions easily accessible from outside this class
- public void sendLine(SocketChannel outputSock, String outputLine) throws IOException {
- sendMessage(outputSock, outputLine + "\n\r");
- }
- public void sendMessage(SocketChannel outputSock, String outputLine) throws IOException {
- outputSock.write(StringtoBB(outputLine));
- }
- /**
- * Converts ByteBuffer to a String and returns it
- * Might be redundant after new implementations
- */
- public String BBtoString(ByteBuffer buf) {
- int myCap = buf.capacity() - buf.remaining();
- byte[] bytearr = new byte[myCap];
- buf.rewind();
- for(int i = 0;i < myCap;i++)
- bytearr[i] = buf.get(i);
- String returnMe = new String(bytearr);
- return returnMe;
- }
- /**
- * Converts String to ByteBuffer and returns it
- *
- * Used with any writing functions to the client
- */
- public ByteBuffer StringtoBB(String theStr) {
- byte[] bytearr = new byte[theStr.length()];
- bytearr = theStr.getBytes();
- ByteBuffer bbuf = ByteBuffer.allocate(theStr.length());
- bbuf = ByteBuffer.wrap(bytearr);
- return bbuf;
- }
- private class dataPerSocket {
- private Thread myLife;
- private boolean readMe;
- private SocketChannel mySocket;
- // private String[] recentCommands;
- // private ByteBuffer newLine = ByteBuffer.allocate(1024);
- private String characterName;
- private boolean loggedIn;
- private Selector selector; // The selector we'll be monitoring
- public dataPerSocket() throws IOException {
- selector = SelectorProvider.provider().openSelector();
- readMe = true;
- mySocket = null;
- // recentCommands = new String[10];
- characterName = "";
- loggedIn = false;
- }
- public void beginLife(SocketChannel newClient) throws IOException {
- // Register it to this objects selector so we can read/write from it in this thread.
- newClient.register(selector, SelectionKey.OP_READ, SelectionKey.OP_WRITE);
- myLife = new Thread(new dataReader());
- myLife.start();
- }
- public class dataReader implements Runnable {
- public void run() {
- String tmpRead = "";
- while (readMe) {
- try {
- // Wait for an event on a registered channel
- selector.select();
- // Iterate over the selected keys (i.e. OP_ACCEPT - could be OP_READ&OP_WRITE though)
- Iterator selectedKeys = selector.selectedKeys().iterator();
- // Yeah.
- while (selectedKeys.hasNext()) {
- SelectionKey key = (SelectionKey) selectedKeys.next();
- selectedKeys.remove();
- if (!key.isValid()) {
- System.out.println("Not valid any more.");
- readMe = false;
- break;
- }
- /**
- * Unclean shutdown. Save their information. etc.
- */
- if(!mySocket.socket().isConnected()) {
- System.out.println(characterName + " quit (non-clean).");
- // close down socket
- // close thread
- // springclean myData
- // global that they have quit
- }
- if(key.isReadable()) {
- tmpRead = readLine().replace("\n", "").replace("\r","");
- if (tmpRead.length() > 0) parse(tmpRead);
- continue;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- System.out.println("dataReader: Finished run().");
- }
- }
- private String readLine() throws IOException {
- // Buffer.
- ByteBuffer buf = ByteBuffer.allocate(1024);
- this.mySocket.read(buf);
- return BBtoString(buf);
- }
- public void initLogin(SocketChannel newClient) throws IOException { // Used by iBH.addClient
- this.mySocket = newClient;
- Date todaysDate = new java.util.Date();
- SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- System.out.println("[" + formatter.format(todaysDate) + "] New connection from " + newClient.socket().getInetAddress() + ".");
- sendLine(this.mySocket, "*** Welcome to PulseMUD! ***");
- sendMessage(this.mySocket, "Enter your username: "); // TODO: Write these functions
- }
- // Pushses newComm to the front of the list
- // public void pushCommand(String newComm) {
- // for(int i = 9; i > 0; i--)/
- // recentCommands[i] = recentCommands[i - 1];
- // recentCommands[0] = newComm;
- // }
- public void writeln(String outputLine) throws IOException {
- sendMessage(this.mySocket, outputLine + "\n\r");
- }
- public void write(String outputLine) throws IOException {
- sendLine(this.mySocket, outputLine);
- }
- // Used for global commands
- public void writeall(String origin, String theMsg) throws IOException {
- for (int i = 0;i < myData.length;i++)
- if (!getCharacterName(i).equals(origin) && isLoggedIn(i))
- myData[i].writeln(theMsg);
- return;
- }
- //splits a string bases on whitespace and returns the first set of characters before the whitespace
- //essentially, the command without arguments, returning it in lowercase --adam
- public String stringCommand(String strInput, int x)
- {
- String strOutput[];
- strOutput = strInput.split(" ");
- strOutput[x] = strOutput[x].toLowerCase();
- return strOutput[x];
- }
- public int getStringCommandLength(String strInput)
- {
- // int length = 0;
- String strOutput[];
- strOutput = strInput.split(" ");
- return strOutput.length;
- }
- private void parse(String toParse) throws IOException {
- // So I figured that no first command is gonna be more than 10 characters long.
- // What I'll do here is read the first 11 characters, searching for a whitespace
- // If we get to the 11th character and there's no whitespace or endline, it must be an erroneus commmand
- // Otherwise, parse according to that command.
- // Putty was sending a line I didn't recognise, of negative integer bytes. This ignores it.
- if (Character.getNumericValue(toParse.charAt(0)) < 0) return;
- // Alternatively, we can do this:
- // if (toParse.startsWith("quit")) {
- // writeln("This isn't implemented yet!");
- // return;
- // }
- if (stringCommand(toParse, 0).equals("quit")) {
- writeln("This isn't implemented yet!");
- return;
- }
- String firstComm = "";
- boolean commandOK = false;
- int i = 0;
- while (i < 11 && i < toParse.length()) {
- if (Character.toString(toParse.charAt(i)).equals(" ")) { commandOK = true; i = 11; break; }
- firstComm += Character.toString(toParse.charAt(i)).toLowerCase();
- i++;
- }
- if (i == toParse.length() && i < 11) commandOK = true;
- if (!loggedIn) {
- if (firstComm.matches("[a-zA-Z]{3,10}")) {
- characterName = Character.toString(firstComm.charAt(0)).toUpperCase() + firstComm.substring(1);
- writeln("Welcome to PulseMUD, " + characterName + "!");
- loggedIn = true;
- return;
- } else {
- writeln("Your name must consist of ONLY\n\ralphanumerical characters and must be\n\rbetween 3 and 10 characters long.");
- write("Enter your username: ");
- return;
- }
- }
- if (commandOK && firstComm.length() > 0 && firstComm.matches("[a-zA-Z]{0,10}")) { // Begin parsing that beautiful command!
- if (stringCommand(toParse, 1).equals("hello")) { writeln("Hello, " + this.characterName + "!"); return; }
- if (firstComm.equals("global")) {
- if(getStringCommandLength(toParse) < 1) {
- writeall(characterName, "[" + characterName + "]: " + toParse.substring(7));
- return;
- } else {
- writeln("Include a message!");
- }
- }
- writeln("I don't know command '" + firstComm + "'.");
- return;
- } else {
- writeln("Erroneus command.");
- return;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement