Skype and DBus: should my client library act as a server?

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Mar 10 04:29:39 PDT 2015


On 09/03/15 23:31, Julien JPK wrote:
> Skype provides a single object: /com/Skype. This object has one method:
> Invoke(String).

This is poor D-Bus API design; but if you're using a proprietary service
like Skype, you're stuck with how they have chosen to design their API.

> However, when Skype has too much data to reply, it returns an empty
> string instead, and ends the method call. [...] After
> returning "", Skype began building its heavy reply, and when it was
> done, tried to contact my program (library) through a completely
> different object and interface.

This is also poor D-Bus API design, particularly if they do not document
that this is how it works; but again, if you're using Skype, you're
stuck with their choice of API.

> As you can see, while the Invoke(String) call returned nothing,
> it seems like Skype did try to reply later on, through a different
> method: my chat messages are sent to my program through a Notify(String)
> method [...] Does this mean that, while it is designed to act as a
> client component, my library should register an object to the session
> bus, and be ready to receive replies through it, while it sends requests
> through Skype's /com/Skype object, in FTP duplex-fashion?

Yes, it looks like that is the intention. If you don't like that design
you'd have to take that up with Skype.

> If so, would any of you have some pointers as to how I can register
> objects and their methods using the low-level API?

* Don't. High-level APIs are there for a reason. I would suggest
exporting a high-level object using gdbus-codegen, or at least the
semi-high-level GDBusInterfaceSkeleton (which is what the code generated
by gdbus-codegen uses).

* For C or C++ without Qt, prefer GDBus (a reimplementation) over
libdbus. You can still use the low-level APIs that  in GDBus - libdbus
only has semi-low-level and really-low-level message-passing-based APIs,
whereas GDBus has both a message-passing layer equivalent to libdbus,
and higher-level object-oriented layers on top of that.

* Don't. High-level APIs are there for a reason. :-)

* g_dbus_connection_register_object() (or its slightly lower-level
libdbus equivalent dbus_connection_register_object_path()) is the
canonical semi-low-level way to register objects to receive method calls.

* If you insist on torturing yourself with low-level details, use
g_dbus_connection_add_filter() or dbus_connection_add_filter() to filter
incoming method calls, reply to them, and mark them as "I handled this"
so that the library does not send back a redundant error reply. (But
seriously, don't do this. I'm a D-Bus maintainer who does know the
low-level details, and I avoid these functions unless absolutely
necessary - part of the reason for high-level API patterns is to guide
application authors towards doing the right thing, whereas the
lower-level message-passing APIs give you plenty of scope for shooting
yourself in the foot.)

> I do understand the
> concepts themselves (having read "An Introduction to the Basics" [1] and
> a few others)

I hope you are aware of the cognitive dissonance involved in reading an
introduction to the basics, and then doing things that the D-Bus
maintainer specifically advises against :-)

If you want to see the messages that result from a higher-level API, all
the D-Bus implementations I'm aware of are open source, so you can
always look at exactly what they're doing on your behalf. (Also, I see
you've already discovered dbus-monitor, which, again, tells you what is
going on at the message-passing level.)

-- 
Simon McVittie
Collabora Ltd. <http://www.collabora.com/>



More information about the dbus mailing list