WIP. Probably need to cherry pick stuff out of here.

Added ClientConnection and server-side handshake.
Added MessageSerialiser and Deserialiser.
#story[1095]
This commit is contained in:
fjc40
2017-08-10 12:13:40 +12:00
parent 3ec87582d3
commit 7cc39abe57
35 changed files with 1837 additions and 793 deletions
@@ -3,6 +3,7 @@ package visualiser.gameController;
import network.BinaryMessageEncoder;
import network.Exceptions.InvalidMessageException;
import network.MessageEncoders.RaceVisionByteEncoder;
import network.Messages.AC35Data;
import network.Messages.BoatAction;
import network.Messages.Enums.BoatActionEnum;
import network.Messages.Enums.MessageType;
@@ -13,6 +14,7 @@ import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -20,28 +22,18 @@ import java.util.logging.Logger;
* Basic service for sending key presses to game server
*/
public class ControllerClient {
/**
* Socket to server
*/
Socket socket;
/**
* Output stream wrapper for socket to server
* Queue of messages to be sent to server.
*/
DataOutputStream outputStream;
private BlockingQueue<AC35Data> outgoingMessages;
/**
* Initialise controller client with live socket.
* @param socket to server
* @param outgoingMessages Queue to place messages on to send to server.
*/
public ControllerClient(Socket socket) {
this.socket = socket;
try {
this.outputStream = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
public ControllerClient(BlockingQueue<AC35Data> outgoingMessages) {
this.outgoingMessages = outgoingMessages;
}
/**
@@ -49,27 +41,13 @@ public class ControllerClient {
* @param key to send
* @throws IOException if socket write fails
*/
public void sendKey(ControlKey key) throws IOException {
public void sendKey(ControlKey key) throws InterruptedException {
BoatActionEnum protocolCode = key.getProtocolCode();
if(protocolCode != BoatActionEnum.NOT_A_STATUS) {
BoatAction boatAction = new BoatAction(protocolCode);
//Encode BoatAction.
try {
byte[] encodedBoatAction = RaceVisionByteEncoder.encode(boatAction);
BinaryMessageEncoder binaryMessage = new BinaryMessageEncoder(MessageType.BOATACTION, System.currentTimeMillis(), 0,
(short) encodedBoatAction.length, encodedBoatAction);
System.out.println("Sending out key: " + protocolCode);
outputStream.write(binaryMessage.getFullMessage());
} catch (InvalidMessageException e) {
Logger.getGlobal().log(Level.WARNING, "Could not encode BoatAction: " + boatAction, e);
}
outgoingMessages.put(boatAction);
}
}
@@ -1,16 +1,19 @@
package visualiser.gameController;
import mock.model.commandFactory.Command;
import mock.model.commandFactory.CommandFactory;
import mock.model.commandFactory.CompositeCommand;
import network.BinaryMessageDecoder;
import network.Exceptions.InvalidMessageException;
import network.MessageDecoders.BoatActionDecoder;
import network.Messages.AC35Data;
import network.Messages.BoatAction;
import network.Messages.Enums.BoatActionEnum;
import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import network.Messages.Enums.MessageType;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.io.InputStream;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -18,57 +21,69 @@ import java.util.logging.Logger;
* Service for dispatching key press data to race from client
*/
public class ControllerServer implements Runnable {
/**
* Socket to client
*/
private Socket socket;
/**
* Wrapper for input from client
*/
private DataInputStream inputStream;
/**
* Initialise server-side controller with live client socket
* @param socket to client
* Queue of incoming messages from client.
*/
public ControllerServer(Socket socket) {
this.socket = socket;
try {
this.inputStream = new DataInputStream(this.socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
private BlockingQueue<AC35Data> inputQueue;
/**
* Collection of commands from client for race to execute.
*/
private CompositeCommand compositeCommand;
/**
* This is the source ID associated with the client.
*/
private int clientSourceID;
/**
* Initialise server-side controller with live client socket.
* @param compositeCommand Commands for the race to execute.
* @param inputQueue The queue of messages to read from.
* @param clientSourceID The source ID of the client's boat.
*/
public ControllerServer(CompositeCommand compositeCommand, BlockingQueue<AC35Data> inputQueue, int clientSourceID) {
this.compositeCommand = compositeCommand;
this.inputQueue = inputQueue;
this.clientSourceID = clientSourceID;
}
/**
* Wait for controller key input from client and loop.
*/
@Override
public void run() {
while(true) {
byte[] message = new byte[20];
while(!Thread.interrupted()) {
try {
if (inputStream.available() > 0) {
inputStream.read(message);
AC35Data message = inputQueue.take();
BinaryMessageDecoder encodedMessage = new BinaryMessageDecoder(message);
BoatActionDecoder boatActionDecoder = new BoatActionDecoder();
if (message.getType() == MessageType.BOATACTION) {
try {
boatActionDecoder.decode(encodedMessage.getMessageBody());
BoatAction boatAction = boatActionDecoder.getMessage();
System.out.println("Received key: " + boatAction.getBoatAction());
} catch (InvalidMessageException e) {
Logger.getGlobal().log(Level.WARNING, "Could not decode BoatAction message.", e);
}
BoatAction boatAction = (BoatAction) message;
boatAction.setSourceID(clientSourceID);
Command command = CommandFactory.createCommand(boatAction);
compositeCommand.addCommand(command);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
Logger.getGlobal().log(Level.WARNING, "ControllerServer Interrupted while waiting for message on incoming message queue.", e);
Thread.currentThread().interrupt();
return;
}
}
}
}
@@ -27,8 +27,8 @@ public class KeyFactory {
keyState.put("SPACE", new VMGKey("VMG"));
keyState.put("SHIFT", new SailsToggleKey("Toggle Sails"));
keyState.put("ENTER", new TackGybeKey("Tack/Gybe"));
keyState.put("PAGE_UP", new UpWindKey("Upwind"));
keyState.put("PAGE_DOWN", new DownWindKey("Downwind"));
keyState.put("UP", new UpWindKey("Upwind"));
keyState.put("DOWN", new DownWindKey("Downwind"));
}
/**