Contents
It is a simple program that allows multiple users to connect to a server and communicate with each other.
Each user can perform six functions :
- create an account
- view existing accounts
- send a message
- read a message
- delete a message
- view their inbox
The Server.java file contains the server code. Τhe server is implemented using RMI.
In order to run the Server, you need to provide a single argument which is the port number. If there is more or less than one argument the program exits.
The Client.java is the client file.
When running the client the arguments vary, depending on the function you are performing.
Function ID 1 (create account) : <ip> <port number> 1 <username>
Function ID 2 (show accounts) : <ip> <port number> 2 <auth token>
Function ID 3 (send message) : <ip> <port number> 3 <auth token> <recipient> <messsage body>
Function ID 4 (show inbox) : <ip> <port number> 4 <auth token>
Function ID 5 (read message) : <ip> <port number> 5 <auth token> <message id>
Αrguments are considered invalid only if their number is less than four. The trust is placed on the user which is the reason why the arguments' order is not examined any further. Necessary checks are performed only on the auth token, and on the username (FN ID 3), provided that they are in the right place. There is one more check for the function ID, given that it is in the correct position, to have a value between 1 and 6.
Once all these arguments have passed the check and depending on the function ID, the client requests from the server the propper function. The response is returned and printed on the client's side.
Funs is the common interface of both the Client and the Server.
In Functions_Server.java the functions declared in the interface are implemented. Users are stored in a Hash Map to reduce the complexity of some searches that need to be done.To give each message a unique id (message id), there is a counter counting the total number of sent messages. The id each messages gets is the value of the counter at the moment the message is sent.
A user requests to create an account with a desired username. This function checks if the desired username is available and valid. A username is available if there is no other user named after it. A valid username is one consisting only of alphanumeric characters but can also contain underscores
Due to the limited auth tokens available, there is an additional check that determines if the number of users has reached the maximum number of auth tokens, which needs to be done to avoid the infinite loop at the generation of the auth token.
If the username is valid and available it returns the auth token that refers to the user, if the username is taken it returns -1 as auth token, and the message Sorry, the user already exists is printed, if the username is invalid it returns -2, and the message Invalid Username is printed and if there can be no more unique users because all the 4-digits auth tokens have been generated it returns -3 and the message Sorry, unable to create new accounts is printed.
Simply returns an array containing every user's username. These usernames are printed in the Client.
Allows a user to send a message to another user. Both users must be registered. A user is allowed to send a message to themselves.
Also, the message body can be empty but the message body argument should not be omitted, there is no check for that.
To send a message, a Message object must be created first. By default every message is considered not read. Then, in order to add this message to the user's inbox, we create a copy of the user, add the message to the copied user's inbox, and replace the user with the updated copy.
When a message is successfuly sent, the message OK is printed, any other message indicates the problem that occured while trying to send the message
Prints the user's inbox. A user is authorised to view only their inbox.
The function returns an arraylist of strings, of every message in a specific user's inbox. The messages are in the following format:
message_id. from: sender
followed by '' in case the message is not read yet.
message_id. from: sender
In case of an empty inbox, it returns an empty arraylist.
With the read message function you can mark a message as read. Basically it allows a user to change the isRead value of a specific message from false to true. Although if a message is already read, the user can "re-read" it and there will be no change. Returns a string of the message, in the following format:
(sender)message body
If a user tries to read a message that does not exist or exists in another user's inbox then it returns Message ID does not exist
Allows the user to remove a message from their inbox, by providing the message's id. A user is not allowed to remove messages from another user's inbox. If the message is successfuly deleted it returns the string OK. If the message is not in their inbox, then it returns Message does not exist. The returned string is printed in the Client.
Apart from the above six user functions there are also some assistive functions. These are:
- The function that checks if a provided username is valid. This function is used localy, only when a user tries to create an account to check if the username he provided is valid. A valid username, as stated earlier, consists of alphanumeric characters and can contain underscores. Empty strings are not accepted, the username must at least contain an alphanumeric character or an underscore.
private static boolean is_valid_username(String s)
- The function that creates the auth token. This function generates a random number between 1000 and 9999. For this project, it is accepted that the auth token is a 4-digit number. This number must be unique, and to be so, there is a while loop that generates a new random 4-digit number for as long as there are collisions with existing auth tokens. Then, it returns the token.
private int generate_unique_auth_token()
- The function that finds a message with a specific message id in a given inbox. It is used localy when a user tries to read/ delete a message, and it returns the index of the message in the array list that represents the inbox or -1 if the message does not exist in the specific inbox.
private int find_message(int message_id, ArrayList<Message> inbox)
- The function that checks if a username belongs to an existing user. This function is used localy when an account is created and in the Client when a user tries to send a message to another user by providing their username, where it checks the provided username.
public int check_username(String username)
- The function that checks if an auth token belongs to an existing user. This function is used in the Client for every function apart from the FN ID 1.
public int check_auth_token(int auth_token)
Every user registered in the system is represented by an account. It stores the username, the auth token and the inbox that corresponds to every user in the system. Apart from the getters and setters for these properties, there is a function to add a new message in the user's inbox and one to remove a message from a user's inbox.
The message class, represents the messages which users interact with. For every message in the system we must know the sender, the receiver, the content of the message (message body), the id of the message and whether the receiver has read it.
In order to create the printing template requested by the task instructions, when the user wants to read his inbox or when the user wants to read a message, there are two functions.
The function,
public String show_message_inbox()
returns this template which is used when a user wants to see his inbox
message_id. from user
and the function,
public String show_message_read()
is used when a user wants to read a message in his inbox.
(sender)message_body
Eleni M.
(^)