August'24: Kamaelia is in maintenance mode and will recieve periodic updates, about twice a year, primarily targeted around Python 3 and ecosystem compatibility. PRs are always welcome. Latest Release: 1.14.32 (2024/3/24)
NOTE: These components implement the OSCAR protocol at the lowest level and require a fairly good knowledge of OSCAR to use them. For a high-level interface, see AIMHarness.py.
NOTE: A "byte" in the following documentation refers to an ASCII char, an unsigned char in C.
OSCAR messages are transmitted in discrete units called FLAPs, which take the following form:
-------------------------------------------
|FLAP-header |
| message start character (*) -- 1 byte |
| channel -- 1 byte |
| sequence number -- 2 bytes |
| length of following data -- 2 bytes |
|-----------------------------------------|
| ------------ |
||FLAP payload| |
| ------------ |
-------------------------------------------
The sequence number is incremented with every FLAP sent. AOL is very strict about in-order sequence numbers and servers may even disconnect a client for not sending the right sequence numbers.
The majority of FLAP payloads (everything except new connection notifications, really serious errors, shutdown notifications, and keepalives) are units called SNACs and are transmitted over channel 2.
The structure of a SNAC:
--------------------------
|SNAC-header |
| family -- 2 bytes |
| subtype -- 2 bytes |
| request ID -- 2 bytes |
| flags -- 4 bytes |
|------------------------
| -------------- |
| | SNAC payload | |
| -------------- |
--------------------------
All SNAC payloads must follow a prescribed format unique to the particular type of SNAC, but all SNAC headers must follow the format described above. Each different (family, subtype) performs a different function. For example, SNAC (04, 07) (meaning family 0x04, subtype 0x07) carries AIM messages from the server to the client, SNAC (01, 11) reports client idle times to the server, and (04, 06) carries a message from one user to another.
Yet another type of OSCAR datatype is a type-length-value (TLV) unit.
The structure of a TLV:
------------------------------------------
|TLV-header |
| type -- 2 bytes |
| length of following data -- 2 bytes |
|----------------------------------------|
| --------- |
| |TLV data | |
| --------- |
-----------------------------------------
TLVs may appear inside SNACs or just inside FLAPs.
OSCARProtocol receives messages on its "talk" inbox in (channel, flap body) format and retransmits them to "outbox" as true FLAPs. It receives FLAPs on its "inbox" inbox and retransmits them to its "heard" outbox in the format (channel, flap body). It also keeps track of sequence numbers.
OSCARClient returns a Graphline with an OSCARProtocol component's inbox/outbox connected to a TCPClient's outbox/inbox. The Graphline's inbox and outbox are l inked to the OSCARProtocol component's "talk" and "heard" boxes, respectively. Send (channel, flap body) tuples to its inbox and receive (channel, flap body) tuples from the outbox.
SNACExchanger provides specialized methods for dealing with SNACs. You must subclass it, as it does not have a main method.
To get an MD5 key from the authorization server during login:
class LoginHandler(SNACExchanger):
def main(self):
self.send((CHANNEL_NEWCONNECTION,
struct.pack('!i', 1)))
while not self.dataReady():
yield 1
reply = self.recv() # server ack of new connection
zero = struct.pack('!H', 0)
request = TLV(0x01, "kamaelia1") + TLV(0x4b, zero) + TLV(0x5a, zero)
self.sendSnac(0x17, 0x06, request)
for reply in self.waitSnac(0x17, 0x07): yield 1
md5key = reply[2:]
print ("%02x " * len(md5key)) % unpackSingles(md5key)
Graphline(osc = OSCARClient('login.oscar.aol.com', 5190),
login = LoginHandler(),
linkages = {("login", "outbox") : ("osc", "inbox"),
("osc", "outbox") : ("login", "inbox"),
}
).run()
For a more complete example, see LoginHandler.py
OSCARClient(server, port) -> returns an OSCARProtocol component connected to a TCPClient.
User input goes into OSCARClient's "inbox" in the form (channel, flap body) and useable output comes out of "outbox" in the same form.
OSCARProtocol() -> new OSCARProtocol component.
Provides a Kamaelia interface to the lowest level of OSCAR protocol, the FLAP level.
For more information on FLAPs, see module level docs.
Warning!
You should be using the inbox/outbox interface, not these methods (except construction). This documentation is designed as a roadmap as to their functionalilty for maintainers and new component developers.
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
checks for data in all our boxes, and if there is data, then call the appropriate function to handle it.
receives data coming in through the wire, reformats it into a Python-friendly form, and retransmits it to its "heard" outbox.
checks that incoming messages from the "talk" inbox are in a (channel, flap data) tuple. If not, exceptions are raised. If so, OSCARProtocol.sendFLAP is called.
main loop
constructs FLAPs and sends them
SNACExchanger() -> component that has methods specialized for sending and receiving FLAPs over Channel 2 (FLAPs whose payloads are SNACs).
For a more thorough discussion on SNACs, see module level docs.
Warning!
You should be using the inbox/outbox interface, not these methods (except construction). This documentation is designed as a roadmap as to their functionalilty for maintainers and new component developers.
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
receives FLAPs containing SNACs and parses the SNAC data.
constructs a SNAC by calling self.makeSnac and sends it out the "outbox".
FIXME: It would be extremely helpful to have a predefined set of SNAC constants or perhaps even classes to pass to this method. For example, self.sendSnac(04, 06, data) is a lot less clear than something like self.sendSnac(MESSAGE_TO_USER, data).
Yields 1 until a SNAC of the requested family and subtype is received. The last value yielded is the payload of the requested SNAC.
The body of the requested SNAC will be assigned to "result".
Got a problem with the documentation? Something unclear that could be clearer? Want to help improve it? Constructive criticism is very welcome - especially if you can suggest a better rewording!
Please leave you feedback here in reply to the documentation thread in the Kamaelia blog.
-- Automatic documentation generator, 05 Jun 2009 at 03:01:38 UTC/GMT