Issues while using DBUS over TCP

Schmottlach, Glenn GSchmott at harmanbecker.com
Wed Aug 6 07:09:06 PDT 2008


For the benefit of others who may be trying to do the same thing, I
*think* I have figured out how to use DBUS using TCP to provide a
RPC-like mechanism. This post contains some of the documentation of the
progress I have made to date.

 

Problem Description:

 

I am developing an embedded system running Linux and was originally
attracted to DBUS as a general purpose IPC mechanism to communicate
between various services (processes) that I write. Since this embedded
box is equipped with an Ethernet port and there are several language
bindings available for DBUS (including Python), I was hoping it would be
simple to communicate with my services on the target from a Python
script on a host (the embedded target will always reside behind the
firewall/router so security is not an issue for me). This is a great way
to test the target platform from the rich development environment of my
host system.

 

For this example (and for testing purposes) I wanted to run another DBUS
session bus that listened on a known TCP port. The first requirement is
to rebuild dbus-daemon with the following change. In this example I'm
using the sources from dbus-1.2.1. Looking in bus/bus.c:

 

Function: new_connection_callaback

 

I added the following call to dbus_connection_set_allow_anonymous()
around line 188:

 

Before:

=====

 

  dbus_connection_set_max_received_size (new_connection,
context->limits.max_incoming_bytes);

  dbus_connection_set_max_message_size (new_connection,
context->limits.max_message_size);

/* on OOM, we won't have ref'd the connection so it will die. */

}

 

After:

====

 

dbus_connection_set_max_received_size (new_connection,
context->limits.max_incoming_bytes);

dbus_connection_set_max_message_size (new_connection,
context->limits.max_message_size);

 

/* This allows anonymous connections */

dbus_connection_set_allow_anonymous(new_connection, TRUE);

 

/* on OOM, we won't have ref'd the connection so it will die. */

}

 

 

Once that's compiled you now have a DBUS daemon that will support
ANONYMOUS authentication over a TCP port.

 

The next step is to add a "session-local.conf" file to the same
directory where session.conf is typically stored (/etc/dbus-1). This
file (session-local.conf) will be automatically loaded in addition to
the session.conf file. I this file we list the ports where the DBUS
daemon should listen. Here's an example script:

 

<!-- This configuration file controls the per-user-login-session message
bus.

Add a session-local.conf and edit that rather than changing this file
directly.

-->

 

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration
1.0//EN"  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

 

<busconfig>

 

<!-- Our well-known bus type, don't change this -->

<type>session</type>

 

<!-- Binds to all localhost addresses -->

<listen>tcp:host=localhost,bind=*,port=6666</listen>

 

<!--   The order of the authentication mechanisms does matter. The
ANONYMOUS

mechanism must be listed LAST in order for external clients to bind
over TCP/IP.

-->

 

<!-

<auth>EXTERNAL</auth>

<auth>DBUS_COOKIE_SHA1</auth>

<auth>ANONYMOUS</auth>

-->

 

</busconfig>

 

Notice that I listen on ALL local interfaces on port 6666 (bind=*
ensures this occurs). If you just use 'localhost' here then typically
this will mean that only clients on the target itself will be able to
connect to your daemon (on 127.0.0.1) over TCP while external clients
(outside the target) will not. You can also explicitly specify the
external IP address if you do not want the use "bind=*" to enforce
binding to all local/external interfaces.

 

The DBUS documentation on authentication (<auth>) is a little sketchy
when it comes to ANONYMOUS authentication. Originally, I specified every
form of authentication I would allow. What I found out is that the order
in which these are listed is VERY important (and contrary to what the
dbus-daemon documentation seems to indicate). This was apparent when
using a Python client on the host computer. If I reversed the order in
which the ANONYMOUS authentication is specified from first to last (e.g.
<auth>ANONYMOUS</auth> comes first before the others) my Python client
could not authenticate successfully. Finally, I removed (by commenting
it out) all the <auth></auth> entries and my Python client can still
authenticates anonymously. Obviously, I am missing some subtle point
here that perhaps someone can point out.

 

The final hurdle involved creating a client connection from my host
computer using Python (on a Windows PC). Communicating over TCP using
the Python DBUS client isn't obvious. Here is the gist of the script:

 

import dbus

import dbus.glib

from dbus.mainloop.glib import DbusGMainLoop

 

class TcpSessionBus(dbus.bus.BusConnection):

   

   def __new__(cls, addr, mainloop=None):

      from _dbus_bindings import BUS_SESSION

      bus = dbus.bus.BusConnection(addr, mainloop=mainloop)

      bus._bus_type = BUS_SESSION

      

      return bus

   

   def get_connection(self):

      return self

   

   _connection = property(get_connection, None, None,

                           """self._connection == self, for backwards

                           compatibility with earlier dbus-python
versions

                           where Bus was not a subclass of
Connection.""")

          

def main():

   addr = 'tcp:host=192.168.217.129,port=6666'

   bus = TcpSessionBus(addr, DbusGMainLoop())

   # Use the bus as normal to create an object and then retrieve the

   # interface.

 

if __name__ == '__main__':

   main()

 

This is a hack (particularly the TcpSessionBus) class and obviously
could use some refinement. The default implementation of the Python
SessionBus class does not allow you to specify a TCP address and
required this work-around. Also, the "_connection" property of the
TcpSessionBus class is important or the Python Dbus implementation will
not wire up the bus class so that it can be used to receive
signals/events from the service.

 

In an effort to be complete, I built and installed my "modified"
dbus-daemon in a separate location from the default. The "configure"
script was invoked as follows:

 

./configure --prefix=/home/user/builds/dbus-1.2.1/publish
--with-xml=expat --exec-prefix=/home/user/builds/dbus-1.2.1/publish
-enable-verbose-mode

 

The "--enable-verbose-mode" is a helpful switch that will log debug
information while the daemon is running.

 

After configuring it I did the "make install" step to build and install
the dbus-daemon in a local directory.

 

Finally, I launched it like so:

 

 DBUS_VERBOSE=1 ./dbus-daemon --print-address
-config-file=/home/user/builds/dbus-1.2.1/publish/etc/dbus-1/session.con
f

 

 

I was able to communicate with a DBUS session service running on my
target platform using the modified dbus-daemon. I am sure some of my
steps or explanations can be improved by someone with a better
understanding of the DBUS architecture. I am open to any corrections or
improvements and I hope this helps someone contemplating a similar use
for DBUS. 
 
*******************************************
Diese E-Mail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtuemlich erhalten haben, informieren Sie bitte sofort den Absender und loeschen Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
 
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and delete this e-mail. Any unauthorized copying, disclosure or distribution of the contents in this e-mail is strictly forbidden.
*******************************************
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freedesktop.org/archives/dbus/attachments/20080806/029cf6d5/attachment-0001.html 


More information about the dbus mailing list