Instant Messaging (or internet chat) has always been an intriguing technology. Most of the current IM systems seem to support great one-on-one chat. However, when it comes to chatting together with multiple people, IRC is the only thing that comes to rescue. Most chatroom based IM services on the internet basically exist for this big online dating market. AIM and Yahoo don't support creating new permanent groups which can be accessed form the popular chat clients available. Now, IRC is good. However, one of my friends who is not into this big messy world of the internet and doesn't care much about the details about computers and networking, once asked me this question.
Both, you and I have a computer with us. These are not small computers but big powerful laptops! If I want to chat with you online using this big bloated chat client, why do I need to connect to this other server to be able to chat with you? Don't you think these things should be more direct?
In some sense, I had to agree with him. Simplicity does have its merits and this commercial (or service oriented) IM scene looks more than dismal to me.
Importance of a 'chatroom'
Often we come across this scenario of a group of people who work together (which means that they reside on the same network) who would like to participate in a (low traffic) chat among all of them on their network. I have seen one organization (CAIDA) which does this and see this need in many other such small communities. I am a graduate student and I think such a chat room based communication system would rock in our work environment. I could use IRC but I would prefer a solution which keeps in-house traffic in-house. Plus, the concept of a central chat server keeps reminding me of this central server dilemma my friend put me into. So I thought I would search for a solution.
I had been hearing about jabber (and how cool it is) and how it is making inroads into the enterprise market where a private chat system is desired inside the company. Even though this thing was a server client architecture I decided to give it a try. However, jabber proved to be quite a beast. Even if I had the persistence, I would not have been able to justify the bloat in clients for the jabber protocol when the server is already that complicated. Plus, I knew that if this jabber room thing caught on in my work environment, it would be hard to back out from managing the server (which I was sure I didn't want to do after some time). I yearned for something simpler, easier to manage and more transparent.
The UNIX Chatroom idea
Let's come to the main idea of the article. Chat is not complicated. It involves three things.
- It involves creating 'rooms' and 'members'. This also involves handling access control.
- It involves sending one's chat message to all the members in a given chat room.
- It involves receiving chat messages from the different members in a chat room and displaying them to the user.
Plus, any added UI fluff (let's not focus on that right now).
A UNIX system already has users with logins on a central machine. So the members part of the puzzle above is already somewhat solved. The chat client to be used is whatever client you use to access the UNIX machine (in sane cases it will be ssh). What's a chatroom? Abstractly speaking its a collection of users right? What's the most easy way to make a collection of something in UNIX? A directory! So let's say that we have this directory called /chatrooms/room1, /chatrooms/room2 etc for the various chat rooms. Now comes the non-intuitive leap part of the solution. To join a room, the user creates a named pipe (with the name equal to the desired screen name) in the room directory. Thus, chatroom directories contain named pipes for all the users in the chatroom and the owner of these named pipes are the users themselves (for access control). UNIX access control in directories and files is used for access control in registering and joining rooms. See how easy it is to search the members 'directory'? See how easy it is to deny somebody from seeing a chatroom's members?
To receive messages, the user reads from his named pipe and displays it. It is important for the user to keep read permissions to this pipe only to him/herself so that other users cannot read from this named pipe.
To send messages, the user has to basically get a line from the standard input and write it to all the named pipes in the chatroom directory. If a particular user is not currently reading from his named pipe then that user is assumed to be offline. The message sending user detects this from the error in sending his message to the other users named pipe. Thus 'presence' information is automatically inferred. Note however, that if we want to have presence information at a much finer timescale than the chat timescale, we will need to poll the named pipe of the other user using a no-op. Note that this scheme allows the sender to completely control the formatting of the message without any requirements on the other user.
Blocking users is not possible using simple UNIX access control. However, with acls etc, any a per user blocking scheme could be implemented by removing the write rights of a blocked user from one's named pipe.
This basically completes all the features of a typical IM system. For things like status messages, a file named (screenname).status should be enough. Its upon your client to interpret this. Very importantly, the client only focuses on the UI and the client is present on the server which makes deployment as easy as cakewalk. I think a prototypical python script for a UI on the stdIO would not cross 100 lines.