404 Not Found

nginx/1.18.0 (Ubuntu)

The Server Architecture of IM++

404 Not Found

404 Not Found

nginx/1.18.0 (Ubuntu)
The design for the IM++ system server was designed to be as simple as possible, but at the same time highly extensible: there should be little difficulty in adding functionality to the server, through normal Java mechanisms. In addition, because the server executable itself could not be an interactive program, the server had to be designed to be manipulated as easily and fully as possible by a remote mechanism. Thirdly, the server, and the entire communications system in general, had to be designed as securely as possible, in order to prevent any possible compromises to the system by malicious external users.

Server Architecture Outline

User Information

The server requires a mechanism for storing the personal data for its users. This information, for each user, is entirely stored within the class:
This class contains the following data: The server stores this information for each registered user. Since sensitive information is contained in this object, it is not transmitted across the network; it contains a method which generates a transmissible and non-sensitive object.

Buddy Information

Intuitively it would seem that a Buddy List should be just a list. However, that does not allow for the grouping of buddies. A tree is an alternate solution, but this allows for potential problems, such as multiple inclusion of users. Instead, since each user should only be included once and should be associated with only one group, a hash table is used, with the keys being the users in the buddy list and the values being the group names (which are of type String).

Additionally, it is useful to keep a list of users who have a given user on their buddy lists. For example, when the server notifies users that a buddy has logged out, only users who have that user on their buddy list need to be notified. Since it is not necessary to associate group names with those buddies, a Set is used.

Account Creation

Creating an account presents a problem to the system, do to its overall asynchronous nature (see general architecture). Additionally, it requires that the server accept a connection for a user without the connector's identity being known, which presents both algorithmic and security issues. In order to work around these problems, the connection for creating accounts is run through another port, which is (for the purposes of this program) always one less than the port number for the server. A "manager" thread handles incoming connections. The classes containing these threads are:
These classes use a highly primitive and insecure protocol, and it is suggested for future developers that they update these classes.

Authentication Systems

The server requires a method for authenticating users when logging on to the server. Again, because of the asynchronous nature of the overall system it is difficult to establish an authentication protocol. For security purposes, the server uses a challenge-response system so that the password is never visible: the server sends a random string, the client appends the string to the password and produces a one-way hash, and the server compares the received value with its own hash calculation.

In this program's implementation of that algorithm, the server immediately sends the random challenge to the user and places that user's receiving thread (see below) into a "waiting pool" of unauthenticated users. All messages except for the authentication response are ignored. Once an authentication is received, it is checked for validity; if it is accepted the user is placed into the "active pool" and removed from the waiting pool; otherwise the user is logged off.

While this mechanism is fairly efficient, it does suffer from the one problem that it is possible for a malicious user to overflow the waiting pool by establishing connections which are never completed. Future developers may wish to implement a "cleanup" thread which removes threads from the waiting pool after a timeout period.

Communications Threads

Every time a client connects to the server, the server creates a thread to handle the incoming and outgoing messages. This is generally through an instance of the class:
which is described in the overview page. The messenger objects are hashed against the user names after being authenticated. When a message is received, the thread looks up the receiver's messenger object and redirects the message (hence the name ServerRouter). Special steps are taken if the message is being sent to the server or if the recipient is not online or away.

Command Execution

Commands are normal messages sent to the user named "Server." When the messenger thread for that user receives a packet intended for the server, it sends it to the server's instance of the class:

Normal User Commands

The command parser contains hashtables with the first word of the command being the table key and the value being an implementation of the class:
The command parser looks up the first word in the string, matches it against a key in the hash table, and calls the associated executable class. The user is returned some Serializable object which is to be used as the return value of the command, as well as the command itself, in an object of type:
Two especially useful commands for all users are ls, which lists all the user commands, and man, which provides information about a command (through its toString method).

Although the current implementation will respond to a command immediately after receiving the request, this should not be considered guaranteed. Future developers may wish to make the CommandParser into a queued thread, so that the server cannot be overloaded with command requests.

Superuser Commands

The superuser is provided with a number of server-manipulation commands which are not accessible by regular users. They are documented in the javadoc file for CommandParser.

Event Mechanisms

The server fires events to notify users of changes in status. These status changes are always related to some user, and they are encapsulated in the class:
These events include a user logging on, logging off, changing away status, and sending a broadcast message.

Server Listeners

The server will first notify all registered ServerListeners of the change event. These listeners are registered with the server and of type:
This is useful for implementing items such as an event log.

There is not yet a mechanism for installing a server listener during the execution of the program. To do so would be fairly simple; it should follow the model of the load command available to the superuser.

User Notifications

When a user causes an event to be fired, only users who have listed that buddy as a user will be notified of the event. This prevents users who have no interest in that user from being notified excessively of events. The event notification will be sent as type:

Server Persistence

When the server shuts down, its state is saved into a file specified upon running the program. The hash table of user information is written by Java serialization to disk.

This presents a major security problem: since the passwords are unencrypted on the server, they may be easily accessed through the serialized state. Future developers may wish to consider the possibility of either encrypting the passwords in the server itself or encrypting the output file.

Security Considerations

In a world of computer hackers, it is necessary to consider security issues whenever writing a program which opens itself to network connections. Most of the security measures in this program have involved privatization of class fields and constructors. For example, packets which are generated by the server have package-private constructors, to prevent external programs from spoofing packets. However, there has been no detailed analysis of the security of this system. Generally this program has preferred extensibility to security, but the option for future developers to make this system much more secure has been left open.

Additionally, communications are not encrypted. A simple improvement that could be made by developers knowledgeable in encryption would be to encrypt the contents of packets. Since the server never reads the contents of a packet--it just routes it--the packet's contents could easily be secured.

404 Not Found

404 Not Found

nginx/1.18.0 (Ubuntu)