2.0 AIM Commands
Everything in the AIM protocol is embodied in AIM commands. The division is not of packets because more than one command may be sent in any one packet, depending on the transmit timing, etc. Commands are an abstraction above packets, and leads to the definition of the FLAP protocol below.
Below is an attempt to generalize the layout of all AIM commands. The acronyms used are those used by the AIM client and the AIM divison of AOL as defined in the document at http://www.aim.aol.com/javadev/terminology.html. Please refer to that document if the explanations listed here are not complete enough for you.
Fig 2.1 Generalized Command Structure
FLAP
- Command Start (byte: 0x2a)
- Channel ID (byte)
- Sequence Number (word)
- Data Field Length (word)
Data Field
- Usually SNAC Data (variable)
|
|
2.1 FLAP
The FLAP is the protocol that sits at the bottom of everything communicated across AIM channels. This generally makes up the first 6 bytes of every AIM command. If this protocol is not obeyed, the OSCAR server will disconnect the offending client immediatly upon reception of a malformed command. This is not helpful for debuging, to say the least.
2.1.1 FLAP: Headers
Contained in the FLAP headers are: (in order of appearance)
- Command-Start [byte] (always 0x2a)
- Channel Identification [byte]
- Sequence Number [word]
- FLAP Data Field Length [word]
This is followed immediatly by an unterminated FLAP Data Field, which concludes the FLAP command.
2.1.2 FLAP: Data Field
Normally, the FLAP Data Field contains a SNAC. The FLAP Data Field makes up the rest of the command (there is no FLAP-specific command terminator).
2.1.3 Sequence Numbers
Why AOL decided to use sequence numbering with TCP is beyond me. The retransmit and data integrity standards of TCP connections make this pointless. So, they're really just there for looks, though that doesn't mean that they can be incorrect. If the server gets an out-of-order command (according to the seqnums, not actual order), you will be disconnected.
The sequence number origins are picked quite randomly. There is no connection between the sequence number set from the server and the set from the client. Sequence numbers are always incremented upward (towards 0xFFFF) for each command sent. If the seqence number does reach 0xFFFF, it will wrap to 0x0000, for obvious reasons. If you start a new connection, it is recommended that a new sequence number origin is picked for that connection, for purposes of internal coherency. Sequence numbers are independent of channels: there's a single series of sequence numbers per TCP connection (per socket). See section 2.1.4 for more information.
2.1.4 Channels
Channels are the method used to multiplex seperate paths of communication across the same TCP socket. These are analogous to TCP/UDP port numbers. Four channels are currently used by OSCAR:
- 0x01 - New Connection Negotiation
- 0x02 - SNAC data (non connection-oriented data)
- 0x03 - FLAP-level Error
- 0x04 - Close Connection Negotiation
After a new connection (socket) is set up using channel 0x01, data should only be carried on channel 0x02, until a low-level FLAP error occurs (channel 0x03) or there is planned termination, which gets "negotiated" (on channel 0x04). Most live events processed during the lifespan of the client are done over channel 0x02. SNACs are never transmitted on any channel other than 0x02.
2.1.5 Features of FLAP
[Not yet.]
2.1.6 Thoughts on FLAP Implementation
The best way to read an incoming FLAP command is to first read only the starting 6 bytes (the FLAP headers). From these 6bytes, you can determine how many more bytes you need to read to complete the command, and how much memory you need to allocate to store it. Never read more or less than the number of bytes specified in the FLAP headers, or your read will result in a truncated or uninterpretable command. (If you read too much, you will probably end up reading the start of the next command, which is bad. Lost data is unacceptable in the AIM standard.)
Because every command must follow FLAP guidelines, I'd recommend using a low-level routine to add the FLAP headers (normally, this will be the "flush transmit queue" routine, so that addition of sequence numbers and the rest of the FLAP headers is done as close timewise as possible to the command being put on the wire). This is the best way to prevent out-of-order seqnums from getting used (which, as stated earlier, is quite fatal).
2.2 SNAC
The SNAC is the unit that sits immediatly above FLAP on most commands, and is the normal contents of the FLAP Data Field for channel 0x02. SNACs are only sent over channel 0x02. Data sent across other channels are not considered complete SNACs. There can be only one SNAC per FLAP command.
SNACs are generalized into the following format:
Position | Size | Purpose |
1 | word | Family ID |
3 | word | SubType ID |
5 | byte | Flags[0] |
6 | byte | Flags[1] |
7 | dword | Request ID |
11 | variable | SNAC Data |
There is no formal declaration of the length of the SNAC data portion (that information must be assumed from the FLAP headers).
"Families", identified by the "Family ID", constitute a group of services. These are usually quite large groups.
Subtypes are a subdivision of the Families. Each subtype ID is different depending on the specific service or information provided in the data section.
Flags are completely optional. They're very rarely used, if at all.
Request IDs are 32bit values used to identify non-atomic information. The client can generate completely random reqid's as long as it remembers what the request was for. Often, though, the results of the SNAC are irrelevent, and the reqid's can be forgotten. But, in information-requestion SNACs, it is imparative you remember the reqid you sent because that's the only way to link it to the response! If this is not done, it will be impossible to have more than one pending request of the same SNAC subtype (which is unlikely at best). For server-initiated SNACs, the reqid is ORed with the fixed value -2147483648, and count up to zero from than from zero.
Table 2.2.1 lists all documented SNAC types and subtypes.
Table 2.2.1 Known SNACs
Subtype | Source | Function |
Family 0x0001: Generic Service Controls |
0x0001 | Client or Server | Error |
0x0002 | Client | Client is now online and ready for normal function |
0x0003 | Server | Server is now ready for normal functions |
0x0004 | Client | Request for new service (the server will redirect the client to a new host where the service is available) |
0x0005 | Server | Redirect (response to subtype 0x0004 from client) |
0x0006 | Client | Request Rate Information (request rate at which client can send SNACs) |
0x0007 | Server | Rate information response (response to subtype 0x0006) |
0x0008 | Client | Rate Information Response Ack |
0x000A | Server | Rate information change |
0x000B | Server | Pause |
0x000D | Server | Resume |
0x000E | Client | Request information on the screen name you've been authenticated under. |
0x000F | Server | Information the screen name you've been authenticated under. |
0x0010 | Server | Evil notification |
0x0012 | Server | Migration notice/request |
0x0013 | Server | Message of the day |
0x0014 | Client | Set Privacy flags |
0x0015 | Server | Well known urls |
0x0016 | Server | No op |
Family 0x0002: Location Services |
0x0001 | Client or Server | Error |
0x0002 | Client | Request rights information |
0x0003 | Server | Rights information |
0x0004 | Client | Set user information |
0x0005 | Client | Request user information |
0x0006 | Server | User information |
0x0007 | Client | Watcher sub request |
0x0008 | Server | Watcher notification |
Family 0x0003: Buddy List Management |
0x0001 | Client or Server | Error |
0x0002 | Client | Request rights information |
0x0003 | Server | Rights information |
0x0004 | Client | Add buddy to buddy list |
0x0005 | Client | Remove buddy from buddy list |
0x0006 | Client | Watcher list query |
0x0007 | Server | Watcher list response |
0x0008 | Client | Watcher sub request |
0x0009 | Server | Watcher notification |
0x000A | Server | Reject notification |
0x000B | Server | Oncoming buddy |
0x000C | Server | Offgoing buddy |
Family 0x0004: Messaging |
0x0001 | Client or Server | Error |
0x0002 | Client | Add ICBM parameter |
0x0003 | Client | Remove ICBM parameter |
0x0004 | Client | Request parameter information |
0x0005 | Server | Parameter information |
0x0006 | Client | Message from the client |
0x0007 | Server | Message to the client |
0x0008 | Client | Evil request |
0x0009 | Server | Evil reply |
0x000A | Server | Missed calls |
0x000B | Client or Server | Client error |
0x000C | Server | Host ack |
Family 0x0005: Advertisments |
0x0001 | Client or Server | Error |
0x0002 | Client | Request advertisments |
0x0003 | Server | Advertisment data (GIFs) |
Family 0x0006: Invitation and Client-to-Client |
0x0002 | Client | Invite a friend to join AIM |
0x0003 | Server | Invite a friend to join AIM ack |
Family 0x0007: Administrative |
0x0001 | Server | Admin error |
0x0002 | Client | Information request |
0x0003 | Server | Information reply |
0x0004 | Client | Information change request |
0x0005 | Server | Information change reply |
0x0006 | Client | Account confirm request |
0x0007 | Server | Account confirm reply |
0x0008 | Client | Account delete request |
0x0009 | Server | Account delete reply |
Family 0x0008: Popup Notices |
0x0001 | Client or Server | Error |
0x0002 | Server | Display popup |
Family 0x0009: BOS-specific |
0x0001 | Client or Server | Error |
0x0002 | Client | Request BOS Rights |
0x0003 | Server | BOS Rights |
0x0004 | Client | Set group permission mask |
0x0005 | Client | Add permission list entries |
0x0006 | Client | Delete permission list entries |
0x0007 | Client | Add deny list entries |
0x0008 | Client | Delete deny list entries |
0x0009 | Server | BOS error |
Family 0x000A: User Lookup |
0x0001 | Client or Server | Error (often Search Failed) |
0x0002 | Client | Search for screen name by email address |
0x0003 | Server | Search Response |
Family 0x000B: Stats |
0x0001 | Client or Server | Error |
0x0002 | Server | Set minimum report interval |
0x0003 | Client | Report events |
0x0004 | Server | Report ack |
Family 0x000C: Translate |
0x0001 | Client or Server | Error |
0x0002 | Client | Translate request |
0x0003 | Server | Translate reply |
Family 0x000D: Chat Navigation |
0x0001 | Client or Server | Error |
0x0002 | Client | Request chat rights |
0x0003 | Client | Request exchange information |
0x0004 | Client | Request room information |
0x0005 | Client | Request more room information |
0x0006 | Client | Request occupant list |
0x0007 | Client | Search for room |
0x0008 | Client | Create room |
0x0009 | Server | Navigation information |
Family 0x000E: Chat |
0x0001 | Client or Server | Error |
0x0002 | Server | Room information update |
0x0003 | Server | Users joined |
0x0004 | Server | Users left |
0x0005 | Client | Channel message from client |
0x0006 | Server | Channel message to client |
0x0007 | Server | Evil request |
0x0008 | Server | Evil reply |
0x0009 | Client or Server | Client error |
Family 0x0045: Unknown (Client Something?) |
0x0002 | Client | Add to notify list |
2.2.1 Notes on SNACs
If you have more to add to the list, please do. These are the basics of OSCAR communication, so there's bound to be alot of them!
One last note on the subject: never eat SNACs. They're extremely fattening, no matter what the National SNAC Council's television commercials tell you about them. Also, they have been known to cause your limbs to start FLAPing, which often results in unannounced levetation.
2.3 TLVs
TLVs are a very convenient and efficient method of putting data into an organized format, esp variable length strings, etc. TLV litterally stands for "Type, Length, Value". And that's exactly what it is: a 16bit Type code, a 16bit value for the length of the Value field, and then the actual data in the Value field (variable length).
TLVs can be be in SNACs, but thats not required. TLVs often are used directly in the FLAP Data Field, but normally are inside of SNACs. No more than one TLV of each Type code may exist in a single FLAP command (SNAC or not). TLVs must follow the strict tuple-rule, or they're really not TLVs, they're raw data.
TLVs are a big win. They make sending a variable length string like, eg, "afritz@iname" as simple as defining a TLV with values {0x0011, 0x000c, "afritz@iname.com"}. (The type 0x0011 is used throughout the authorization process as the "email address type".) A side note about strings: strings in this protocol are never NULL-terminated. If they look like they are, that's probably a word-length value behind it.
|