package vooga.rts.networking.server; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.util.logging.Level; import java.util.logging.Logger; import vooga.rts.networking.NetworkBundle; import vooga.rts.networking.communications.IMessage; import vooga.rts.networking.communications.Message; import vooga.rts.networking.communications.clientmessages.InitialConnectionMessage; import vooga.rts.networking.communications.servermessages.CloseConnectionMessage; /** * Represents a server-side connection between the client and the server. * * @author David Winegar * @author Henrique Morales * */ public class ConnectionThread extends Thread { private Socket mySocket; private ObjectInputStream myInput; private ObjectOutputStream myOutput; private int myID; private String myUserName; private String myGameName; private IMessageReceiver myMessageServer; private boolean myConnectionActive = false; private Logger myLogger; /** * Represents a thread that communicates to a client * * @param socket socket used for establishing the connection * @param id number of connection */ ConnectionThread (Socket socket, IMessageReceiver server, int id, Logger logger) { mySocket = socket; myMessageServer = server; myID = id; myLogger = logger; try { myInput = new ObjectInputStream(mySocket.getInputStream()); myOutput = new ObjectOutputStream(mySocket.getOutputStream()); } catch (IOException e) { myLogger.log(Level.FINER, NetworkBundle.getString("InitialConnectionFailed")); } } /** * Switches which IMessageReceiver to send messages to. * * @param server to switch to */ public void switchMessageServer (IMessageReceiver server) { myMessageServer = server; } /** * Keeps listening for messages and adds to the server's message queue */ @Override public void run () { myConnectionActive = true; try { Object obj = myInput.readObject(); // Checks to see if first object passed is initial connection message if (obj instanceof InitialConnectionMessage) { sendToMessageServer(obj); } else { // first object is not initial connection message myConnectionActive = false; close(); return; } while (myConnectionActive) { obj = myInput.readObject(); if (obj instanceof IMessage) { sendToMessageServer(obj); } } } catch (IOException e) { myLogger.log(Level.FINER, NetworkBundle.getString("ConnectionFailedIO")); close(); } catch (ClassNotFoundException e) { myLogger.log(Level.FINER, NetworkBundle.getString("ConnectionFailedClassEx")); } } /** * sends object to message server */ private void sendToMessageServer (Object obj) { Message message = (Message) obj; myMessageServer.receiveMessageFromClient(message, this); } /** * Closes streams and socket of this thread */ public void close () { myMessageServer.removeConnection(this); myConnectionActive = false; sendMessage(new CloseConnectionMessage()); try { if (myOutput != null) { myOutput.close(); } if (myInput != null) { myInput.close(); } if (mySocket != null) { mySocket.close(); } } catch (IOException e) { myLogger.log(Level.FINER, NetworkBundle.getString("ClosingConnectionsFailed")); } myLogger.log(Level.FINER, NetworkBundle.getString("ClosedConnection") + myID); } /** * Broadcasts a Message object to the client * * @param m Message object to be sent */ public void sendMessage (IMessage m) { if (!mySocket.isConnected()) { close(); } try { myOutput.writeObject(m); myLogger.log(Level.FINEST, NetworkBundle.getString("MessageSent") + m.getClass().getSimpleName()); } catch (IOException e) { myLogger.log(Level.FINE, NetworkBundle.getString("MessageFailed") + m.getClass().getSimpleName()); } } /** * gets the ID for the connection thread * * @return id */ public int getID () { return myID; } /** * Gets the user name for the connection thread. * * @return username */ public String getUserName () { return myUserName; } /** * Gets the name of the game the user is playing. * * @return game name */ public String getGameName () { return myGameName; } /** * Sets the user name - can only be set once. * * @param userName name to set */ public void setUserName (String userName) { if (myUserName == null) { myUserName = userName; } } /** * Sets the game name - can only be set once. * * @param gameName name to set */ public void setGameName (String gameName) { if (myGameName == null) { myGameName = gameName; } } }