Trac is being migrated to new services! Issues can be found in our new YouTrack instance and WIKI pages can be found on our website.

Changes between Version 9 and Version 10 of GSoC2010/DetachableLibpurple


Ignore:
Timestamp:
Apr 29, 2013, 12:13:08 AM (11 years ago)
Author:
gillux
Comment:

Added technical documentation

Legend:

Unmodified
Added
Removed
Modified
  • GSoC2010/DetachableLibpurple

    v9 v10  
    5858
    5959= Details of the hack =
    60 Here is an outline of how I think to manage this project.
    6160== Drawing ==
    6261{{{
     
    6665                                            +---------------------------+
    6766}}}
     67The idea is to have libpurple acting as a daemon on one side, and as a client on the other side. DBus is used as the RPC mechanism. Because I care about security, we may forward the data over a custom tunnel as described in [http://dotsec.fr/~gillux/detachable_sessions2.svg this drawing].
    6868
    69 == For the minimal version ==
    70  * '''Daemon wrapper''' Create a daemon program that basically runs libpurple which activates the configured accounts, connect to servers… This daemon also listens for incoming clients connexions.
    71  * '''Detached mode''' Current standalone mode of clients is kept as a default. Add an option in them to run in detachable mode. The aim is to have to change the libpurple API (and hence the clients) as less as we can. Ideally, they would only have to tell libpurple they want to use the detached mode, and then use it as usual. And all these libpurple calls and events are transparently routed from/to the daemon.
    72  * '''Attaching and detaching''' Modify the daemon to handle the attaching of a client. It means sending to the client all it needs to be in the current state of the daemon. This includes things like active accounts, buddy list and chat logs. Detaching is much easier but has to be handled aswell.
    73  * '''Clients synchronization''' Modify the daemon's libpurple to get a full synchronization of events coming in and out of all the clients. For example, one client call would appears as an event for the others clients.
     69== Technical details about the current implementation ==
     70We just forward API calls, object properties and signals between daemon and clients through dbus. The daemon “UI” is located in purpled/, and the dbus code reside in libpurple/dbus/.
    7471
    75 == For the remote version ==
    76 Identify then adapt each part of libpurple which aren't remote-friendly, such as audio and video streams or file transfers. For instance in the latter case, files must be transfered to/from the daemon while it sends/receives them.
     72Let’s imagine we have a !PurpleFoo gobject in libpurple/foo.c. First, libpurple/dbus/foo.xml contains what parts of !PurpleFoo are exported on dbus. A python script generates libpurple/dbus/foo.xml.h from this XML,
     73which is basically a C struct version of the XML. This XML data is called “introspection data” in dbus terminology. Just call purple_object_class_register_dbus_iface() giving this C struct data as
     74argument, and all the properties and signals listed in the XML get automatically synchronized between clients and daemon.
    7775
    78 == Communication ==
    79 DBus will be used to make the daemon<->UI client communication. I needed something that support bidirectional calls and over multiple peers. For remote communications there is a TCP layer implemented. However there are some drawbacks in this TCP layer: the lack of authentication and encryption. I plan to overcome those using a custom tunnel as described in [http://dotsec.fr/~gillux/detachable_sessions2.svg this drawing].
     76The usual initialization code of !PurpleFoo from libpurple/foo.c gets
     77extended by calling two functions from libpurple/dbus/foo.c: one for
     78the class and one for the objects. For instance we have
     79purple_account_class_dbus_init() called from purple_account_class_init()
     80and purple_object_dbus_init() called from purple_account_new(). This
     81extra initialization code will do different things depending on the
     82running mode flag.
     83
     84The running mode flag is a boolean field of !PurpleCore which says
     85whether the libpurple acts as a daemon, a client, or in normal mode.
     86Typical code is if(purple_core_is_daemon_mode()) {...}. The idea is
     87that the detachable session functions are common between client and
     88daemon, but what gets actually executed internally is different
     89depending on the context.
     90
     91To export a method, we just call purple_object_bind_dbus_callback()
     92in the extra dbus initialization part. Simple functions such as
     93purple_account_connect() can be directly binded to a dbus method,
     94whereas more complex ones requires an extra wrapper function, such as
     95purple_account_register().
     96
     97== What needs to be done ==
     98First, gobjectification.
     99
     100Then, export the gobjectified parts on dbus so that everything is nicely synchronized between clients and daemon. This should be easy as it mostly consists of adding wrapper code.
     101
     102Other than that, the initialization part of libpurple will need to be
     103adapted for the clients. Currently, libpurple gather data from
     104~/.purple/ during its initialization part '''only'''. However we need to be
     105able to load this data remotely and anytime after libpurple has been
     106initialized.
     107
     108There are two approaches to get the whole thing working. Quick and dirty
     109way and clean and right way. Quick and dirty way is e.g. to simply
     110replace the call purple_blist_load() by a purple_blist_load_RPC() one that grabs the buddy list from the daemon instead of the local blist.xml. This is obviously wrong because it freezes the UI and cannot handle network errors neither do retries. But it works with very minimal effort. And this is how things are currently done.
     111
     112The clean and right way is to first initialize libpurple without loading anything from ~/.purple/, and then to get the data from the daemon. I can imagine having a separate Pidgin launcher for detachable sessions, which would prompt the user for the daemon’s IP first, properly show any network errors etc.
     113
     114And finally, many extra things that don’t prevent detachable sessions from basically working, such as handling of downloads, searching through logs, getting logs of what happened while a client was disconnected etc. This is probably a lot of work.
     115
     116Also, we need to encrypt and authenticate the data between clients and daemon through a tunnel. Since gdbus allows to run a custom dbus
     117server, and to connect to a particular server, it should be possible to
     118forward the dbus connection through a custom tunnel.
All information, including names and email addresses, entered onto this website or sent to mailing lists affiliated with this website will be public. Do not post confidential information, especially passwords!