org.walluck.oscar
Class AIMConnection

java.lang.Object
  extended byjava.lang.Thread
      extended byorg.walluck.oscar.AIMConnection
All Implemented Interfaces:
java.lang.Runnable

public class AIMConnection
extends java.lang.Thread

In OSCAR, every connection has a set of SNAC groups associated with it. SNAC groups are sometimes called SNAC families by me and other open source/free software AIM/ICQ client writers after the trend started by libfaim/gaim. The SNAC groups inside an AIMConnection are the groups that you can send over that connection without generating a "Not supported" SNAC error. I will explain this by describing what libfaim calls "connection types", stored as the type member in the AIMConnection, and specified in AIMConstants. The explanation goes as follows: So let us say that you have your core BOS connection running. One of your handlers has just given you a SNAC of the group 0x0004 to send you. Maybe an IM destined for some twit in Greenland. So you start at the top of your connection list, looking for a connection that claims to support group 0x0004. You find one. Why, that neat BOS connection of yours can do that. So you send it on its way. Now, say, that fellow from Greenland has friends and they all want to meet up with you in a lame chat room. This has landed you a SNAC in the family 0x000e and you have to admit you're a bit lost. You've searched your connection list for someone who wants to make your life easy and deliver this SNAC for you, but there isn't one there. Here comes the good bit. Without even letting anyone know, particularly the handler that decided to send this SNAC, and definitly not that twit in Greenland, you send out a service request. In this request, you have marked the need for a connection supporting group 0x000e. A few seconds later, you receive a service redirect with an IP address and a cookie in it. Great, you say. Now I have something to do. Off you go, making that connection. One of the first things you get from this new server is a message saying that indeed it does support the group you were looking for. So you continue and send rate confirmation and all that. Then you remember you had that SNAC to send, and now you have a means to do it, and you do, and everyone is happy. Except the Greenlander, who is still stuck in the bitter cold. Oh, and this is useful for building the Migration SNACs, too. In the future, this may help convince me to implement rate limit mitigation for real. We'll see. Just to make me look better, I'll say that I've known about this great scheme for quite some time now. But I still haven't convinced myself to make libfaim work that way. It would take a fair amount of effort, and probably some client API changes as well. (Whenever I don't want to do something, I just say it would change the client API. Then I instantly have a couple of supporters of not doing it.) Generally, addGroup is only called by the internal handling of the server ready SNAC. So if you want to do something before that, you'll have to be more creative. That is done rather early, though, so I don't think you have to worry about it. Unless you're me. I care deeply about such inane things. I am not sure what rate limit migration is at this point, since I've never seen it. I also tend to disagree on this whole connection type thing. The only types that you should specify here are for Chat and ChatNav. DirectIM and FIle Transfer will use their own separate threads and connections.

Since:
1.0
Version:
1.0
Author:
David Walluck

Field Summary
 
Fields inherited from class java.lang.Thread
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY
 
Constructor Summary
AIMConnection(AIMSession sess, int type, java.lang.String dest)
          Creates a new AIM connection.
AIMConnection(AIMSession sess, int type, java.lang.String dest, ProxyConnection pc)
          Creates a new AIM connection with a proxy.
 
Method Summary
 void addCookie(MsgCookie cookie)
          Add a message cookie for this session.
 void addGroup(int version)
          Add a group for this connection.
 void addRate(RateClass rate)
          Adds a rate to this connection.
 int cleanCookies(int maxAge)
          Clean message cookies.
 int cleanSNACs(int maxAge)
          Clean the SNAC hash table.
 void close(AIMSession sess)
          Close a connection.
 void connect()
          Connects to the ip:port specified in dest.
static void connKill(AIMSession sess)
          Closes all connections in the guven session.
 void deregisiterListener(int family, int subtype, Listener listener)
          Remove a listener for this connection.
 void enqueueFrame(AIMFrame frame)
          Push a frame onto the transmit queue.
static AIMConnection findByGroup(AIMSession sess, int group)
          Find a connection that supports the given SNAC group.
static AIMConnection findByType(AIMSession sess, int type)
          Finds the first connection of a given type belonging to this session.
 RateClass findRate(int classID)
          Find a rate by the guven class ID.
 RateClass findRate(int family, int subtype)
          Find a rate by a given SNAC family and SNAC subtype.
 int getFlags()
          Get the value of flags.
 long getForcedLatency()
          Get value of forcedLatency.
 java.util.ArrayList getGroups()
          Get the value of groups.
 java.lang.String getHost()
          Get the value of host.
 java.util.Hashtable getICQHashtable()
          Get the value of ihash.
 java.io.InputStream getInputStream()
          Get the value of is.
 java.lang.Object getInternal()
          Get value of interbal.
 long getLastActivity()
          Get value of lastActivity.
 java.util.Iterator getListeners(int family, int subtype)
          Get the connection listeners for the given SNAC family.
 java.util.ArrayList getMembers()
          Get the value of members.
 java.util.HashMap getMsgCookies()
          Get the value of msgCookies.
 java.io.OutputStream getOutputStream()
          Get the value of os.
 int getPort()
          Get the value of port.
 java.util.ArrayList getRates()
          Gets the value of rates.
 Queue getReceiveQueue()
          Get the value of receiveQueue.
 int getRetries()
          Get the value of retries.
 int getRetryTime()
          Get the value of retryTime.
 AIMSession getSess()
          Get the value of sess.
 java.net.Socket getSocket()
          Get the value of socket.
 int getSubtype()
          Get the value of subtype.
 Queue getTransmitQueue()
          Get the value of transmitQueue.
 int getType()
          Get the value of type.
 boolean isInSess(AIMSession sess)
          Determines whether this connection belongs to the given sesion.
static void killAllInSess(AIMSession sess)
          Kills all connections belonging to this session.
 void logOff(AIMSession sess)
          Log off of this connection.
 ListenerEntry lookupListenerEntry(int family, int subtype)
          Look up a listener entry for this connection.
 ListenerEntry lookupListenerEntryCreate(int family, int subtype)
          Look up a listener entry for this connection.
 int nextId()
          Get the next SNAC ID.
 int nextMsgId()
          Get the next Msg ID.
 int nextPacketId()
          Get the next ICQ Packet ID.
 int nextSeq()
          Get the next FLAP sequence number.
 SNAC peekSNAC(int id)
          Peek at a SNAC in the SNAC hash table.
 void registerListener(int family, int subtype, Listener listener)
          Add the given listener to the given listener entry family for this connection.
 MsgCookie remCookie(MsgCookie cookie)
          Remove a message cookie for this session.
 SNAC remSNAC(int id)
          Remove a SNAC from the SNAC hash table.
 void run()
          The run method for this connection.
 void sendFrame(AIMFrame frame)
          Send a frame over the socket.
 void sendSignoff(AIMSession sess, AIMConnection conn)
          Send a sign off.
 void setFlags(int flags)
          Set the value of flags.
 void setForcedLatency(long forcedLatency)
          Set value of forcedLatency.
 void setGroups(java.util.ArrayList groups)
          Set the value of groups.
 void setHost(java.lang.String host)
          Set the value og host.
 void setInternal(java.lang.Object internal)
          Set value of internal.
 void setLastActivity(long lastActivity)
          Set the value of lastActivity.
 void setPort(int port)
          Set the value of port.
 void setRetries(int retries)
          Set the value of retries.
 void setRetryTime(int retryTime)
          Set the value of retryTime.
 void setSocket(java.net.Socket socket)
          Set the value of socket.
 void setSubtype(int subtype)
          Set the value of subtype.
 void setType(int type)
          Set the value of type.
 boolean supportsGroup(int group)
          Find if a given group is supported by this connection.
 void updateRate(int classID)
          Update the rate with the given class ID.
 void updateRate(int family, int subtype)
          Update the rate with the given SNAC family and subtype.
 
Methods inherited from class java.lang.Thread
activeCount, checkAccess, countStackFrames, currentThread, destroy, dumpStack, enumerate, getContextClassLoader, getName, getPriority, getThreadGroup, holdsLock, interrupt, interrupted, isAlive, isDaemon, isInterrupted, join, join, join, resume, setContextClassLoader, setDaemon, setName, setPriority, sleep, sleep, start, stop, stop, suspend, toString, yield
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

AIMConnection

public AIMConnection(AIMSession sess,
                     int type,
                     java.lang.String dest,
                     ProxyConnection pc)
Creates a new AIM connection with a proxy.

Parameters:
sess - the oscar session
type - the type of connection
dest - the destination ip:port as a string
pc - ProxyConnection

AIMConnection

public AIMConnection(AIMSession sess,
                     int type,
                     java.lang.String dest)
Creates a new AIM connection.

Parameters:
sess - the oscar session
type - the type of connection
dest - the destination ip:port as a string
Method Detail

nextSeq

public int nextSeq()
Get the next FLAP sequence number.

Returns:
the next sequence number

nextId

public int nextId()
Get the next SNAC ID. For AIM, we use a sequential SNAC ID. For ICQ, see elsewhere in the code.

Returns:
the next SNAC ID

nextPacketId

public int nextPacketId()
Get the next ICQ Packet ID.

Returns:
the next ICQ packet ID

nextMsgId

public int nextMsgId()
Get the next Msg ID. Start at 0xffff and decrement by 1 until we reach 0x0000.

Returns:
the next ICQ message ID

getRetries

public int getRetries()
Get the value of retries.

Returns:
Value of retries.

setRetries

public void setRetries(int retries)
Set the value of retries.

Parameters:
retries - Value to assign to retries.

connect

public void connect()
             throws java.io.IOException
Connects to the ip:port specified in dest. Call this after you have created the AIM connection and set any other things that you needed to set.

Throws:
java.io.IOException - if an error occurs

getMembers

public java.util.ArrayList getMembers()
Get the value of members.

Returns:
value of members.

addGroup

public void addGroup(int version)
Add a group for this connection. See the description of this class for more information about groups.

Parameters:
version - the group version

getGroups

public java.util.ArrayList getGroups()
Get the value of groups.

Returns:
value of groups.

setGroups

public void setGroups(java.util.ArrayList groups)
Set the value of groups.

Parameters:
groups - Value to assign to groups

supportsGroup

public boolean supportsGroup(int group)
Find if a given group is supported by this connection.

Parameters:
group - the group
Returns:
true if supported, false otherwise

findByGroup

public static AIMConnection findByGroup(AIMSession sess,
                                        int group)
Find a connection that supports the given SNAC group.

Parameters:
sess - the oscar session
group - the SNAC group
Returns:
the connection if the SNAC group is supported, or null otherwise

isInSess

public boolean isInSess(AIMSession sess)
Determines whether this connection belongs to the given sesion.

Parameters:
sess - the oscar session
Returns:
true if the connection belongs to the fiven session, false otherwise

killAllInSess

public static void killAllInSess(AIMSession sess)
Kills all connections belonging to this session.

Parameters:
sess - the oscar session

getRates

public java.util.ArrayList getRates()
Gets the value of rates.

Returns:
value of rates.

addRate

public void addRate(RateClass rate)
Adds a rate to this connection.

Parameters:
rate - the rate to add

findRate

public RateClass findRate(int classID)
Find a rate by the guven class ID.

Parameters:
classID - the class ID
Returns:
the rate class if found, null otherwise

findRate

public RateClass findRate(int family,
                          int subtype)
Find a rate by a given SNAC family and SNAC subtype.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
Returns:
the rate class if found, null otherwise

getInputStream

public java.io.InputStream getInputStream()
Get the value of is.

Returns:
value of is.

getOutputStream

public java.io.OutputStream getOutputStream()
Get the value of os.

Returns:
value of os.

getHost

public java.lang.String getHost()
Get the value of host.

Returns:
value of host.

setHost

public void setHost(java.lang.String host)
Set the value og host.

Parameters:
host - Value to assign to host.

getPort

public int getPort()
Get the value of port.

Returns:
value of port.

setPort

public void setPort(int port)
Set the value of port.

Parameters:
port - Value to assign to port.

getType

public int getType()
Get the value of type.

Returns:
value of type.

setType

public void setType(int type)
Set the value of type.

Parameters:
type - Value to assign to type.

connKill

public static void connKill(AIMSession sess)
Closes all connections in the guven session.

Parameters:
sess - the oscar session.

sendSignoff

public void sendSignoff(AIMSession sess,
                        AIMConnection conn)
                 throws java.io.IOException
Send a sign off.

Parameters:
sess - the oscar session
conn - the bos connection for this session
Throws:
java.io.IOException - if an error occurs

close

public void close(AIMSession sess)
Close a connection.

Parameters:
sess - the oscar session

getTransmitQueue

public Queue getTransmitQueue()
Get the value of transmitQueue.

Returns:
value of transmitQueue.

getReceiveQueue

public Queue getReceiveQueue()
Get the value of receiveQueue.

Returns:
value of receiveQueue.

run

public void run()
The run method for this connection.


sendFrame

public void sendFrame(AIMFrame frame)
               throws java.io.IOException
Send a frame over the socket. FIXME: I can't even begin to describe what a hack ICQ packet handling is

Parameters:
frame - the frame to send
Throws:
java.io.IOException - if an error occurs

enqueueFrame

public void enqueueFrame(AIMFrame frame)
Push a frame onto the transmit queue.

Parameters:
frame - the frame to enqueue

lookupListenerEntry

public ListenerEntry lookupListenerEntry(int family,
                                         int subtype)
Look up a listener entry for this connection.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
Returns:
the listener entry if found, or null otherwise

lookupListenerEntryCreate

public ListenerEntry lookupListenerEntryCreate(int family,
                                               int subtype)
Look up a listener entry for this connection. If the entry exists, return it, else create a new listsner entry and return that listener transparently.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
Returns:
the listener entry

registerListener

public void registerListener(int family,
                             int subtype,
                             Listener listener)
Add the given listener to the given listener entry family for this connection. We could disallow certain SNAC pairs 0x0001/0x0002, 0x0001/0x0003, 0x0001/0x0006, 0x0001/0x0007, 0x0001/0x0008, 0x0001/0x0017, 0x0001/0x0018, but when the tools are implemented everything should start to work out.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
listener - the SNAC listener

deregisiterListener

public void deregisiterListener(int family,
                                int subtype,
                                Listener listener)
Remove a listener for this connection. Make sure that both the listener entry and the given listener exist for this connection before calling this method.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
listener - the SNAC listener

getListeners

public java.util.Iterator getListeners(int family,
                                       int subtype)
Get the connection listeners for the given SNAC family.

Parameters:
family - the SNAC family
subtype - the SNAC subtype
Returns:
the listeners

peekSNAC

public SNAC peekSNAC(int id)
Peek at a SNAC in the SNAC hash table.

Parameters:
id - the SNAC ID to look for
Returns:
the SNAC if found

remSNAC

public SNAC remSNAC(int id)
Remove a SNAC from the SNAC hash table.

Parameters:
id - the SNAC ID
Returns:
the SNAC that was removed

cleanSNACs

public int cleanSNACs(int maxAge)
Clean the SNAC hash table.

Parameters:
maxAge - maximum age of the SNAC's in seconds
Returns:
the number of SNAC's removed from the hash table

logOff

public void logOff(AIMSession sess)
Log off of this connection.

Parameters:
sess - the oscar session

getFlags

public int getFlags()
Get the value of flags.

Returns:
value of flags.

setFlags

public void setFlags(int flags)
Set the value of flags.

Parameters:
flags - Value to assign to flags.

getSocket

public java.net.Socket getSocket()
Get the value of socket.

Returns:
value of socket.

setSocket

public void setSocket(java.net.Socket socket)
Set the value of socket.

Parameters:
socket - Value to assign to socket.

getInternal

public java.lang.Object getInternal()
Get value of interbal.

Returns:
value of interbal.

setInternal

public void setInternal(java.lang.Object internal)
Set value of internal.

Parameters:
internal - Value to assign to internal.

getLastActivity

public long getLastActivity()
Get value of lastActivity.

Returns:
value of lastActivity.

setLastActivity

public void setLastActivity(long lastActivity)
Set the value of lastActivity.

Parameters:
lastActivity - Value to assign to lastActivity.

getForcedLatency

public long getForcedLatency()
Get value of forcedLatency.

Returns:
value of forcedLatency.

setForcedLatency

public void setForcedLatency(long forcedLatency)
Set value of forcedLatency.

Parameters:
forcedLatency - Value to assign to forcedLatency.

getSubtype

public int getSubtype()
Get the value of subtype.

Returns:
value of subtype.

setSubtype

public void setSubtype(int subtype)
Set the value of subtype.

Parameters:
subtype - Value to assign to subtype.

updateRate

public void updateRate(int classID)
Update the rate with the given class ID.

Parameters:
classID - the class ID

updateRate

public void updateRate(int family,
                       int subtype)
Update the rate with the given SNAC family and subtype.

Parameters:
family - the SNAC family
subtype - the SNAC subtype

getRetryTime

public int getRetryTime()
Get the value of retryTime.

Returns:
value of retryTime.

setRetryTime

public void setRetryTime(int retryTime)
Set the value of retryTime.

Parameters:
retryTime - Value to assign to retryTime.

getSess

public AIMSession getSess()
Get the value of sess.

Returns:
value of sess.

getICQHashtable

public java.util.Hashtable getICQHashtable()
Get the value of ihash.

Returns:
value of ihash.

getMsgCookies

public java.util.HashMap getMsgCookies()
Get the value of msgCookies.

Returns:
value of msgCookies.

addCookie

public void addCookie(MsgCookie cookie)
Add a message cookie for this session.

Parameters:
cookie - the message cookie to add

remCookie

public MsgCookie remCookie(MsgCookie cookie)
Remove a message cookie for this session.

Parameters:
cookie - the MessageCookie to remove.
Returns:
the removed MsgCookie or null if not found

cleanCookies

public int cleanCookies(int maxAge)
Clean message cookies.

Parameters:
maxAge - max age before cleaning the cookie
Returns:
the number of cookies cleaned

findByType

public static AIMConnection findByType(AIMSession sess,
                                       int type)
Finds the first connection of a given type belonging to this session.

Parameters:
sess - the oscar session
type - the type
Returns:
the first connection of the given type