Developing a Chat Server (honors hw10h)


Writing the server

To write a server, we will be using the universe form. It is similar to big-bang, and we'll be interested in the following events: new connections, disconnections, and messages.
Here's how we'll be using those events:

Server events

UniverseState

The UniverseState is very similar to the World State for local programs, only that it keeps track of the State of the entire Universe, not just a World. At the very least, the UniverseState will have to contain all the client connections (a.k.a. IWorlds), to be able to send Messages from any client to any client.

IWorld

An IWorld is a datatype internal to the universe teachpack that describes a client connection.
For the purpose of this lab, there is one operation you can perform on an IWorld, which is iworld-name. iworld-name takes an IWorld and returns a String which represents the name of the client in the specific client connection (a.k.a. IWorld).
iworld-name will return, for a given IWorld (a.k.a. client connection), exactly the name specified by the name clause of big-bang in the specific client.

Bundle

A Bundle is a collection of three things:

For our purposes, the list of IWorlds to be disconnected will either be empty (in most cases) or the singleton list (for handling disconnections).
A Bundle is created using the make-bundle function, whose contract is:

make-bundle: UniverseState [Listof Mail] [Listof IWorld] -> Bundle

How the basic chat server works

The server we design will keep track of the connected clients, and any time a client sends a message to the server, which will be a String, the server sends a Mail to each connected client (including the sending client) that contains a String containing both the client's name and the message sent by the client.

To create a Mail value, the make-mail function is used, whose contract is:
IWorld Message -> Mail

For example, if the client with the name "vlad" sends the message "hello" to the server, then each client should receive a Mail value from the server that contains the String "vlad: hello".

In addition, the server should send a Message (as before, a String) to each connected client whenever a client connects or disconnects.

For example, if the client "chadwick" connects, each client will receive the message "chadwick connected.", and if it later disconnects, each (still-connected) client will receive the message "chadwick disconnected."

The basic chat server implementation

We start with a basic server implementation (download). The server that you initially connected to with your "initial client" in lab follows this simple implementation. To launch the server the universe function is used:
		
(universe INITIAL-UNIVERSE
       		(on-msg handle-msg)
       		(on-new handle-new)
       		(on-disconnect handle-disconnect))
INITIAL-UNIVERSE is the first UniverseState, when there are no connected clients.
A good way to test the client-server interaction right after modifications to the client or the server have been done is to run everything on the local machine: the server and a few clients (two is good for starters). The clients will have to specify (register LOCALHOST) in their big-bang form. If everything behaves as expected, you can now test the interaction over a network.

Note: To launch more than one client from the same machine, use launch-many-worlds:

(launch-many-worlds (run "chadwick") (run "vlad"))


Altering the protocol

Right now the simple chat server that we've provided above can only interact with clients that send around Strings as Messages (i.e., clients like the "initial client" we provided you with in lab). You will have to extend this server so that it can handle a Message that is a non-empty list of Strings so your server can interact with the advanced client you developed in lab. As in lab, the first String defines what type of Message is being described, and the meaning of any other strings in the list depend on the type. See Exercises 4 through 7 and Exercise 11 for information on the types of messages you might want to support. (We suggest you also look at the data definitions for incoming and outgoing messages in the "advanced chat server" implementation we provided on the hw10h page.)

To avoid spoofing, the following protocol should be used by the server to communicate to the clients:
When clients send "MSG" Messages to the server, they do not send a <name>—the server adds the appropriate client name before sending the messages to clients. In other words, the only Message sent from clients to the server at this point is (list "MSG" <msg>); the other Messages are generated server-side for connections and disconnections. For other, later extensions, the server should add names as appropriate to Messages.
We suggest that in future extensions, the second position in the list (i.e. after the Message type) is reserved for the client name, so that adding it is a uniform operation.