Skip to content

Releases: 0xGhazy/quick-chat

Mini-Discord v1.0

10 Jul 09:13
Compare
Choose a tag to compare

Mini-Discord is a multi-threaded console Java application that handles multiple client requests and conversations simultaneously. This is the version I have submitted as an assessment to apply as a junior Java developer at @Mokalamat company.

banner

Mini-Discord

Java

Overview

Mini-Discord is a multi-threaded console Java application that handles multiple client requests and conversations at the same time. it consists of main two parts Client Application and Server Application. In the following section, I'll describe how they work internally and show the features with screenshots.

About the server

Overview

server

The server is the main part of the Mini Discord application. it starts to listen on the specified port and connect with clients to handle communication and requests.

the most important role of the server is handling multiple requests simultaneously, each client has its own Client Handler which is responsible for sending and receiving messages, and commands from and to the client.

What happens under the hood?

  • A new client opens the client from its end, this will inform the server that a new lobby client is active now.
  • The server will accept the new client request, then create a new client handler and start a new thread for this handler and start it.
    // ---- code snippet ---- 
    Socket clientSocket = serverSocket.accept();
    // generate a temporary name for lobby clients.
    String tempUsername = "lobby-client-" + DateTimeHandler.timestampNow();
    logger.logThis("info", "Listening for client requests. . .");
    logger.logThis("request", "A new lobby client request is accepted");
    ClientHandler clientHandler = new ClientHandler(clientSocket, tempUsername);
    Thread thread = new Thread(clientHandler);
    thread.start();
    // ---- code snippet ---- 
  • By Client handler constructor take the socket, and username as arguments to initialize the client handler object by setting the username for this, and the most important role here is to add this -newly created- to the clientsList which hold all current active handlers.
class ClientHandler implements Runnable {

    /* ---- code snippet ---- */

    // shared by all handlers
    private static ArrayList<ClientHandler> clientsList = new ArrayList<>();

    public ClientHandler(Socket socket, String username) {
        try {
            this.socket = socket;
            this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.username = username;
            clientsList.add(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /* ---- code snippet ---- */

}
  • By starting the client thread, it will trigger the Overrided run method from the Runnable interface. which will handle the incoming client requests by the specified flag in the request message.

  • Each client request to be handled by the handler must consist of FLAG, DELIMITER, and PAYLAOD. handler will parse it choose which function will be executed and replay it to the client.

Parsing incoming commands from the client:

    // reading commands from the client side.
    command = bufferedReader.readLine();
    String[] commandArray = command.split(Settings.DELIMITER);
    String flag = commandArray[0];
    String payload = commandArray[1];

Choose which function will be executed:

    if(flag.equals("[RESET]")) 
    {
        logger.logThis("request", "Reset password request is captured");
        Credentials credentials = credentialsService.deSerialize(payload);
        String username = credentials.getUsername();
        String password = credentials.getPassword();
        // hashing the new password
        password = HashingService.getSha256(password);
        String result = databaseAPI.updatePassword(username, password);
        logger.logThis("info", "Account updated [" + result + "]");
        sendMessage(this, result);
    }

Internal flags

The clients send the user message that applies the following structure

FLAG DELIMITER PAYLOAD

Note: No spaces between them, for example of [VALIDATE] usage.

[VALIDATE]>hossam
   |      |    |
   |      | (Username)
   |  (DELIMITER)
 (FLAG)

Here is a list of all available and handled flags on the server side with their descriptions.

Flag Server usage Followed By
[SIGNUP] Signup a new user Serialized User object
[LOAD] Read the user from the database then return it to the client Username
[RESET] Reset user password Serialized Credentials object
[VALIDATE] Validate if the username is exist in database Username
[UPDATE] Update the user words and conversations Serialized User object
[SNAPSHOT] Ask the server to return conversation Username
[AUTH] Authorize user in login process Serialized Credentials object
[JOIN] Add user to the chat room Username
[BROADCAST] Send message to all peers in chat room "{sendername}~{message}"
[LEAVE] inform all users a member has left Username

Server project directory architecture

Files in Description
database The database API responsible for dealing with the database and tasks such as adding new user, update user statistics, etc.
model the main object classes that the server and the client exchange together
server contains the server backend logic such as running the server, and handling incoming requests
service all needed functionality by the models such as serialization, deserialization, and hashing function
utils all utility functions such as logging, colored output, banners, etc.
Settings.java all settings needed by the server is here such as port, host, database connection, etc.

Features & Screenshots

  • Secured stored credentials
    All confidential data is stored hashed in the database using the SHA256 algorithm. from guava library

hashed passwords

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>32.1.3-jre</version>
    </dependency>
public static String getSha256(String plainPassword) throws NoSuchAlgorithmException {
    return Hashing.sha256()
                .hashString(plainPassword, StandardCharsets.UTF_8)
                .toString();
    }
  • Logging events
    I have implemented logging events handler /utils/Logger.java to enable logging events and verbosity to make it easier to know what is happening right now with each event.

server ver

  • Settings class
    in the Settings.java you can specify the settings of the server such as the following.
public class Settings {
    public static final Integer PORT = 5000;
    public static final String DATABASE_USERNAME = "_USERNAME_";
    public static final String DATABASE_PASSWORD = "_PASSWORD_";
    private static final String DATABASE_NAME = "DATABASE_NAME";
    public static final String DATABASE_URI = "jdbc:mysql://localhost:3306/" + DATABASE_NAME;
    // this property must be set in the client too
    // it's the DELIMITER between flag and payload.
    public static final String DELIMITER = ">";
}

About the Client

Overview

carbon

The client is the second important part of the application, by running the client it will try to connect to the server on the specified host and port number in the Settings.java. seeing the prompt means you can ask the server for the actions you need in your current mode.

The client has 3 main modes:

Mode Description How to active?
Lobby The default mode when opening the client default
Active The mode loaded after login, your profile is loaded here to be ready for dumping /login
Chatting Mode in the chat room, in which you send messages to all peers /join

Use /help to get the current available commands for Lobby, and Active modes.

Client project directory architecture

Files in Description
model The main object classes that the server and the client exchange together
network Connection handlers such as client connection handler, and message listener
service All needed functionality by the models such as serialization, deserialization, hashing, reporting functions
ui All ui modes a...
Read more