devxlogo

Create a Java TOC2 Class to Communicate with AIM

Create a Java TOC2 Class to Communicate with AIM

OL Instant Messenger (AIM) is well known as one of the top four IM clients used today. Popular with both home users and businesses, AIM allows you to send instant messages (IMs) to other people who have a handle on the AIM network. However, you may not be aware that the protocol underlying AIM, called TOC2, is the gateway through which you can create a lot of customized AIM-based applications. AOL provides an API that anybody can use to connect to TOC2 and AOL’s network. In this article I’ll give you a brief history of the TOC2 protocol and then show you how to create your own custom chat application using the TOC2 API.

There are many different reasons to integrate instant messaging into an application. Obviously, you can create your own chat client, with whatever features you like. However, the real power lies in creating applications that you can “chat” with, just like you do a human. Want to know the status of your servers? Just fire up your instant messenger and ask your server for some information.

There are many different ways that you can integrate instant message technology into applications. To make use of AOL’s chat network you will have to use their protocol, called TOC. Around August 10, 2005 AOL upgraded from the TOC protocol to the TOC2 protocol. The changes were minor, but unfortunately the upgrade broke every existing software connection to the TOC protocol. AOL’s action left many users thinking that AOL had blocked third-party applications from accessing its network. This is not the case, but it does mean that all third-party AIM software must be upgraded to support TOC2.

I learned this the hard way. Back in 2001 I wrote a simple Java class that accesses AIM using TOC. My class broke, along with everything else, back in August. I have since upgraded it, and I am releasing the new version with this article.

Author’s Note: The original AIM chat client and the updated version in this article are released under the LGPL license. Readers are free to use it, but credit must be given to the author, Jeff Heaton.

TOC Servers
To use TOC you simply use the sockets API available with Java. Special packets will then be exchanged with the server. These packets, called FLAPs, contain a single line of ASCII text that describes the TOC command that you wish to execute. The FLAP packet is relatively simple, and has the following format.

Byte 0: Marker (must be 0x2a)
Byte 1: Packet Type
Bytes 2,3: Sequence Number
Bytes 4,5: Length of Data
Bytes 6- : Packet Data

All communication with the TOC server will be in the form of these FLAP packets. This includes both packets that the TOC server sends to you, as well as packets that you send the TOC server.

As you will notice above, bytes 2,3 and 4,5 both go together. These two-byte pairs are called “words.” Words are always sent as big-endian numbers. The following method is provided to write a word to the socket output string.

   protected void writeWord(short word)   throws IOException   {     os.write((byte) ((word >> 8) & 0xff) );     os.write( (byte) (word & 0xff) );   }

A sendFlap method is also provided, which makes use of the writeWord method.

   protected void sendFlap(int type,String str)   throws IOException   {     int length = str.length()+1;     sequence++;     os.write((byte)'*');     os.write((byte)type);     writeWord(sequence);     writeWord((short)length);     os.write(str.getBytes());     os.write(0);     os.flush();   }

All FLAP packets start with the “*” character. Next the sequence number is incremented. The length of the string and the string itself are then transmitted. With the exception of the signon packet, all FLAP packets will be sent using this method. The flap signon is sent using the sendFlapSignon method. This is done because the signon packet has a slightly different format.

Likewise, a getFlap method is provided. This method will read a FLAP packet from the remote computer and return a String that holds the data that was in that packet:

   protected String getFlap()   throws IOException   {     if ( is.read()!='*' )       return null;     is.read();     is.read();     is.read();     int length = (is.read()*0x100)+is.read();     byte b[] = new byte[length];     is.read(b);     

As you can see, this method reads a FLAP packet, and as before, the first character is an “*” as required. The sequence number and other fields are ignored. Only the length is used so that the correct number of characters for the packet are read.

You open a connection to the TOC server and exchange messages with it. There are actually two servers you will deal with. The first is the TOC server, which is at toc.oscar.aol.com, port 9898. The second is the login server, which is at login.oscar.aol.com, port 5190.

To communicate with AIM you open a connection to the TOC server. You then exchange login information and begin your AIM session.

Logging onto TOC
The JavaTOC2 class provides a login method to connect you to the TOC network. The login method takes two parameters: your AIM Screen Name and your password. The login method is shown here:

  public boolean login(String id,String password)   throws IOException   {

The first thing that the login method does is to open a socket connection to the TOC server.

     this.id = id;     connection = new Socket(tocHost,tocPort);     is = connection.getInputStream();     os = connection.getOutputStream();

The first thing that you must communicate to the TOC server is the token “FLAPON.” Next the signon packet is sent, which tells TOC the capabilities of your client.

     sendRaw("FLAPON

");     getFlap();     sendFlapSignon();

To login to the TOC server you must send the command “toc2_signon.” This command is of the format:

toc2_signon [auth host] [auth port] [screen name] [password] [language] [version] [160] [code]

This command is constructed with the following lines of code.

     String command = "toc2_signon " +                      authHost + " " +                      authPort + " " +                      id + " " +                      roastPassword(password) + " " +                      language + " "" +                      this.version + "" 160 " + calculateCode(id,password);

Notice that the password is encoded with a method named roastPassword. This method does very basic encoding on the password, which I will discuss shortly. Likewise, the id and password are both encoded into a number. This number is calculated by a method named calculateCode. This method will also be discussed shortly.

Next the signon command is sent.

     sendFlap(DATA,command);     String str = getFlap();

If an error is detected, then it is reported to the user, and the login method returns false, indicating an error.

     if ( str.toUpperCase().startsWith("ERROR:") ) {       handleError(str);       return false;     }

The login method completes by sending several lines of compatibility information. The following commands give a fairly generic set of capabilities, which should be sufficient for most programs.

     this.sendFlap(DATA,"toc_add_buddy " + this.id);     this.sendFlap(DATA,"toc_init_done");     this.sendFlap(DATA,"toc_set_caps 09461343-4C7F-11D1-8222-444553540000 09461348-4C7F-11D1-8222-444553540000");     this.sendFlap(DATA,"toc_add_permit ");     this.sendFlap(DATA,"toc_add_deny ");     return true;   }

As previously mentioned, the password is encoded. This process is called “roasting the password.” This “encryption” is basically an XOR shift across the password. While the password can be easily decrypted, it at least keeps the password from being transferred in plain text. The roastPassword method is shown here:

   protected String roastPassword(String str)   {     byte xor[] = roastString.getBytes();     int xorIndex = 0;     String rtn = "0x";     for ( int i=0;i

In addition to the password a code must be calculated using the calcuateCode method. The calculateCode method is shown here.

   protected int calculateCode(String uid,String pwd)   {     int sn = uid.charAt(0)-96;     int pw = pwd.charAt(0)-96;     int a = sn * 7696 + 738816;     int b = sn * 746512;     int c = pw * a;     return( c - a + b + 71665152 );   }

Once you complete the login process you are ready to send and receive instant messages.

Receiving an Instant Message
To receive instant messages you must implement the Chatable interface:

public interface Chatable {   public void unknown(String str);   public void error(String str,String var);   public void im(String from,String message);}

Whenever you receive a message, the im method will be called. The error method will be called when an error occurs. The unknown method will be called when a known TOC command is received. This allows you to handle additional TOC commands that my library does not handle.

To process the TOC events you should call the processTOCEvents method. This method enters a loop and waits for TOC events to come through the socket:

   public void processTOCEvents()   throws IOException   {     for ( ;; ) {       String str = this.getFlap();       System.out.println(str);       if ( str==null )         continue;       if ( str.toUpperCase().startsWith("IM_IN2:") ) {         handleIM(str);       } else if ( str.toUpperCase().startsWith("ERROR:") ) {         handleError(str);       } else {         owner.unknown(str);       }     }   }

As you can see, this method enters a loop and waits for IM_IN2 commands. Because this method enters a loop, you should call it from a background thread. It will process incoming TOC messages until its thread is terminated.

For every incoming instant message, the handleIM method is called. This method parses the instant message and sends the results on to the interface's im method:

   protected void handleIM(String str)   {     StringBuffer sb = new StringBuffer(str);     nextElement(sb);     // get who its from     String from = nextElement(sb);     String a = nextElement(sb);     String b = nextElement(sb);     // get message     String message = sb.toString();     owner.im(from,message);   }

As you can see, this method parses the parameters of the incoming message. The only parameters that are used are who the message is from, and what the message text is.

Sending an Instant Message
To send messages, the send method is provided. The send method accepts two parameters: who the message is to and what the message is. The send method is shown here.

   public void send(String to,String msg)   {     try {       this.sendFlap(DATA,"toc_send_im " + normalize(to) + " "" +encode(msg) + """);     } catch ( java.io.IOException e ) {     }   }

The send method is relatively simple. The message is packaged up as a toc_send_im command and sent over the socket. The normalize method is used to properly encode any special characters that might be in the user's name.

Talking to a Computer
Finally, I will show you a simple example program that makes use of the JavaTOC2 class. This example is contained in the file SystemChat.java. This is a very simple application that demonstrates how to use the class. It can be a starting point for much larger applications.

First, you must modify the run method to include your screen name and password:

  public void run()  {    toc = new JavaTOC2(this);    try    {      toc.login("[Your Screen Name]","[Your Password]");      toc.processTOCEvents();    } catch (IOException e)    {      e.printStackTrace();    }  }

This example program waits for you to chat with it and ask simple questions (see Figure 1). To do this the im method waits for these questions and then sends the answers:

Figure 1. The Chat App: The screen shot shows the basic UI for the chat application built in the article.
public void im(String from, String message)  {    String str;    str = message.toLowerCase();    if( str.indexOf("what time is it")!=-1)    {      Date d = new Date();      toc.send(from,d.toString());    }    else if( str.indexOf("who are you")!=-1)    {      Date d = new Date();      toc.send(from,System.getProperty("user.name"));    }    else if( str.indexOf("what are you")!=-1)    {      Date d = new Date();      toc.send(from,System.getProperty("os.name")+" "+          System.getProperty("os.version")+" "+          System.getProperty("os.arch"));    }  }

As you can see there are three questions you can ask the system:

  • What time is it?
  • Who are you?
  • What are you?

To answer each of these questions, the program will call on the JDK.

This program demonstrates all of the elements you might use to implement a chat application.

This article did not discuss every feature of TOC2. For more information about buddy lists, media types, and other TOC2 features you can check out the Wikipedia article on the TOC2 command set. This was the source that I used to gather information about the new TOC2 command set.

Future Directions
The source code presented in this article provides a great starting point for creating your own chat applications. Using the JavaTOC2 you can create a chat-enabled Java application in minutes.

If you are going to write software that responds to instant messages, you should be aware that there are several patents that cover this area. As always, you should seek legal advice to determine the extent to which these patents may overlap with your development project.

Additionally, there are very advanced APIs already available for interfacing to chat networks. These APIs also include advanced Natural Language Processing capabilities. One of the oldest and most popular is ConverseAgent. You can even chat with one of its Bots by adding SmarterChild to your AIM buddy list.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist