From 5e0eb7a10ecb88d95b5a5883068593de8ccdf114 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:44:58 -0800 Subject: [PATCH 01/14] Wave 2 Complete --- src/ChatterboxClient.java | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 9f80fc0..6bbc1c3 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -126,8 +126,41 @@ public static void main(String[] args) { */ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException { // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) + // Make sure the args are 4, throw exception otherwise + if (args.length != 4) { + throw new IllegalArgumentException(); + } + + // Variable to track the port number + int convertedPort; + + // Try to convert the port number, catch if there is an issue + try { + // Convert the port into an integer and store its converted value + convertedPort = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + + // Check if the port is in range/valid + if (!inRange(1, 65535, convertedPort)) { + throw new IllegalArgumentException(); + } else { + return new ChatterboxOptions(args[0], convertedPort, args[2], args[3]); + } // Remove this exception - throw new UnsupportedOperationException("Argument parsing not yet implemented. Implement parseArgs and remove this exception"); + // throw new UnsupportedOperationException("Argument parsing not yet implemented. Implement parseArgs and remove this exception"); + } + + /** + * A helper method that checks if a number is in range of two given numbers + * @param min the minimum integer value + * @param max the max integer value + * @param num the number to check if in range + * @return whether the target number is in range + */ + private static boolean inRange(int min, int max, int num) { + return num >= min && num <= max; } /** From 8eac85d1724f9438905bd09a9c1eda6fc8802556 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:50:31 -0800 Subject: [PATCH 02/14] Fixed javadoc for helper in range method --- src/ChatterboxClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 6bbc1c3..3f3a10e 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -154,6 +154,7 @@ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentE /** * A helper method that checks if a number is in range of two given numbers + * * @param min the minimum integer value * @param max the max integer value * @param num the number to check if in range From d56dde332d242d73a658de99a3718df5bb1d4622 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:57:30 -0800 Subject: [PATCH 03/14] Wave 3 Complete --- src/ChatterboxClient.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 3f3a10e..bef8618 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -180,8 +180,12 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output this.userInput = new Scanner(userInput, StandardCharsets.UTF_8); this.userOutput = userOutput; - throw new UnsupportedOperationException("Constructor not yet implemented. Implement ChatterboxClient constructor and remove this exception"); + // throw new UnsupportedOperationException("Constructor not yet implemented. Implement ChatterboxClient constructor and remove this exception"); // TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into fields + this.host = options.getHost(); + this.port = options.getPort(); + this.username = options.getUsername(); + this.password = options.getPassword(); } /** From 542d63135d1ff5ed6ca99ecdd0c92b0a59ec1b5c Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:26:13 -0800 Subject: [PATCH 04/14] Wave 4 Complete --- src/ChatterboxClient.java | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index bef8618..9b9f79a 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -2,7 +2,10 @@ import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.Scanner; @@ -202,10 +205,27 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output * @throws IOException if the socket cannot be opened */ public void connect() throws IOException { - throw new UnsupportedOperationException("Connect not yet implemented. Implement connect() and remove this exception!"); + // throw new UnsupportedOperationException("Connect not yet implemented. Implement connect() and remove this exception!"); // Make sure to have this.serverReader and this.serverWriter set by the end of this method! // hint: get the streams from the sockets, use those to create the InputStreamReader/OutputStreamWriter and the BufferedReader/BufferedWriter + + // Instantiate a socket object with the right host and port number + Socket socket = new Socket(this.host, this.port); + + // Track all input to read + InputStream inputStream = socket.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, java.nio.charset.StandardCharsets.UTF_8); + + // Set the server reader + this.serverReader = new BufferedReader(inputStreamReader); + + // Track all output streams + OutputStream outputStream = socket.getOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, java.nio.charset.StandardCharsets.UTF_8); + + // Set the server writer + this.serverWriter = new BufferedWriter(outputStreamWriter); } /** From 72ca287ebe4b331002991643932556c93f117ed9 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 17:48:59 -0800 Subject: [PATCH 05/14] Wave 5 Complete --- src/ChatterboxClient.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 9b9f79a..5232ca8 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -249,9 +249,15 @@ public void connect() throws IOException { * @throws IllegalArgumentException for bad credentials / server rejection */ public void authenticate() throws IOException, IllegalArgumentException { - throw new UnsupportedOperationException("Authenticate not yet implemented. Implement authenticate() and remove this exception!"); + // throw new UnsupportedOperationException("Authenticate not yet implemented. Implement authenticate() and remove this exception!"); // Hint: use the username/password instance variables, DO NOT READ FROM userInput // send messages using serverWriter (don't forget to flush!) + System.out.println(serverReader.readLine()); + + // Write the username and password to the server and flush + serverWriter.write(this.username + " " + this.password + "\n"); + serverWriter.newLine(); + serverWriter.flush(); } /** From 0f7725971a77d5baa877e37b1cc5e908d833dbf1 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:33:58 -0800 Subject: [PATCH 06/14] Reworked Wave 5, Authentication should read properly now... --- src/ChatterboxClient.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 5232ca8..866c9bf 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -252,12 +252,25 @@ public void authenticate() throws IOException, IllegalArgumentException { // throw new UnsupportedOperationException("Authenticate not yet implemented. Implement authenticate() and remove this exception!"); // Hint: use the username/password instance variables, DO NOT READ FROM userInput // send messages using serverWriter (don't forget to flush!) - System.out.println(serverReader.readLine()); + + // Read and display any messages from the server + userOutput.write((serverReader.readLine() + "\n").getBytes(StandardCharsets.UTF_8)); + userOutput.flush(); // Write the username and password to the server and flush serverWriter.write(this.username + " " + this.password + "\n"); - serverWriter.newLine(); serverWriter.flush(); + + // Server response + String serverResponse = serverReader.readLine(); + + // Read any messages coming from the server + if (serverResponse.startsWith("Welcome")){ + // Write the welcome message to the output + userOutput.write((serverResponse + "\n").getBytes(StandardCharsets.UTF_8)); + userOutput.flush(); + return; + } else { throw new IllegalArgumentException(serverResponse); } } /** @@ -274,6 +287,7 @@ public void authenticate() throws IOException, IllegalArgumentException { */ public void streamChat() throws IOException { throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); + // printIncomingChats(); } /** From 6ab6377ad91ce5b5c2913902711d26cca95efcd1 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:07:04 -0800 Subject: [PATCH 07/14] Completed Wave 6 --- src/ChatterboxClient.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 866c9bf..aab9c5c 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -286,8 +286,8 @@ public void authenticate() throws IOException, IllegalArgumentException { * @throws IOException */ public void streamChat() throws IOException { - throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); - // printIncomingChats(); + // throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); + printIncomingChats(); } /** @@ -307,6 +307,21 @@ public void streamChat() throws IOException { public void printIncomingChats() { // Listen on serverReader // Write to userOutput, NOT System.out + + // Variable to track the response + String res; + + // Run repeaditly + while (true) { + // Try to read the line coming in from the server + try { + res = serverReader.readLine(); + userOutput.write((res + "\n").getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + // Exit if there is an IO exception + System.exit(0); + } + } } /** From 88e5de85eac227a9024b0d42c1670bef41b9b5ec Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:12:25 -0800 Subject: [PATCH 08/14] Fixed Wave 6, added flush for userOutput --- src/ChatterboxClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index aab9c5c..a0f5b28 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -317,6 +317,7 @@ public void printIncomingChats() { try { res = serverReader.readLine(); userOutput.write((res + "\n").getBytes(StandardCharsets.UTF_8)); + userOutput.flush(); } catch (IOException e) { // Exit if there is an IO exception System.exit(0); From 6a49a7b01b4ee10b104c97b2301b8edf6ef8d901 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:52:04 -0800 Subject: [PATCH 09/14] Fixed Wave 6, made sure server disconnected message pops up --- src/ChatterboxClient.java | 42 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index a0f5b28..c471237 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -9,6 +9,8 @@ import java.nio.charset.StandardCharsets; import java.util.Scanner; +import javax.imageio.IIOException; + /** * A simple command-line chat client for the Chatterbox server. * @@ -287,7 +289,11 @@ public void authenticate() throws IOException, IllegalArgumentException { */ public void streamChat() throws IOException { // throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!"); - printIncomingChats(); + Thread incoming = new Thread(() -> printIncomingChats()); + Thread outgoing = new Thread(() -> sendOutgoingChats()); + + incoming.start(); + outgoing.start(); } /** @@ -311,20 +317,41 @@ public void printIncomingChats() { // Variable to track the response String res; - // Run repeaditly while (true) { - // Try to read the line coming in from the server try { + // Read the line from the server reader res = serverReader.readLine(); - userOutput.write((res + "\n").getBytes(StandardCharsets.UTF_8)); - userOutput.flush(); + + // Check for null res + if (res == null) { + writeUserOutput("Server disconnected."); + System.exit(0); + } + + // Not null, write to user output and flush + writeUserOutput(res); } catch (IOException e) { - // Exit if there is an IO exception - System.exit(0); + try { + writeUserOutput("Connection lost."); + } catch (IOException f) { + System.exit(0); + } finally { + System.exit(0); + } } } } + /** + * Private helper method to write to the user output and flush + * + * @param msg + */ + private void writeUserOutput(String msg) throws IOException { + userOutput.write((msg + "\n").getBytes(StandardCharsets.UTF_8)); + userOutput.flush(); + } + /** * Continuously read user-typed messages and send them to the server. * @@ -340,7 +367,6 @@ public void printIncomingChats() { public void sendOutgoingChats() { // Use the userInput to read, NOT System.in directly // loop forever reading user input - // write to serverOutput } public String getHost() { From b743781c380f0448f81e6d1a55c96e8867c9291c Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Thu, 4 Dec 2025 20:03:37 -0800 Subject: [PATCH 10/14] Completed Wave 7 --- src/ChatterboxClient.java | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index c471237..36626be 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -325,7 +325,7 @@ public void printIncomingChats() { // Check for null res if (res == null) { writeUserOutput("Server disconnected."); - System.exit(0); + System.exit(1); } // Not null, write to user output and flush @@ -334,9 +334,9 @@ public void printIncomingChats() { try { writeUserOutput("Connection lost."); } catch (IOException f) { - System.exit(0); + System.exit(1); } finally { - System.exit(0); + System.exit(1); } } } @@ -367,6 +367,30 @@ private void writeUserOutput(String msg) throws IOException { public void sendOutgoingChats() { // Use the userInput to read, NOT System.in directly // loop forever reading user input + while (true) { + if (userInput.hasNextLine()) { + // Store the line the user inputted + String input = userInput.nextLine(); + + // Try to write the message to the server + try { + serverWriter.write((input + "\n")); + serverWriter.flush(); + } catch (IOException e) { + // Error writing to server, connection lost + // Try to write to the user what has happened + try { + writeUserOutput("Connection is gone."); + } catch (IOException f) { + // Exit the system if another IOException is met writing to the user + System.exit(1); + } finally { + // Exit anyways + System.exit(1); + } + } + } + } } public String getHost() { From fbfba063ec74e442d209caa9c24652a495496d36 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Sun, 7 Dec 2025 21:02:52 -0800 Subject: [PATCH 11/14] Made some quality of life changes in terms of argument exception messages and null messages --- src/ChatterboxClient.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 36626be..0e2484c 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -133,7 +133,7 @@ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentE // TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password) // Make sure the args are 4, throw exception otherwise if (args.length != 4) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Invalid arguments, there must be 4 arguments."); } // Variable to track the port number @@ -144,12 +144,12 @@ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentE // Convert the port into an integer and store its converted value convertedPort = Integer.parseInt(args[1]); } catch (NumberFormatException e) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Invalid port number, please enter a valid port number."); } // Check if the port is in range/valid if (!inRange(1, 65535, convertedPort)) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Invalid port number, please enter a valid port number."); } else { return new ChatterboxOptions(args[0], convertedPort, args[2], args[3]); } @@ -256,8 +256,13 @@ public void authenticate() throws IOException, IllegalArgumentException { // send messages using serverWriter (don't forget to flush!) // Read and display any messages from the server - userOutput.write((serverReader.readLine() + "\n").getBytes(StandardCharsets.UTF_8)); - userOutput.flush(); + String serverMsg = serverReader.readLine(); + + // Only write the user if there is a message from the server + if (serverMsg != "") { + userOutput.write((serverMsg + "\n").getBytes(StandardCharsets.UTF_8)); + userOutput.flush(); + } // Write the username and password to the server and flush serverWriter.write(this.username + " " + this.password + "\n"); From 202bd60ef510a29232e06e71aa16ddeb85fff1d7 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:08:57 -0800 Subject: [PATCH 12/14] Stop tracking passwords file --- my_passwords.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 my_passwords.txt diff --git a/my_passwords.txt b/my_passwords.txt deleted file mode 100644 index 0332ee1..0000000 --- a/my_passwords.txt +++ /dev/null @@ -1,2 +0,0 @@ -You can add your passwords here and they won't be committed to your git repository. - From eeec7773e6a826a6df6082186c451edcb707cf75 Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:56:51 -0800 Subject: [PATCH 13/14] Removed some redundent code that could be replaced by a helper method. --- src/ChatterboxClient.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 0e2484c..6037539 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -260,8 +260,7 @@ public void authenticate() throws IOException, IllegalArgumentException { // Only write the user if there is a message from the server if (serverMsg != "") { - userOutput.write((serverMsg + "\n").getBytes(StandardCharsets.UTF_8)); - userOutput.flush(); + writeUserOutput(serverMsg + "\n"); } // Write the username and password to the server and flush @@ -274,8 +273,7 @@ public void authenticate() throws IOException, IllegalArgumentException { // Read any messages coming from the server if (serverResponse.startsWith("Welcome")){ // Write the welcome message to the output - userOutput.write((serverResponse + "\n").getBytes(StandardCharsets.UTF_8)); - userOutput.flush(); + writeUserOutput(serverResponse + "\n"); return; } else { throw new IllegalArgumentException(serverResponse); } } From 82b764d2b39f42d29993619b9069625ed19345ef Mon Sep 17 00:00:00 2001 From: AI <182692506+AhmedIhsan123@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:17:48 -0800 Subject: [PATCH 14/14] Removed unneeded import statment --- src/ChatterboxClient.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ChatterboxClient.java b/src/ChatterboxClient.java index 6037539..d0a2276 100644 --- a/src/ChatterboxClient.java +++ b/src/ChatterboxClient.java @@ -9,8 +9,6 @@ import java.nio.charset.StandardCharsets; import java.util.Scanner; -import javax.imageio.IIOException; - /** * A simple command-line chat client for the Chatterbox server. *