An Overview of libmsn

Author: Mark Rowe
Contact: bdash@users.sourceforge.net
Version: overview.txt 339 2005-02-06 06:50:39Z bdash
Status: Work in Progress

Contents

This document contains a high level overview of libmsn 3.2. libmsn 3.2 is based on Meredydd Luff's libmsn 2.1, but is closer to a complete rewrite than a new version.

An Overview of the MSN Messenger System

Communication with MSN Messenger takes place in connections to two primary types of servers. A connection is established with the notification server when you signed in, and this connection is maintained until you sign out of the service. Instant messages to other users take place after connecting to switchboard servers. A connection is made to a switchboard server for every conversation that you take part in.

The notification server is responsible for managing your online presence, buddy list, and dispatching invitations to join conversations to your buddies. It also notifies you of changes in your buddy's status, and when a buddy requests your presence in a chat.

The switchboard server's sole responsibility is the transmission of messages between buddies. Connections to the switchboard server map one-to-one to the concept of a conversation with one or more buddies. That is to say, a switchboard connection is opened for every conversation that you participate in.

For more detailed information about the MSN Messenger system, you should look to the hypothetic.org MSN Messenger protocol documentation.

An Introduction to libmsn

libmsn is a single-threaded, asynchronous library that is written in C++. All of it's code is defined within the namespace MSN. In this documentation, the qualifying MSN:: will omitted for the sake of brevity.

The Library's Files

All code that needs to access libmsn's functionality should use the following syntax to include it's headers:

#include <msn/msn.h>

Bare in mind that you will need to instruct your compiler to link to the libmsn library. This can be done by passing -lmsn as an argument to gcc.

Communication with the Library

Communication with libmsn is done via an object-oriented API and user-provided callback functions. An instance of a user-defined subclass of MSN::Callbacks should be passed to the NotificationServerConnection constructor. All callbacks are declared within msn/externals.h. All callbacks listed need to be defined, otherwise you will get linker errors when you attempt to build your program. Many of the callbacks can be defined as an empty function, but those listed under Required Callbacks need to be implemented with the documented semantics.

Core Classes

To use libmsn you need to be aware of several key classes.

NotificationServerConnection
This represents a connection to a notification server, and provides the ability to change your online status, manipulate your buddy list, and request a new switchboard server connection.
SwitchboardServerConnection
This represents a connection to a switchboard server, and provides the ability to invite additional users into the switchboard session, and to send a message to the members of the session.
FileTransferInvitation
This represents an invitation to either send or receive a file to or from another buddy. It allows you to accept or decline the transfer, and monitor it's progress.
Message
Message represents a message that will be sent to a switchboard session.

Basic Program Flow

Below is a list of the general program flow and interaction with libmsn.

  1. Create a NotificationServerConnection with the correct username and password, and ask it to connect to messenger.hotmail.com on port 1863:

    struct pollfd mySockets[32];
    int numberOfSockets = 0;
    MSN::NotificationServerConnection *mainConnection;
    Callbacks cb;
    
    mainConnection = new
        MSN::NotificationServerConnect("myPassport@example.com", 
                                       "myS3cr3t",
                                       cb);
    mainConnection->connect("messenger.hotmail.com", 1863);
    
libmsn will then register and unregister sockets to be checked for completed connections, available data, and writability by calling MSN::Callbacks::registerSocket and MSN::Callbacks::unregisterSocket one or more times as is appropriate.
  1. Enter your main event loop. This may be based on select, poll, or a similar API that will notify you when data is available on a given socket:

    poll(mySockets, numberOfSockets, -1); 
    
  2. Inform libmsn when data has a socket connection has completed, data has arrived on a socket, or a socket has become writable. This can be done by using the Connection object's socketConnectionCompleted, dataArrivedOnSocket, and socketIsWritable methods as is appropriate:

    MSN::Connection *c;
    
    // Retrieve the connection associated with the
    // socket's file handle on which the event has
    // occurred.
    c = mainConnection->connectionWithSocket(mySockets[i].fd);
    
    // if this is a libmsn socket
    if (c != NULL)
    {
        // If we aren't yet connected, a socket event means that
        // our connection attempt has completed.
        if (c->isConnected() == false)
            c->socketConnectionCompleted();
    
        // If this event is due to new data becoming available 
        if (mySockets[i].revents & POLLIN)
            c->dataArrivedOnSocket();
    
        // If this event is due to the socket becoming writable
        if (mySockets[i].revents & POLLOUT)
            c->socketIsWritable();
    }
    
  3. When a socket used by libmsn is closed, you should delete the Connection object that it is associated with:

    MSN::Connection *c;
    
    // Retrieve the connection associated with the
    // socket's file handle on which the event has
    // occurred.
    c = mainConnection->connectionWithSocket(mySockets[i].fd);
    
    // if this is a libmsn socket
    if (c != NULL)
    {
        // Delete the connection.  This will cause the resources
        // that are being used to be freed.
        delete c;
    }
    

These four steps are all that is required to use libmsn. Your program code can then use the API that is provided to manipulate your buddy list, request switchboard sessions, and send instant messages.

Callbacks

Required Callbacks

The following callbacks are required by libmsn to implement the documented semantics as they are used to integrate with your program:

int MSN::Callbacks::connectToServer(std::string server, int port, bool *connected)
Return an integer containing a socket that has been connected to server:port. libmsn will call this when it wants to establish a connection a computer named server that is listening on port. The value true should be stored in *connected if the connection has completed, or false if the connection did not complete. -1 should be returned if an error occurs.
void MSN::Callbacks::registerSocket(int socket, int reading, int writing)
Called by libmsn to inform you which events you should watch for on socket. If reading is true, then libmsn wishes to be informed when data arrives on the socket. If writing is true, libmsn wishes to be informed when it is possible to write data to socket.
void MSN::Callbacks::unregisterSocket(int socket)
Called by libmsn to inform you that it no longer wishes to be notified of events relating to socket.

Optional Callbacks

All other callback functions may optionally be implemented. If you have no use for the callback, it may be defined as an empty function.

Common Tasks

Requesting a Switchboard Session

A switchboard connection is required for interaction with any other buddy on the MSN Messenger service.

You can use the NotificationServerConnection's requestSwitchboardConnection method to request a session. You may pass an optional piece of data as the tag argument so that you can identify this switchboard request:

// Request a switchboard session, using requestContext to allow
// us to identify this session request

void *requestContext = <some data>;
mainConnection->requestSwitchboardConnection(requestContext);

MSN::Callbacks::gotSwitchboard will be called when the requested switchboard session is established.

Inviting Buddies Into a Switchboard Session

Once you have established a switchboard session, you need to invite your receiving buddy into the session. You can do this by using the SwitchboardServerConnection's inviteUser method. Note that the buddy is not considered to have joined the session until MSN::Callbacks::buddyJoinedConversation has been called with the switchboard server and buddy as arguments.

Sending Instant Messages

When your switchboard session has been established, and buddies invited, you can then send an instant message. libmsn represents messages with it's Message class, so an instance needs to be created that contains the message that you wish to send. This instance will then allow you to control such things as the font and color that the message will appear in. The message can then be transmitted into the switchboard session by using the SwitchboardServerConnection's sendMessage method:

MSN::SwitchboardServerConnection *theSwitchboard =
                                       <a switchboard connection>;
MSN::Message msg(myMessageText);
msg.setFontName("Courier New");
msg.setFontEffects(MSN::Message::ITALIC_FONT);

theSwitchboard->sendMessage(&msg);