

libicq2000 Tutorial

Barnaby Gray [mailto:barnaby@beedesign.co.uk||barnaby@beedesign.co.uk] 

April 4th, 2002 

Abstract

libicq2000 is an opensource C++ library being developed to
support the icq2000/2001 protocol. It is easy for developers
to use as the backbone for their clients' connection to
the ICQ network - all the protocol work is abstracted away
in one nice object-orientated interface. 

Table of Contents

1 About libicq2000 
    1.1 The library 
    1.2 Design Concepts
    1.3 Features supported
2 Library basics
    2.1 The library object
    2.2 Callbacks
    2.3 libicq2000 callbacks
3 Getting it working
    3.1 Sockets



1 About libicq2000 

1.1 The library 

libicq2000 was begun as the protocol backend for the opensource
gtk-- client [http://ickle.sourceforge.net/||ickle].
It was always designed as a separate library, and soon after
it's creation, it became apparent it would be widely useful
for many other clients too, so the library project was split
off. Although the main work of development is still done
by the original ickle developer (me), there are quite a
few clients using the library, and quite a network of developers
contributing bits and pieces every now and again. Join in
the community!

The library is all coded in C++ and uses the STL extensively.
It should compile fine with gcc 2.95.x, 2.96 and 3.0.x.

1.2 Design Concepts

libicq2000 is designed as a single threaded model of execution,
with the main loop of control being in the client. To this
end, the client using the library may be single or multi-threaded,
the choice is up to you. You will find out later within
this tutorial how this works. The library is designed to
be robust, and even though I'm not going to make an OpenBSD
style claim of security, it certainly should cope well with
any kind of crap thrown at it in terms of protocol.

1.3 Features supported

Currently libicq2000 supports:

* Message sending/receiving

* URL sending/receiving

* SMS sending/receiving, including delivery reports (SMTP
  gateway delivery too)

* Status changes

* Authorisation Requests

* "You were added" messages

* Fetching user info from server (both basic and advanced)

* Fetching away messages

* Setting custom away messages

* Direct Connections

* Invisibility, including visible/invisible lists

* Ignore lists

2 Library basics

2.1 The library object

Your main access to the library is through the ICQ2000::Client
object. You can construct one of these either with no parameters,
or provide the UIN and Password at construction. It's up
to you - if you don't provide them then you will need to
set them with the methods setUIN and setPassword before
connecting.

// Simple example (1)

#include <libicq2000/Client.h>

int main(int argc, char *argv[]) {

  ICQ2000::Client icqclient;

}

Now for some explanation of how to compile with the library.

The library as installed from one of the release tarballs
installs the executable libicq2000-config in /usr/local/bin
by default. You should use this to get the compile-time
flags that will depend on where the user has installed the
headers for the library, etc... To get the include directory
flags pass the --cflags option, to get the library linker
flags, pass the --libs option.

So for our simple example, save the above code as simple.cpp
and compile as:

# g++ simple.cpp -o simple `libicq2000-config --cflags --libs`

(Note the backticks ` around libicq2000 part of the command
line)

This should compile and link fine, then you can execute it
by typing:

# ./simple

Wow, big deal - it obviously won't do much yet!

2.2 Callbacks

Before we can get further into this tutorial the callback
system in the library needs to be explained a little. It
is built around the excellent C++ framework libsigc++. You
should read the documentation for libsigc++ before continuing
further. In case you can't particularly be bothered (I know
I wouldn't have), here's a brief enough introduction hopefully
to get by. libsigc++ has objects called SignalN which represent
signallers in a signal-slot architecture. You connect up
'slots' to these, with a slot representing a callback within
your application. So, something like:

myclient.connected.connect( slot( this, &MyClient::connected_cb
) );

Assuming you have a method declared in your MyClient class
as:

class MyClient {

   ...

   void connected_cb(ConnectedEvent *ev);

   ...

}

This means whenever inside the library it signals that it
is connected to the network (by emitting a signal on the
connected signaller), your MyClient connected_cb method
will be called, with the ConnectedEvent the library constructs
passed to it as the first parameter.

The slot function (part of libsigc++) can also construct
Slot objects for normal static functions, static (class)
methods as well as object methods as shown above. However,
I usually find object methods the most useful. The beauty
of libsigc++ is it makes how the client decides to use the
library independant from how the library operates. You,
the client programmer, decides what you want called-back
in your client when events happen in the library, and you
can have multiple methods called-back too.

2.3 libicq2000 callbacks

Having got that stuff out of the way, here's the specifics
to libicq2000.

libicq2000 has the following callbacks. These are listed
here as a brief summary, fuller explanation follows:

connected emitted when connection to the network has succeeded

disconnected emitted when disconnection from the network
  has happened (whether requested, or due to errors)

messaged emitted when someone sends a message to you

messageack emitted when a message you are attempting to
  send to someone is successfully delivered

contactlist emitted on Contact List Events - when someone
  is added to or removed from the contact list inside the
  library

contact_userinfo_change_signal emitted when the user information
  for a contact on your contact list is changed. This will
  happen when you fetch their user information from server,
  or when you set it yourself on the contact.

contact_status_change_signal emitted when a contact on
  your contact list changes status, eg. when they go online,
  go away, etc..

newuin emitted after you have requested a new UIN from
  the server, and registration has succeeded

logger emitted when the library has generated a log message

socket emitted when the library wishes to register a socket
  callback with the client

self_contact_userinfo_change_signal emitted when your user
  information is changed

self_contact_status_change_signal emitted when your status
  is changed

want_auto_resp emitted when someone requests your away
  message

search_result emitted when more search results have been
  received for a search the client initiated

3 Getting it working

3.1 Sockets

Due to the way the library's threadedness works, unfortunately
the raw guts of the socket part of the library must be exposed
to the client. Since the library makes socket connections
to the server (and between clients) it needs to wait on
these sockets for incoming data. But the library can't block
on a socket, as then your client will be unable to do anything.
The standard (well-behaved way) of waiting on sockets is
with the select function. If you don't understand how the
select libc function works you should read up on it now
(man 2 select).

Your client should register a callback with the socket signaler.
The library will emit a signal on this signaler when it
wants the client to wait on read or write on socket for
it. This signal is emitted with a ConnectedEvent. The client
should then add this to lists it keeps of read, write or
exception sockets and use these with the select call. When
the select call returns on with read or write on a socket
the library signaled to it, the client should call Client::socket_cb
with the relevant file descriptor passed as the parameter.
Hopefully a brief example will illustrate this:

OK, enough babbling around, let's get something working.

