This "tutorial" was written by Keith as a Weblog entry once, and has since been updated slightly to match changes in joscar. It is by no means complete nor does it teach how to implement a robust login sequence. A full joscar tutorial will probably come in a future release. Check the Joust website for updates.
The latest version of this tutorial is available at http://joust.kano.net/joscar/docs/howto/login.html.
I have to admit that JoscarTester (and almost all of net.kano.joscartests.*) is some really awful code. It's not part of joscar, so I didn't worry too much about it. It's just a "client" I use to test new stuff. So that developers (like Adam :) don't have to parse through that garbage, I shall attempt to describe here how a typical client would function.
First a bit of background on how OSCAR works over TCP. A typical OSCAR "session" consists of at least two but up to six (or so) TCP connections. The first is to the "authorizer" server, login.oscar.aol.com, where you log in with your screenname and password. This server redirects you to a "basic online service" (BOS) server. You disconnect from the authorizer and connect to the BOS server. From there you can do most things (IM, info, buddy list, and so on), but other "services" require connections to new servers. Other services are not covered in this tutorial.
To connect to the authorizer, you could create your own TCP Socket
or simply use my pre-prepared ClientConn
class (I personally prefer asynchronous sockets, probably from my Tcl days :). In fact, there's a ClientConn subclass designed specifically for OSCAR connections! It's called ClientFlapConn
and not only does it connect and whatnot, it also runs a FLAP event loop!
What is a FLAP, you may ask? Well it looks like you need to do some more research on the protocol! Briefly, however, FLAP is the protocol over which all client-server (and no client-client) OSCAR communication takes place. It's very simple, allowing for "login cookies," disconnection messages ("you have been disconnected because your screenname was signed onto from another computer"), and separate "channels" of data. It is over the FLAP protocol that OSCAR's ever-popular SNAC commands are sent (on the SNAC data channel).
So, to utilize this whole FLAP thing, first we need to set up a FLAP event handler (for incoming FLAP data packets) and a SNAC command handler (for incoming SNAC commands on the SNAC flap channel) for each connection you make to an OSCAR server. Setting up a FLAP connection is done like so:
Socket socket = createNewTcpConnectionHoweverYouWant(); FlapProcessor flapProcessor = new FlapProcessor(socket);
And then you can begin sending FLAP packets through the FLAP "processor." In addition, you might want to set up a loop to read incoming commands (I suggest something cleaner than this):
Runnable looper = new Runnable() { public void run() { while (true) { if (!flapProcessor.readNextFlap()) break; } } }; new Thread(looper).start();
So now you've got the FLAP commands being read in from the socket. But where are they going?? If you want to be notified when a new FLAP packet comes in, you need to add a packet listener to the FLAP processor:
FlapPacketListener listener = new FlapPacketListener() { public void handlePacket(FlapPacketEvent e) { System.out.println("Got FLAP packet!!!"); } }; flapProcessor.addPacketListener(listener);
You should probably add an exception handler as well, but we won't get into that here. So now we're reading in FLAP packets. Yay. The problem is that we aren't that interested in FLAP-level data most of the time. We like SNACs; the majority of the interesting parts of the OSCAR protocol are SNAC-based. So let's add a SNAC processor too!
ClientSnacProcessor snacProcessor = new ClientSnacProcessor(flapProcessor);
Now packets on the SNAC channel of the FLAP connection we made will be converted into SnacCommand
s, and we can easily utilize SNACs' request-response system without any extra code on our part. Yay!
You'd notice, however, if you tried to run the above code, that the "Got FLAP packet!!!"
message would not appear when SNAC commands were received. So where are they going? Well, we need to add a listener to the SNAC processor just like we did for the FLAP processor:
SnacPacketListener snacListener = new SnacPacketListener() { public void handlePacket(SnacPacketEvent e) { System.out.println("Got SNAC packet!"); } } snacProcessor.addPacketListener(snacListener);
Also, some SNAC packets are sent in response to specific commands we sent; in joscar these are called SNAC Responses, and can be handled with a SnacRequestListener
. All SNAC packets received during authorization are SNAC responses. For details, see the sample code at the end of this tutorial.
We don't need to add an exception handler to the SNAC processor; it just uses the FLAP processor's exception handlers.
Alright! Now we're processing FLAPs and SNACs and whatnot. Now, however, comes the hard part: the actual protocol.
Here's how the connection to the authorizer goes:
LoginFlapCmd
LoginFlapCmd
KeyRequest
KeyResponse
AuthRequest
AuthResponse
See the javadoc for details on what each command should contain. The AuthResponse
, if the login was successful, contains a host and maybe a port (use 5190 otherwise) for the BOS server. Here's how the connection to the BOS server goes:
LoginFlapCmd
LoginFlapCmd
(with login cookie provided in AuthResponse
above) ServerReadyCmd
ClientVersionsCmd
ServerVersionsCmd
RateInfoRequest
RateInfoCmd
RateAck
ParamInfoReq
ParamInfoCmd
SetParamInfoCmd
(if necessary) LocRightsRequest
LocRightsCmd
SetInfoCmd
MyInfoRequest
YourInfoCmd
SsiRightsRequest
SsiRightsCmd
SsiDataCheck
), the SSI data is only sent back if it's changed since then; otherwise, the SSI is simply sent back. This SSI (server-stored information) contains such things as the buddy list and privacy settings (for example, whether typing notification is enabled). When a response is received (after any changes to the SSI have been made), the client "activates" the SSI, causing the stored privacy settings to take effect, triggering buddy status updates, and so on.
SsiDataRequest
or (preferably) SsiDataCheck
SsiDataCmd
or SsiUnchangedCmd
ActivateSsiCmd
ClientReadyCmd
So. That's the login process for you. Many of the commands sent in setting up the BOS connection are unnecessary, but it's good to send them even if you don't quite know what you're doing; the server sort of expects them and might behave differently without them, thinking you are an older or somehow broken client.
I'll leave you with some sample code that connects to the authorization server and logs in. It doesn't even connect to the BOS server, but I think it serves as a good introduction to joscar:
If you can't get something working, you should try using the Java Logging API to trace what's going on inside joscar:
ConsoleHandler handler = new ConsoleHandler(); handler.setLevel(Level.ALL); Logger logger = Logger.getLogger("net.kano.joscar"); logger.addHandler(handler); logger.setLevel(Level.ALL);
If you still can't figure it out, feel free to email me at keith@kano.net.
Enjoy.