org.walluck.oscar.handlers
Class ICBMHandler

java.lang.Object
  extended by org.walluck.oscar.handlers.SNACHandler
      extended by org.walluck.oscar.handlers.ICBMHandler

public class ICBMHandler
extends SNACHandler

Family 0x0004 - Routines for sending/receiving Instant Messages.

Note the term ICBM (Inter-Client Basic Message) blankets all types of genericly routed through-server messages. Within the ICBM types (family 0x0004), a channel is defined. Each channel represents a different type of message. Channel 1 is used for what would commonly be called an "instant message". Channel 2 is used for negotiating "rendezvous". These transactions end in something more complex happening, such as a chat invitation, or a file transfer. Channel 4 is used for various ICQ messages.

In addition to the channel, every ICBM contains a cookie. For standard IM's, these are only used for error messages. However, the more complex rendezvous messages make suitably more complex use of this field.

Since:
1.0
Version:
1.0
Author:
David Walluck
See Also:
SNACHandler

Constructor Summary
ICBMHandler()
          Family 0x0004.
 
Method Summary
 void clientAutoresp(AIMSession sess, SNACHandler handler, AIMFrame frame, SNAC snac, AIMInputStream buffer)
          Subtype 0x000b - Client auto-response.
 void delICBMParams(AIMSession sess)
          Delete ICBM parameter information.
 int fingerprintClient(byte[] msghdr)
          Takes a msghdr (and a length) and returns a client type code.
 void handleSNAC(AIMSession sess, SNACHandler handler, AIMFrame frame, SNAC snac, AIMInputStream buffer)
          Handles incoming SNAC's.
 void incomingIMCH4(AIMSession sess, SNACHandler handler, AIMFrame frame, SNAC snac, int channel, UserInfo userinfo, TLVChain tlvchain, byte[] cookie)
          Incoming IM (Channel 4).
 void reqICBMParams(AIMSession sess)
          Subtype 0x0004 - Request ICBM parameter information.
 void sendCH1(AIMSession sess, String destSN, int flags, String msg)
          Simple wrapper for sendIMExt.
 void sendCH1Ext(AIMSession sess, AOLIM args)
          Subtype 0x0006 - Send an ICBM (instant message).
 void sendCH4(AIMSession sess, String sn, int type, String message)
          Subtype 0x0006 - Send an ICQ-esque ICBM.
 void sendMtn(AIMSession sess, String sn, int typing)
          Send a mock typing notification.
 void sendRendezvous(AIMSession sess, String sn, Rendezvous rv)
          Send a rendezvous message.
 void setICBMParams(AIMSession sess, ICBMParams params)
          Subtype 0x0002 - Set ICBM parameters.
 void warn(AIMSession sess, AIMConnection conn, String destsn, int flags)
          Send a warning.
 
Methods inherited from class org.walluck.oscar.handlers.SNACHandler
getFamily, getVersion, setFamily, setVersion
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ICBMHandler

public ICBMHandler()
Family 0x0004.

Method Detail

fingerprintClient

public int fingerprintClient(byte[] msghdr)

Takes a msghdr (and a length) and returns a client type code. Note that this is only a guess and has a low likelyhood of actually being accurate.

Example fingerprints:

0101 01
AOL Mobile Communicator, WinAIM 1.0.414
0101 02
WinAIM 2.0.847, 2.1.1187, 3.0.1464, 4.3.2229, 4.4.2286, 5.x
0101 0102
WinAIM 4.1.2010
01
AOL 6.0, CompuServe 2000, TOC, iChat
0106
WinICQ 5.45.1.3777.8

Note that in this function, only the feature bytes are tested, since the rest will always be the same.

Parameters:
msghdr - the message header
Returns:
the client identifier
See Also:
AIMConstants

setICBMParams

public void setICBMParams(AIMSession sess,
                          ICBMParams params)
                   throws IOException
Subtype 0x0002 - Set ICBM parameters.

I definitely recommend sending this. If you don't, you'll be stuck with the rather unreasonable defaults. You don't want those. Send this.

Parameters:
sess - the oscar session
params - the icbm parameters
Throws:
IOException - if an error occurs

reqICBMParams

public void reqICBMParams(AIMSession sess)
                   throws IOException
Subtype 0x0004 - Request ICBM parameter information.

Parameters:
sess - the oscar session
Throws:
IOException - if an error occurs

sendCH1Ext

public void sendCH1Ext(AIMSession sess,
                       AOLIM args)
                throws IOException
Subtype 0x0006 - Send an ICBM (instant message).

Possible flags in AIMConstants:

AIM_IMFLAGS_AWAY
Marks the message as an autoresponse
AIM_IMFLAGS_ACK
Requests that the server send an ack when the message is received (of type 0x0004/0x000c)
AIM_IMFLAGS_OFFLINE
If destination is offline, store it until they are online (probably ICQ only).
AIM_IMFLAGS_UNICODE
Instead of ASCII7, the passed message is made up of UNICODE couples. If you set this, you'd better be damn sure you know what you're doing.
AIM_IMFLAGS_ISO_8859_1
The message contains the ASCII8 subset known as ISO-8859-1.

Note that AIM_IMFLAGS_ACK and AIM_SESS_FLAGS_DONTTIMEOUTONICBM will cause problems when used together. if AIM_SESS_FLAGS_DONTTIMEOUTONICBM is set, the SNAC will not be cached, even if you set for the message AIM_IM_FLAGS_ACK.

Generally, you should use the lowest encoding possible to send your message. If you only use basic punctuation and the generic Latin alphabet, use ASCII7 (no flags). If you happen to use non-ASCII7 characters, but they are all clearly defined in ISO-8859-1, then use that. Keep in mind that not all characters in the PC ASCII8 character set are defined in the ISO standard. For those cases (most notably when the (R) symbol is used), you must use the full UNICODE encoding for your message. In UNICODE mode, _all_ characters must occupy 16bits, including ones that are not special. (Remember that the first 128 UNICODE symbols are equivelent to ASCII7, however they must be prefixed with a zero high order byte.)

I strongly discourage the use of UNICODE mode, mainly because none of the clients I use can parse those messages (and besides that, wchars are difficult and non-portable to handle in most UNIX environments). If you really need to include special characters, use the HTML UNICODE entities. These are of the form ߪ where 2026 is the hex representation of the UNICODE index (in this case, UNICODE "Horizontal Ellipsis", or 133 in in ASCII8).

Implementation note: Since this is one of the most-used functions in any IM client, it is written with performance in mind. As such, it is not as clear as it could be in respect to how this message is supposed to be layed out. Most obviously, tlv chains should be used instead of writing out the bytes manually.

Parameters:
sess - the oscar session
args - the AOL IM args
Throws:
IOException - if an error occurs

sendCH1

public void sendCH1(AIMSession sess,
                    String destSN,
                    int flags,
                    String msg)
             throws IOException
Simple wrapper for sendIMExt.

You cannot use sendIM if you need the HASICON flag. You must use sendIMExt directly for that.

sendIM also cannot be used if you require UNICODE messages, because that requires an explicit message length. Use sendIMExt.

Parameters:
sess - the oscar session
destSN - the destination screenname
flags - the message flags
msg - the ASCII encoded message
Throws:
IOException - if an error occurs

sendRendezvous

public void sendRendezvous(AIMSession sess,
                           String sn,
                           Rendezvous rv)
                    throws IOException
Send a rendezvous message.

Parameters:
sess - the oscar session
sn - the screenname
rv - the rendezvous to send
Throws:
IOException - if an error occurs

sendCH4

public void sendCH4(AIMSession sess,
                    String sn,
                    int type,
                    String message)
             throws IOException
Subtype 0x0006 - Send an ICQ-esque ICBM.

This can be used to send an ICQ authorization reply (deny or grant). It is the "old way." The new way is to use SSI. I like the new way a lot better. This seems like such a hack mostly because it's in network byte order. Figuring this stuff out sometimes takes a while, but that's ok, because it gives me time to try to figure out what kind of drugs the AOL people were taking when they merged the two protocols.

Parameters:
sess - the oscar session
sn - the destination screen name
type - the type of message, 0x0007 for authorization denied and 0x0008 for authorization granted
message - the message you want to send, it should be null terminated.
Throws:
IOException - if an error occurs

incomingIMCH4

public void incomingIMCH4(AIMSession sess,
                          SNACHandler handler,
                          AIMFrame frame,
                          SNAC snac,
                          int channel,
                          UserInfo userinfo,
                          TLVChain tlvchain,
                          byte[] cookie)
                   throws IOException
Incoming IM (Channel 4).

Parameters:
sess - the oscar session
handler - the handler
frame - the incoming frame
snac - the incoming SNAC
channel - the channel
userinfo - user information
tlvchain - TLV chain
cookie - the cookie
Throws:
IOException - if an error occurs

warn

public void warn(AIMSession sess,
                 AIMConnection conn,
                 String destsn,
                 int flags)
          throws IOException
Send a warning.

Flags:

AIMConstants.AIM_WARN_ANON
Send as an anonymous (doesn't count as much)

Parameters:
sess - the oscar session
conn - the bos connection for this session
destsn - the screenname to warn
flags - the warning flags
Throws:
IOException - if an error occurs
See Also:
AIMConstants

clientAutoresp

public void clientAutoresp(AIMSession sess,
                           SNACHandler handler,
                           AIMFrame frame,
                           SNAC snac,
                           AIMInputStream buffer)
                    throws IOException
Subtype 0x000b - Client auto-response.

Receive the response from an ICQ status message request. This contains the ICQ status message.

Parameters:
sess - the oscar session
handler - the handler
frame - the incoming frame
snac - the incoming SNAC
buffer - the incoming buffer
Throws:
IOException - if an error occurs

sendMtn

public void sendMtn(AIMSession sess,
                    String sn,
                    int typing)
             throws IOException
Send a mock typing notification.

MacAIM implements a typing notification that does not require a direct connection. When you begin typing, you send the "begin typing" message (type 0x0002). A few seconds later you send a "text has been typed" message (type 0x0001). After the message has been sent you send a "no more text has been typed" message (type 0x000).

The client and server SNAC's use the same subtype. Go figure.

Parameters:
sess - the oscar session
sn - the screenname
typing - what typing state we are in when this message is sent
Throws:
IOException - if an error occurs

delICBMParams

public void delICBMParams(AIMSession sess)
                   throws IOException
Delete ICBM parameter information.

Parameters:
sess - the oscar session
Throws:
IOException - if an error occurs

handleSNAC

public void handleSNAC(AIMSession sess,
                       SNACHandler handler,
                       AIMFrame frame,
                       SNAC snac,
                       AIMInputStream buffer)
                throws IOException
Handles incoming SNAC's.

Specified by:
handleSNAC in class SNACHandler
Parameters:
sess - the oscar session
handler - the handler
frame - the incoming frame
snac - the incoming SNAC
buffer - the incoming buffer
Throws:
IOException - if an error occurs