Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions my_passwords.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
You can add your passwords here and they won't be committed to your git repository.

Passion1218!
221 changes: 208 additions & 13 deletions src/ChatterboxClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

import java.net.Socket;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/*
Worked on WAVE 1 - 7
MOST OF MY COMMENTS BEGIN WITH NOTE, some dont have but the main ones
have NOTE
*/


/**
* A simple command-line chat client for the Chatterbox server.
*
Expand All @@ -32,12 +43,12 @@ public class ChatterboxClient {
private String password;

// Streams for user I/O
private Scanner userInput;
private OutputStream userOutput;
private Scanner userInput; // for reading user input
private OutputStream userOutput; // for printing to user

// Readers/Writers for server I/O (set up in connect())
private BufferedReader serverReader;
private BufferedWriter serverWriter;
private BufferedReader serverReader; // for reading from the network socket
private BufferedWriter serverWriter; // for writing to the network socket

/**
* Program entry.
Expand Down Expand Up @@ -124,12 +135,45 @@ public static void main(String[] args) {
* @return a fully populated ChatterboxOptions
* @throws IllegalArgumentException on any bad/missing input
*/


// This is Wave 1 --> for the command arg lines
public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentException {
// TODO: read args in the required order and return new ChatterboxOptions(host, port, username, password)
// 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");

// NOTE: We need 4 arguments of validation for the program
if ( args.length != 4) {
throw new IllegalArgumentException("Expected 4 arguments: HOST PORT USERNAME PASSWORD");

}

//NOTE: The expeced order based on the required argument order
String host = args[0];
String portString = args[1];
String username = args[2];
String password = args[3];

int port;
try {
// NOTE: This is for converting the portString to Integer
//Its required coz the PORT is numerical
port = Integer.parseInt(portString);
} catch (NumberFormatException e) {
// NOTE: It rhrows when the string isnt a valid numnber
throw new IllegalArgumentException("The port has to be a valid integer.");
}

if (port < 1 || port > 65535) {
throw new IllegalArgumentException("Port must be between 1 and 65535.");
}

return new ChatterboxOptions(host, port, username, password);
}

// this is WAVE 2 --> Adding constructors

/**
* Construct a ChatterboxClient from already-parsed options and user streams.
*
Expand All @@ -143,12 +187,25 @@ public static ChatterboxOptions parseArgs(String[] args) throws IllegalArgumentE
* @param userOutput stream to print data to the user
*/
public ChatterboxClient(ChatterboxOptions options, InputStream userInput, OutputStream userOutput) {
// NOTE: THE utf 8 is for the character encoding
// NOTE: the userinput gets the input then the chat starts
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");
// NOTE: add // on line 196-> so it removes the red scuiggle line in line 188
// throw new UnsupportedOperationException("Constructor not yet implemented. Implement ChatterboxClient constructor and remove this exception");
// TODO: copy options.getHost(), getPort(), getUsername(), getPassword() into fields
}

// NOTE: In the this.host (line 202 - 205) the constructor just saves the data
// into the client's memory for them to be used with other methods
this.host = options.getHost();
this.port = options.getPort();
this.username = options.getUsername();
this.password = options.getPassword();
}



/**
* Open a TCP connection to the server.
Expand All @@ -163,12 +220,40 @@ public ChatterboxClient(ChatterboxOptions options, InputStream userInput, Output
*
* @throws IOException if the socket cannot be opened
*/

//THis is wave 4 --> Connect

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
}

//FRED: --> WAVE4 PART
// NOTE: Added socket connection
// NOTE: The socket line makes the call --> then establish connection
// if server's not there rhe exception is throen
// NOTE: The socket initializes the connection to the specified host and port

Socket socket = new Socket(this.host, this.port);

// NOTE: Create UTF-8 input reader
// NOTE: the socketgetinputstream --> gets the byte stram from the netword
// NOTE: the inputstramreader changes the raw bytes to readable UTF 8 Texts
// that we can read
InputStreamReader inputStreamReader =
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8);
this.serverReader = new BufferedReader(inputStreamReader);

// Create UTF-8 output writer
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
// NOTE: The buffered writer helps send the text to the server -->
// kinda like an outbox in gmail
this.serverWriter = new BufferedWriter(outputStreamWriter);
}



/**
* Authenticate with the server using the simple protocol.
Expand All @@ -190,10 +275,53 @@ public void connect() throws IOException {
* @throws IOException for network errors
* @throws IllegalArgumentException for bad credentials / server rejection
*/

//THis is wave 5 --> Authenticate
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!)


// NOTE: Read users prompt if there is
String prompt = serverReader.readLine();
if (prompt == null) {
throw new IOException("Server disconnected before authentication prompt.");
}

// NOTE: Prompt sent to the user
// NOTE: The getBytes() --> changes tect into bytes to be sent
// to the outstream
userOutput.write((prompt + "\n").getBytes(StandardCharsets.UTF_8));
userOutput.flush();

// NOTE: Send username and password as required by the server
String loginLine = username + " " + password;
serverWriter.write(loginLine + "\n");
// NOTE: The flush() sends it to the server directly for the login attempt
serverWriter.flush();

// Read server response
String response = serverReader.readLine();
// NOTE: If response is null, server disconnects
if (response == null) {
throw new IOException("Server disconnected during authentication.");
}

//NOTE: server's response to the user
userOutput.write((response + "\n").getBytes(StandardCharsets.UTF_8));
userOutput.flush();

//NOTE: if successful, you get welcome, if not an exception is thrown
if (response.startsWith("Welcome")) {
} else {
// NOTE: Failed authentication throws an exception
// if the main method catches the exception it directly exits the client
throw new IllegalArgumentException(response);
}



}

/**
Expand All @@ -208,8 +336,50 @@ public void authenticate() throws IOException, IllegalArgumentException {
*
* @throws IOException
*/

// this is for wave 6 & 7 --> Chat streaming
public void streamChat() throws IOException {
throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!");
// throw new UnsupportedOperationException("Chat streaming not yet implemented. Implement streamChat() and remove this exception!");

// NOTE: in this wave, the incoming thread runs the thread printincomingchats everytime
//thus helps the client can then keep reading the messages of the server
// The lambda makes the thread shorter and cleaner. (eg line 351 with ->)


//ADDED THE PRINT CHATS FOR WAVE 6
// printIncomingChats();

// updated the printincoming chats and added the try method
Thread incomingThread = new Thread(() -> {
try {
printIncomingChats();
} catch (IOException e) {
// When server disconnects, this will throw the exception and
// the thread ends there
}
});

Thread outgoingThread = new Thread(() -> {
try {
sendOutgoingChats();
} catch (IOException e) {
// Writing failed (server likely disconnected)
}
});

// NOTE: Both of these start at the same time
incomingThread.start();
outgoingThread.start();

try {
// this tells the main thread to wait until its done reading messages
incomingThread.join();
outgoingThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}


}

/**
Expand All @@ -226,9 +396,20 @@ public void streamChat() throws IOException {
* - If an IOException happens, treat it as disconnect:
* print a message to userOutput and exit.
*/
public void printIncomingChats() {
public void printIncomingChats() throws IOException{
// Listen on serverReader
// Write to userOutput, NOT System.out

// WAVE 6 continuation:
String line;
// NOTE: As long as the readline is not null, the loop continues
// as long as there are readlines or texts added. It will continue reading
while ((line = serverReader.readLine()) != null) {
//
userOutput.write((line + "\n").getBytes(StandardCharsets.UTF_8));
// NOTE: Flush so the user sees the message ASAP
userOutput.flush();
}
}

/**
Expand All @@ -243,10 +424,24 @@ public void printIncomingChats() {
* - If writing fails (IOException), the connection is gone:
* print a message to userOutput and exit.
*/
public void sendOutgoingChats() {
public void sendOutgoingChats() throws IOException{
// Use the userInput to read, NOT System.in directly
// loop forever reading user input
// write to serverOutput

// WAVE 7:
while (true) {
// NOTE: This is to check if there is anothe rline to read
if (!userInput.hasNextLine()) {
break; // if not found break and exit
}
String message = userInput.nextLine();
serverWriter.write(message + "\n");
serverWriter.flush();
}



}

public String getHost() {
Expand Down