I have started a document (available at http://sourceforge.net/docman/display_doc.php?docid=1098&group_id=12069\) which lists some of the issues with distributed authentication. I hope to get some feedback from whoever has some to offer.
Hi taso, great job u've done here I must say. Although I am still a new java programmer please permit me to make a few suggestions as to how to solve the distributed chat problem.
1. On the distributed chat, usernames should be qualified with the name of the server that authenticated them.eg <i>Server.User</i>
2. Each server should keep a list of all users grouped by the servers that authenticated them.
3. If a user wishes to join a non-local room and their is a name collision, the user should be forced to choose an alias.
I have to agree with bubus, adding the server name will also enable booting and banning from remote systems.
Another idea is to allow only one a a specific user name in a chat system or should I say a closed chat system. You could accomplish this by having each server pass state information (more work that the server has todo) or have a standalone state server that just monitors who is online. Note that in an authentication world the database will need to be contacted inorder to authenticate someone, the overhead in registering with another server should be small. These could even be done via HTTP and a servlet or a staic connection. The HTTP solution has extra overhead in returning the results but it reduces the number of open connection in the system.
I'd love to talk about this some more so let me know what you are thinking.
Prepending the server name certainly would help iron out ambiguity, but I think it might be too cumbersome to have to qualify users' names. What I am striving for is to make the distributed backend transparent to the user. The whole network should really look and act as though it was one big server. Which means, that duplicate names really shouldn't be allowed at all.
Currently, there is a class in the server called DistributedState. That class is really a facade that uses two other classes, RoomTable and ServerTable. NFC servers do pass their state around. At any point in time, all the server's DistributedState should contain the same info. So in most cases (when all the nodes are up and running), the "name collision" problem is avoided.
Now, the issues come in when one server becomes detached from the rest of the network (due to router failure, network failure, or whatever). During this disconnected period is when two users with the same name can potentially log on to two servers which are detached from one another.
Currently nothing is done to avoid this. Here is the basic exchange:
- A server (re)attaches to the rest of the network, and it broadcasts its current user and room lists to the others.
- The other servers, in turn, broadcast their own user and room lists
After this exchange (not optimal, but that's whole other story :), each server knows the state of the whole system.
What I am thinking is that during a user list exchange, the servers should be able 'negotiate' user lists with each other instead of just blindly sending them. For instance, maybe the user who was signed on first should "win". Or, in the case of distributed authentication, an authenticated user should always win over an non-authenticated user. (We'll have to nail down the exact criteria)
If you are the loser of such a negotiation, the server will then put you into a "change-your-name-or-die mode". Until you change your name, your name will not be published to the other servers.
This means that NFC is going to need a "change-your-name" command, which it currently doesn't have. I think given the circumstances, it's worth doing.
What do you guys think of this so far?
P.S., I sort of purposely ignored the issue of authentication and whether admins on one server should be allowed to /kill users on a remote server. I want to work on somehow abstracting the actual policy used, such that people who create their own NFC network can define their own policies (there's room for more discussion here too).
My thought is that the back-end is just what it is a back end. String messages don't have to be passed but Serialized Objects could be passed that contain the information about the object. This way the JVM will control packing and unpacking of the objects. You can now send lists of objects in stream on the back end server to server communication.
-Example server comes online... (how does it know which other servers there are?)
-Gets RMI interface for each server and broadcasts its user and room lists to these servers. Note what is being passes is a Hashtable or something.
-Sends its Current state information to each of the servers.
If you have a single registration server that keeps track of the users currently in the system and where they are then you have a single point of collection for user information. This could be very light weight only contacted for users entering and leaving the system.
Now your interesting point about a server becoming detached from the system. When a server becomes detached from the system it should prevent login's to that server. Until the room can re-connect with the other servers users will only be able to chat in rooms that are present on that server.
The other issue is that when the server becomes disconnected most likly users are chating in rooms. Are you thinking that you want to put users back into the rooms that they where chatting in? If so this brings up another issue of state handling for the room when the server reconnects.
hmmm... the more I read into what you are saying is that users can only chat in rooms that are on the server that they are on. If rooms can be tagged just like users name@host then you could have rooms and users on different servers talking to each other. Each user has a home server. Each room has a home server. The information that is shared amoung servers is users and rooms with thier locations.
I do like the change-your-name feature, also included is a move-to-server feature.
Sorry if you can't make heads or tails of this. I'm very tired right now.
I've considered RMI and rejected it. The backend is, after all, a messaging system, so publish/subscribe via JMS fit the bill much nicer.
> -Example server comes online... (how does it know which other
>servers there are?)
It's handled by the protocol. There is a more-or-less accurate protocol doc at http://nfcchat.sourceforge.net/doc/protocol.html.
> -Gets RMI interface for each server and broadcasts its user and room
> lists to these servers. Note what is being passes is a Hashtable or
This is iterative logic and takes time. Instead, I send out just ONE JMS message, which the router is happy to distribute to all the subscribers for me. Note that it is quite possible to put real Objects like Hashtables into a JMS message, but this would add more overhead. The message distribution and parsing is NOT the part that's broken here! :)
> -Sends its Current state information to each of the servers.
Again, handled by JMS.
Things like RMI and CORBA are great, but for the purposes of a messaging server, which typically just wants to send a message and forget about it, JMS is a better fit. Not to mention that JMS handles routing effeciently.
> If you have a single registration server that keeps track of the users
> currently in the system and where they are then you have a single
> point of collection for user information. This could be very
This also a single point of failure! I don't like this at all. I think going with the distributed state that I have now was much better solution. Do you disagree?
> hmmm... the more I read into what you are saying is that users can
> only chat in rooms that are on the server that they are on. If rooms
> can be tagged just like users name@host then you
> could have rooms and users on different servers talking to each other.
> Each user has a home
> server. Each room has a home server. The information that is shared
> amoung servers is users and rooms with thier locations.
No, not quite. Users do have "home server", but rooms do not. When a detached server re-connects to the network, all of the rooms are effectively merged together.
I think we should just introduce a concept of local and global users, with a central registration point for global users.
Once 2 or more servers are networked, there is no distinction between local and global users, at least from a user's perspective.
We already have distributed (non-centralized) state management, and it works. Centralizing it would complicate matters (because then we have to worry about electing a new state manager if a node becomes detached, among other things).
Hello... new here... but how about something like this. You could *possibly* solve this issue of distributed server... and "awareness transparency" with something like xmlBlaster (http://www.xmlBlaster.org) its a MOM, but has excellent facilities for network failures... and (and if you hadn't guessed) it's messages are all XML... which provides a great deal of flexibility in what a message looks like.
I could almost see NFC acting as facilitator between the core MOM and the clients using a Pub/Sub model. I understand... and have been playing with the JMS capabilities (using swiftmq) of NFC... but xmlBlaster uses corba which is a bit more portable.
The drawbacks would be that a full blown MOM (like xmlBlaster) is rather cumbersom to configure and get up and running.