scp-app

git clone git://git.codymlewis.com/scp-app.git
Log | Files | Refs | LICENSE

commit 07e82437a6c70757c817303c7cf2ffe91ef13e9f
parent 1cbed5c430c9d87eb54ce25a3714fd4e21041e40
Author: Cody Lewis <luxdotsugi@gmail.com>
Date:   Mon, 20 Aug 2018 21:47:52 +1000

Disconnect now works correctly

Diffstat:
AChat.java | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MChatClient.java | 81++++++++++++++++++++++++++++++++++++++++++-------------------------------------
MChatServer.java | 84++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
MSCP.java | 15++++++++-------
4 files changed, 160 insertions(+), 82 deletions(-)

diff --git a/Chat.java b/Chat.java @@ -0,0 +1,61 @@ +import java.util.Scanner; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +/** + * Chat.java - SENG3400A1 + * Shared functions and variables between ChatServer and ChatClient + * + * @author Cody Lewis + * @since 2018-08-19 + */ +public class Chat { + protected SCP scp; // Must be a class as it uses non-static variables + protected Scanner console; + protected PrintWriter out; + protected BufferedReader in; + protected Socket cliSocket; + protected InetAddress address; + protected int port; + protected String username; + public Chat() { + scp = new SCP(); + console = new Scanner(System.in); + } + /** + * Take an input from the users and give an out suitable to put into a message + * @return A String of the input formatted to be embedded in a SCP message + */ + protected String textToMessage() { + String line = console.nextLine(), message = ""; + do { + if(line.compareTo("DISCONNECT") == 0) { + return "DISCONNECT"; + } + message += "\n" + line; + line = console.nextLine(); + } while(line.length() != 0); + return message.substring(1); // get rid of leading \n + } + /** + * Recieve a message from the other user + */ + protected String recieveMessage() throws SCPException, IOException { + String packet = "", line = ""; + while((line = in.readLine()).compareTo("SCP END") != 0) { + packet += line + "\n"; + } + if(scp.parseDisconnect(packet)) { + return "DISCONNECT"; + } + if(scp.parseAcknowledge(packet)) { + return "ACKNOWLEDGE"; + } + return scp.parseMessage(packet, "127.0.0.1", 3400); + } + protected void disconnect() { + out.println(scp.disconnect()); + } +}+ \ No newline at end of file diff --git a/ChatClient.java b/ChatClient.java @@ -2,9 +2,10 @@ import java.util.Scanner; import java.io.BufferedReader; import java.io.PrintWriter; import java.io.InputStreamReader; +import java.io.IOException; import java.net.Socket; +import java.net.InetAddress; import java.net.UnknownHostException; -import java.io.IOException; /** * ChatClient.java - SENG3400A1 * A socket based half duplex chat client @@ -12,11 +13,7 @@ import java.io.IOException; * @author Cody Lewis * @since 2018-08-10 */ -public class ChatClient { - private SCP scp = new SCP(); - private Socket socket; - private PrintWriter out; - private BufferedReader in; +public class ChatClient extends Chat { public static void main(String args[]) { ChatClient cc = new ChatClient(); cc.run(args); @@ -28,25 +25,41 @@ public class ChatClient { */ public void run(String args[]) { try { - String hostName = args.length > 0 ? args[0] : "localhost"; - int port = args.length > 1 ? Integer.parseInt(args[1]) : 3400; - System.out.println(String.format("Connecting to %s:%d", hostName, port)); - connectToServer(hostName, port); + address = args.length > 0 ? InetAddress.getLocalHost() : InetAddress.getLocalHost(); + port = args.length > 1 ? Integer.parseInt(args[1]) : 3400; + if(port < 1024) { + throw new SCPException("Using a port number 1023 or lower may interrupt system operations"); + } + System.out.println(String.format("Connecting to %s:%d", address.getHostAddress(), port)); + connectToServer(); System.out.println("Connected to server"); - Scanner console = new Scanner(System.in); System.out.print("Input a username: "); - String username = console.next(); - scpConnect(hostName, port, username); + username = console.next(); + scpConnect(); System.out.println("Connected to SCP"); String message; - while(true) { - System.out.print(recieveMessage()); - System.out.print("send a message: "); - message = console.next(); - if(message == "DISCONNECT") { + String recievedMessage; + boolean disconnect = false; + while(!disconnect) { + recievedMessage = recieveMessage(); + if(recievedMessage == "DISCONNECT") { + out.println(scp.acknowledge()); + disconnect = true; break; } - out.println(scp.message("127.0.0.1", 3400, message)); + System.out.print(recievedMessage); + System.out.print("send a message: "); + message = textToMessage(); + if(message.compareTo("DISCONNECT") == 0) { + out.println(scp.disconnect()); + if(recieveMessage().compareTo("ACKNOWLEDGE") == 0) { + disconnect = true; + break; + } else { + throw new SCPException("Server did not acknowledge disconnect"); + } + } + out.println(scp.message(address.getHostAddress(), port, message)); System.out.println("Server is typing..."); } console.close(); @@ -64,10 +77,10 @@ public class ChatClient { * @param port the port number the server is running on * @return true on successful connection */ - private boolean connectToServer(String hostName, int port) throws UnknownHostException, IOException { - socket = new Socket(hostName, port); - out = new PrintWriter(socket.getOutputStream(), true); - in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + private boolean connectToServer() throws UnknownHostException, IOException { + cliSocket = new Socket(address.getHostAddress(), port); + out = new PrintWriter(cliSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader(cliSocket.getInputStream())); return true; } /** @@ -77,31 +90,23 @@ public class ChatClient { * @param username client specified username * @return true on packet send */ - private boolean scpConnect(String hostName, int port, String username) throws SCPException, IOException { - String connectionString = scp.connect(username, hostName, port); + private boolean scpConnect() throws SCPException, IOException { + String connectionString = scp.connect(username, address.getHostAddress(), port); out.println(connectionString); - if(scpDecide(username)) { - scpAcknowledge(username); + if(scpDecide()) { + scpAcknowledge(); return true; } return false; } - private boolean scpDecide(String username) throws SCPException, IOException { + private boolean scpDecide() throws SCPException, IOException { String inLine, packet = ""; while((inLine = in.readLine()).compareTo("SCP END") != 0) { packet += inLine + "\n"; } return scp.parseAccept(packet, username); } - private void scpAcknowledge(String username) { - out.println(scp.acknowledge(username, "127.0.0.1", 3400)); - } - private String recieveMessage() throws SCPException, IOException { - String packet = ""; - String line = ""; - while((line = in.readLine()).compareTo("SCP END") != 0) { - packet += line + "\n"; - } - return scp.parseMessage(packet, "127.0.0.1", 3400); + private void scpAcknowledge() { + out.println(scp.acknowledge(username, address.getHostAddress(), port)); } } diff --git a/ChatServer.java b/ChatServer.java @@ -15,14 +15,8 @@ import java.net.UnknownHostException; * @author Cody Lewis * @since 2018-08-10 */ -public class ChatServer { - private SCP scp = new SCP(); +public class ChatServer extends Chat { private ServerSocket serverSocket; - private Socket cliSocket; - private PrintWriter out; - private BufferedReader in; - private InetAddress hostInetAddress; - private int port; private String username; private static final int BACKLOG = 1; // Max length for queue of messages public static void main(String args[]) { @@ -36,10 +30,13 @@ public class ChatServer { */ public void run(String args[]) { try { - hostInetAddress = args.length > 0 ? InetAddress.getLocalHost() : InetAddress.getLocalHost(); + address = args.length > 0 ? InetAddress.getLocalHost() : InetAddress.getLocalHost(); port = args.length > 1 ? Integer.parseInt(args[1]) : 3400; + if(port < 1024) { + throw new SCPException("Using a port number 1023 or lower may interrupt system operations"); + } String welcomeMessage = args.length > 2 ? args[2] : "Welcome to SCP"; - System.out.println(String.format("Starting server on %s:%d", hostInetAddress.getHostAddress(), port)); + System.out.println(String.format("Starting server on %s:%d", address.getHostAddress(), port)); startSocket(); System.out.println("Started server"); hostConnection(welcomeMessage); @@ -60,26 +57,44 @@ public class ChatServer { System.out.println("Waiting for client to SCP connect"); username = clientConnect(); username = username.substring(1, username.length() - 1); // remove quotes - if(username == "") { + if(username == "") { // Can't have a blank username anyway cliSocket.close(); - System.out.println("Rejected client for time differential greater than 5"); - } - scpAccept(); - if(acknowledged()) { - System.out.println(String.format("User %s has connected to SCP", username)); - Scanner console = new Scanner(System.in); - String message = welcomeMessage; - while(true) { - out.println(scp.message(hostInetAddress.getHostAddress(), port, message)); - System.out.println(String.format("%s is typing...", username)); - System.out.print(recieveMessage()); - System.out.print("Send a message: "); - message = console.next(); - if(message == "DISCONNECT") { - break; + System.out.println("Rejected client for time differential greater than 5, trying again"); + hostConnection(welcomeMessage); + } else { + scpAccept(); + if(acknowledged()) { + System.out.println(String.format("User %s has connected to SCP", username)); + String message = welcomeMessage; + String recievedMessage; + boolean disconnect = false; + while(!disconnect) { + out.println(scp.message(address.getHostAddress(), port, message)); + System.out.print(String.format("%s is typing...", username)); + recievedMessage = recieveMessage(); + if(recievedMessage == "DISCONNECT") { + out.println(scp.acknowledge()); + disconnect = true; + break; + } + System.out.print(recievedMessage); + System.out.print("Send a message: "); + message = textToMessage(); + if(message.compareTo("DISCONNECT") == 0) { + out.println(scp.disconnect()); + if(recieveMessage().compareTo("ACKNOWLEDGE") == 0) { + disconnect = true; + break; + } else { + throw new SCPException("Client did not acknowledge disconnect"); + } + } } + console.close(); + } else { + System.err.println("Client did not acknowledge, trying again"); + hostConnection(welcomeMessage); } - console.close(); } } /** @@ -89,7 +104,7 @@ public class ChatServer { * @return True on successful start */ private boolean startSocket() throws IOException { - serverSocket = new ServerSocket(port, BACKLOG, hostInetAddress); + serverSocket = new ServerSocket(port, BACKLOG, address); return true; } /** @@ -140,16 +155,11 @@ public class ChatServer { while((inLine = in.readLine()).compareTo("SCP END") != 0) { packet += inLine; } - return scp.parseAcknowledge(packet) == "success"; - } - /** - * Recieve a message from the client - */ - private String recieveMessage() throws SCPException, IOException { - String packet = "", line = ""; - while((line = in.readLine()).compareTo("SCP END") != 0) { - packet += line + "\n"; + boolean result = scp.parseAcknowledge(packet); + if(result) { + return true; + } else { + throw new SCPException("SCP ACKNOWLEDGE", packet); } - return scp.parseMessage(packet, "127.0.0.1", 3400); } } diff --git a/SCP.java b/SCP.java @@ -8,6 +8,7 @@ import java.io.IOException; * * @author Cody Lewis * @since 2018-08-10 + * TODO Add all detail checks to the parsing */ public class SCP { // Packet generating methods @@ -95,7 +96,7 @@ public class SCP { * @param packet the connect packet * @return A Result object containing final status and corresponding data */ - public String parseConnect(String packet) throws TimeDiffException, SCPException, IOException { + public String parseConnect(String packet, String address, int port) throws TimeDiffException, SCPException, IOException { String username = ""; BufferedReader sstream = new BufferedReader(new StringReader(packet)); boolean firstLine = true; @@ -130,11 +131,11 @@ public class SCP { private int findTimeDiff(int otherTime) { return Math.abs((int)Instant.now().getEpochSecond() - otherTime); } - public String parseAcknowledge(String packet) throws SCPException { + public boolean parseAcknowledge(String packet) { if (packet.indexOf("SCP ACKNOWLEDGE") > -1) { - return "success"; + return true; } - throw new SCPException("SCP ACKNOWLEDGE", packet); + return false; } public boolean parseAccept(String packet, String username) throws SCPException, IOException { boolean accept = false; @@ -183,10 +184,10 @@ public class SCP { } return message; } - public String parseDisconnect(String packet) throws SCPException { + public boolean parseDisconnect(String packet) { if (packet.indexOf("SCP DISCONNECT") > -1) { - return "success"; + return true; } - throw new SCPException("SCP DISCONNECT", packet); + return false; } } \ No newline at end of file