keith thompson

tales from the darkstar


« Previous month (May 2009) | Main | Next month (Jul 2009) »
Monday Jul 27, 2009

Of protocols and transports

As mentioned in my previous post I worked on the Darkchat server which was going to be demoed and used at JavaOne 2009.  The server would be on the public network so that attendees could access it during the convention. For this to work we needed to to be able to limit logins to authorized clients (JavaOne attendees). The details of creating and distributing account usernames and passwords were being worked on and early-on it looked like we would have a way for attendees to register for an account, and for them to create a username and password (the final solution was way cooler than this scheme, perhaps a story for later). The default protocol and transport that comes with Darkstar provides very little security for client logins. The Simple SGS protocol sends usernames and passwords in the clear over TCP. I was concerned that passwords could be snooped (humm.. a conference full of computer geeks, what were the chances? - for answer see below1) and though this was only a demo, what if someone used an important password thinking that it was being protected. In looking at the options and the time that was available two solutions seemed possible, to create an SSL transport to replace TCP, or create a new protocol that included some level encryption. To me, creating a new protocol seemed the easier of the two.

In the Darkstar server are two services that handle the bulk of the communication duties with the client, the client session service and the channel service. These two services implement the most of the ClientSession and Channel semantics that the application sees. They are built on top of a protocol layer. This layer determines the format and content of the messages exchanged between the client and the server. The protocol layer is, in turn, built on top of a transport layer. The transport layer deals with the network connection with the client.

The protocol layer is defined by the interfaces in the com.sun.sgs.protocol package in the Darkstar Server Internal API sub-project.  The protocol implementation is configurable at server runtime through the session service property:

com.sun.sgs.impl.service.session.protocol.acceptor

The property must refer to a class which implements the ProtocolAcceptor interface. The implementation class must also have a public constructor which takes the following arguments:

java.util.Properties
com.sun.sgs.kernel.ComponentRegistry
com.sun.sgs.service.TransactionProxy

The ComponentRegistry and TransactionProxy objects provide access to the components within the Darkstar kernel such as the data service or the task scheduler.

The ProtocolAcceptor object is responsible for initial client connection and login, including authentication. The client session service registers its interest with the acceptor by calling accept(), passing in a ProtocolListener object. When a successful client connection and login is made the acceptor should call ProtocolListener.newLogin() passing in the authenticated Identity of the client, a SessionProtocol object, and a completion handler. It is the SessionProtocol object which implements the outgoing messages needed by the session and channel services. The implementation must be able to handle  sending a session and channel message, a channel join and leave message, and be able to disconnect the client. Exactly how these messages are sent is up to the SessionProtocol implementation and the client. When done processing the new login, the ProtocolListener will call the completion handler with a SessionProtocolHandler object. This object handles the incoming session and channel messages as well as logout and disconnect. It is the responsibility of the protocol implementation to call the SessionProtocolHandler object as needed. Piece of cake.

Now the protocol layer needs only be responsible for the when and what of the messages exchanged between the server and the client. It does not need to worry about the underlying network transport. It can, but it does not need to. There is a set of interfaces in the internal APIs that define a network transport layer. Through these APIs the protocol layer can use existing implementations of network transports and transport providers can code against the API to create new transports. But I will leave the discussion of transports for another post.

There is one item that deserves extra explanation. One of the methods that the protocol acceptor must implement is getDescriptor(). This method returns a ProtocolDescriptor object. The information in this object is used when a client connection must be redirected to another node. In particular, the getConnectionData() returns an array of data that contains the protocol and transport specific information needed by the client to connect to the node described by the descriptor. For example the byte array might contain the IP address and port number needed for a TCP connection. The server does not look at the data, but the client protocol must be able to interpret it. In general, if using the TCP transport supplied with Darkstar, getConnectionData() needs simply to return the data from the transport descriptor's getConnectionData() method. (see either the SGS simple protocol, or the challenge-response descriptor implementations).

In summary, to build a custom protocol you need to do the following:
  • Create an implementation of ProtocolAcceptor to handle client logins
  • Call ProtocolListener.newLogin() for each successful login
  • Create an implementation of SessionProtocol which forms outgoing messages
  • Call SessionProtocolHandler methods for incoming messages
  • Set the ...protocol.acceptor property to the ProtocolAcceptor implementation
  • Create the client-side protocol handling code

For what Darkchat needed, the above steps were rendered trivial by simply copying the SGS simple protocol sources (found in the com.sun.sgs.impl.protocol.simple package) and modifying them to add in a couple of new protocol messages. The new protocol implements a challenge-response login exchange where the server sends a randomly generated challenge to the client and the client responds with their password encrypted using the challenge. The new messages were the client's request for challenge, and the server's message containing the challenge. The new protocol can be found in the Darkchat server sub-project in the com.sun.sgs.impl.protocol.challengeresponse package.

A similar tact was used to create the client-side protocol handler. The client challenge-response code was based on the sources from the sgs-java-client project. Unfortunately the client code in Darkchat is a little hard to follow for two reasons. First, the sgs-java-client code is hard to follow in the first place. Second, there is an extra two layers in the client side stack, one to allow replacement of the underlying Java SE client with one for Java ME, and the second to handle the conversion from Java to JavaFX. The Java ME client was never completed and does not exist in the source tree. Maybe something for the future!


1Shortly after the JavaOne Keynote the Darkchat gang scurried back to our hotel to get things going. The first step was to send out the email which contained the JNLP script to launch the Darkchat client to all of the attendees. Ant had built a nifty little program which sent an email out every 20-30 seconds or so. We quickly realized it would take a couple of hours to send roughly 8,000 emails so we all sat back and waited for our first login. It was like watching grass grow on a soccer field where a game is being played. In only a few minutes we had our first guinea pig, GOAL! There was much rejoicing. We hung around chatting with the folks entering Darkchat and after about a half hour in, a person noted that he could see everyones messages and was surprised that nothing was encrypted. When queried, he said that he was using (some program I don't remember the name of) to snoop the packets in and out of the server! I informed him that only the login passwords were encrypted and smiled to myself....

Friday Jul 17, 2009

I'm baaack.....

It has been awhile since my last note but I've been busy. In fact, earlier this year I found myself in a very familiar situation... working on a demo. We had three months to do it, but this time it was not going to be a demo shown at a booth under a nice controlled environment like Snowman at GDC, nooooo... this time the server was going to be on the internet and all 8,000 (or whatever) attendees of JavaOne 2009 would be handed a client. The origin of this insanity came from the JavaFX team. We (the Project Darkstar team) had innocently contacted them, inquiring about the possibility of using JavaFX clients with the Darkstar stack. When we got on the phone they started talking about an idea they had about doing a demo for JavaOne using Darkstar, what timing! (I often wonder what would have happened if we hadn't called them?) Anyway, Anthony Rogers and Moises Chicharro (the JavaFX dudes) were obviously crazy enough to be convinced it was possible and apparently so was I. I talked myself and by bosses into temporarily shelving my current work and have at it.

The next couple of months was... interesting, and for the most part fun. I built the server, some client libraries, and tools while Ant and Mo built the JavaFX based client. The result was Darkchat, a multiplayer visual chat environment. The visual client was brilliant (kudos to Ant and Mo) and fun to use. It, along with the server did a great job at JavaOne, in spite of the last code change coming in at 2 am the morning of the Keynote where Darkchat was to be announced and demoed in front of thousands. But I'm getting ahead of myself here. (BTW if you watch the video of the Keynote you can see (starting at 2:40) our own Chris Melissinos give a live demo of Darkchat! Ant, Mo, and I were in the second row holding our collective breaths.)

As with building anything you learn things along the way, tricks, patterns, traps to avoid, etc.. like always point the nail-gun away from your body. It was no different building the Darkchat server (except for the nail-gun thing). Since I already had experience working on a server with Snowman I thought I would have a good handle on what was needed for Darkchat. lol! A common answer, that I myself often give to the question "what is the best way to do x with Darkstar?" is, "it depends on the application". Well, Darkchat was different enough from Snowman that a whole new set of tricks had to be learned. I'm planning on sharing some on those in forthcoming posts so stay tuned.


Today's Page Hits: 30