Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#849 closed task (complete)

DBus as possible replacement of MSGQ.

Reported by: vorner Owned by: vorner
Priority: medium Milestone: Sprint-20110419
Component: Unclassified Version:
Keywords: Cc:
CVSS Scoring: Parent Tickets:
Sensitive: no Defect Severity:
Sub-Project: Feature Depending on Ticket:
Estimated Difficulty: 1.0 Add Hours to Ticket: 0
Total Hours: 1.0 Internal?: no

Description

This is part of #765, I'm going to have a look at DBus if it would solve our problems with msgq.

Subtickets

Change History (9)

comment:1 Changed 50 years ago by vorner

  • Add Hours to Ticket changed from 0.0 to 1.0
  • Total Hours changed from 0.0 to 1.0

comment:1 Changed 9 years ago by vorner

  • Owner changed from vorner to UnAssigned
  • Status changed from new to reviewing

So, I discovered it might be usable, with some work.

Licence:
The core dbus (libdbus and dbus-daemon) have two licences (we can choose which one we use), GPL and some AFL. The AFL, according to what they claim, it is somehow more wordy MIT or BSD licence. Their FAQ says the code can be used in closed-sourced application, that it only forbids suing them around patents while still using their code. So, while I'm not a lawyer, my impression is this could be compatible.

Python bindings has some licence in the sense „you can do everything, only include the no-warranty disclaimer“, which we do anyway.

I looked for some C++ bindings of the low-level libdbus, but they are either abandoned, single-man show toolkit-based or GPL, so we would probably need to wrap around libdbus ourself. The libdbus is something that is meant to be integrated into something, they say it can be plugged into whatever mainloop or so, but it is really low-level.

Dependencies:
None for the libdbus, the dbus-daemon needs xml parser to read configuration (it is happy with either expat or libxml).

The python bindings need glib (either a new one, that includes dbus support in itself, or older and glib-dbus bindings). I don't know how big problem that is, but maybe the people who don't want glib on their system would be the same as those not wanting python there.

Platforms, stability, testing:
They say they run on anything UNIX-like (quick google query for solaris dbus showed some minor bugs, like it wants to be root if it should be the system message bus, so I deduce it runs there, we would run our own instance anyway). It seems quite widely used, both KDE and GNOME use it, most linux distros rely on the system daemon for all the new fancy hal daemons, bluetooth support, etc. The documentation claims they are one of the best OSS project regarding test coverage.

The windows port is merged into the main release for some time now and it is used over 3 years for KDE on windows, but they say some of the tests weren't ported to windows yet.

I guess it doesn't provide a mock class for testing.

Misc:
They use TCP connections on windows, so the communication is possible over something non-UNIX-socketish, but remote connection isn't implemented yet. They use some cookie for authentication. So, running over multiple machines would need some work (I didn't ask on the ML yet, this could be one of the questions).

They have a data type to send an unix file descriptor. It might error on sending it, if the connection or daemon doesn't support it, but it should work for „common“ unix scenario. Windows and cross-machine might be problem.

I did run multiple instances of dbus some time ago, and the dbus-daemon can be passed a different configuration file (instead of --system or --session) to start another daemon. It would just provide the environment variables needed for connecting to it.

Performance is hard to guess from what is found on the internet. However, they compare it with raw socket (I found 2.5 slower than passing trough raw socket, but then they rewrote some marshalling and validating of data since then, so it probably changed), other compared it with CORBA and said it was slightly slower. But that sounds like reasonable performance, really better than our python msgq implementation. And all their communication can be asynchronous, which helps real-life speed as well.

It is possible to declare types and public functions/interfaces, etc. to help some bindings and generating remote proxy objects, but it seems not to be mandatory.

Design:
Each application gets an unique address at connection, which is never reused. An application might claim a nickname (so we could have a config manager that would be called a config manager, no matter which address it got).

The system is somehow objectish, so an application might provide an object (or more of them, but currently it seems we would have single object per module) with methods (similar like our commands) and signals. There are also some interfaces which are implemented by objects (I didn't really read the documentation to depth, though, but this might turn out to ask for provided function signatures ‒ but we can use some variant or something generic enough) that state which methods are available on the object.

So, for example, for configuration, we would have an object that would be the configuration (in the manager) and it would have a method to provide the configuration values.

The signals are kind of broadcast. An object may emit signal to inform the world about something. Anybody is allowed (well, there can be some ACLs in the config file) to subscribe for notification of signal (or provide some pattern which signals to subscribe). So it's slightly inverse of what we have. In the example with configuration, it would have a signal „configuration changed“ (and it could carry the data as well).

Conclusion:
I see a way how to replace the msgq by dbus, which would have some advantages and disadvantages:

  • It has slightly different semantics, so we would need to modify the code a little bit (for example the inverse broadcasts)
  • It would require nontrivial amount of work (for example wrapping the libdbus for our needs, and, in future, probably implementing some kind of bridge between two dbuses across network, modifying some communication logic slightly, work around the need to provide interfaces).
  • We would get something that has a large userbase, reasonable performance, is reliable and has all the strange problems we're having (like short reads, filling buffers) already solved.
  • It allows people to write their modules in whatever language they like, there are binding to nearly everything (haskell, java, perl, Qt, …).
  • We might integrate better into the rest of the system. We could use the system bus by default and provide signals about important events, we might listen for events from NetworkManager? (not that I would believe many servers do have the beast).

Discussion welcome.

comment:2 Changed 9 years ago by vorner

I just looked at some bindings, perl ones are perfectly fine with ignoring interfaces, specifying whatever signatures, etc.

Python is fine with not providing interface when calling the method and uses the @decorator thingie to automatically generate all the fancy introspection stuff, so it's almost for free and others may benefit from it. So we probably don't need to worry about them much.

comment:3 Changed 9 years ago by stephen

  • Owner changed from UnAssigned to stephen

comment:4 follow-up: Changed 9 years ago by stephen

  • Owner changed from stephen to vorner

I agree with Michal and have the following additional comments:

Licence

  • Even with AFL "Some of the standalone binaries are under the GPL only" (from the source code's COPYING file). This raises the bar but does not necessarily rule it out - after all, if these are standalone, then BIND 10 will not be a "derivative work".
  • With AFL, we would need to prominently attribute in the source code that part of the code is D-Bus and subject to the AFL.
  • When AFL code is distributed, "You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License.". Obviously the question of "what is reasonable" is subject to interpretation but if the code is downloadable from a web site, I would argue that "reasonable" would include the need to check a box to confirm that person downloading the software has read the terms and conditions before the download is allowed.

However, as Michal noted, the FAQ explicitly states that it can be used in proprietary applications.

Bindings
Regarding the C++ bindings, D-Bus is written in C so it should not be an insurmountable problem to create a useful interface layer in C++. However, the documentation does warn "If you use this low-level API directly, you're signing up for some pain" which may indicate that coding our own binding in C++ will be far from straight forward.

Miscellaneous

  • Sending file descriptors for sockets between processes in Windows is awkward but can apparently be done through the function WSADuplicateSocket; whether D-Bus can handle this is another matter.
  • D-Bus comes with qdbus, a tool to examine the state of the bus and generally aid diagnosis of problems. This could prove very useful and avoid us having to write our own.
  • I'd see the real blocker in the use of D-Bus as being how important cross-machine communication is. TCP support appears to be very limited - two quotes from the D-Bus web pages are:
    • "Currently the communicating applications are on one computer, or through unencrypted TCP/IP suitable for use behind a firewall with shared NFS home directories."
    • "The TCP/IP transport isn't tested in use and it has the problems of access control, lack of encryption, and inability to go through firewalls and NAT."

Comments on Conclusions
I think this seems a good product, although I have the following reservations:

  • Licence: the fact that part of the distribution - even if only stand-alone applications - is GPL. Introducing that caveat into BIND 10 documentation may make people nervous.
  • The need to write our own C++ wrapper. This may be non-trivial. However, if we do this we should consider making it a separate project and making the output available to the D-Bus community.
  • If cross-machine support is required, the limited TCP support may be an insuperable hurdle.

For these reasons, I'd be keen to see if something else is better before making a decision to go with this one.

comment:5 in reply to: ↑ 4 Changed 9 years ago by vorner

  • Owner changed from vorner to stephen

Hello

Replying to stephen:

Licence

Well, it depends. We don't really want to distribute dbus ourself, do we? Just dynamically link libdbus (and it would be the same thing authors of proprietary extensions would do as well, I guess). Anyway, one of the first users of dbus was Skype, which has one of the worst proprietary licences. And they linked libdbus statically into their binary. Of course, they did not bundle dbus-monitor or any of these with it.

Bindings
Regarding the C++ bindings, D-Bus is written in C so it should not be an insurmountable problem to create a useful interface layer in C++. However, the documentation does warn "If you use this low-level API directly, you're signing up for some pain" which may indicate that coding our own binding in C++ will be far from straight forward.

As far as I understand this, in python, Qt, or whatever, you just say something like „This object is to be exported, these are the methods that should be exported“ and the bindings handle the rest.

With the libdbus, you actually need to know what kind of messages go over the wire, provide a callback where you get a message requesting running a method m on object x.y.z with parameter 42 and it's up to you to decide where do you get the x.y.z object, how to call it's method or what is an object anyway. But it'll handle marshalling the data structures that are sent, it will be able to connect, etc.

So, there is a gaph between them and it wouldn't be straight-forward (and we might try to have a look at some of the abandoned bindings to have a starting point, or something, maybe), but I think for our needs, something simple would be enough (we don't really need to be able to create proxy objects with full introspection of the remote end, etc).

Miscellaneous

  • I'd see the real blocker in the use of D-Bus as being how important cross-machine communication is. TCP support appears to be very limited - two quotes from the D-Bus web pages are:
    • "Currently the communicating applications are on one computer, or through unencrypted TCP/IP suitable for use behind a firewall with shared NFS home directories."
    • "The TCP/IP transport isn't tested in use and it has the problems of access control, lack of encryption, and inability to go through firewalls and NAT."

Yes, and it's because there was no need for this on their side ‒ freedesktop and dbus is mostly interested in desktop usage. So they go as far as they need ‒ some people have multiple computers with shared home, so they can have shared dbus for multiple logins. Nobody really needed encryption or some real ACL (except for the basic allowed/not allowed to connect ‒ note that DBus has the ability to do full ACLs on per-message basis, so the missing ACL would mostly mean they can't do the ACLs based on IP address, etc, once the connection is made, the connectee is fully trusted as local). It might be a worthwhile idea to persuade someone that he really wants to have his Empathy running across multiple computers that aren't on the same LAN and have him write it >:-).

The fact that windows version uses TCP/IP over localhost makes me think the data go well over the connection, so the only need would be to place some better authentication in front of the connection and wrap it into encryption. Traversal trough NAT, is it really a problem for us? Can't we expect all the clustering machines would see each other?

Anyway, how much do we need from it? If we didn't need encryption (and said that if the clustering servers are in different locations, the admin should use vpn or something), it might be more or less enough. Because, from dbus-daemon manpage, about how it can listen:

Example: <listen>unix:path=/tmp/foo</listen>
Example: <listen>tcp:host=localhost,port=1234</listen>

and about authentication to connect:

Example: <auth>EXTERNAL</auth>
Example: <auth>DBUS_COOKIE_SHA1</auth>

Should I try some experiments with it?

Anyway, it sounds like better state than current msgq has ‒ we don't really have any authentication, do we? And we aren't able to listen on TCP.

And if it really was a problem, we could do a small hack ‒ create a bridge application, that would sign for all signals, on local dbus, presented all objects from the remote end on it's connection and used the libdbus in one-to-one mode to connect with the bridge on the other side and forward it in between.

For these reasons, I'd be keen to see if something else is better before making a decision to go with this one.

Agreed, I'm going to have a look at more options. We really want the best thing available ;-).

comment:6 follow-up: Changed 9 years ago by stephen

  • Owner changed from stephen to vorner

Well, it depends. We don't really want to distribute dbus ourself, do we? Just dynamically link libdbus (and it would be the same thing authors of proprietary extensions would do as well, I guess).

Some used of BIND (including those putting it in embedded systems) might need to link statically. However is Skype can do it, I guess that BIND 10 users can as well.

...and the bindings handle the rest.

That's what I call optimism :-) But seriously, I'm surprised that there is no fully-supported C++ binding it it were that easy.

TCP Support...

All you say is very true.

I suggest that you close this ticket now; it won't preclude anyone from adding comments, but you've done all the work you're likely to do on it. The comparison between alternatives can be done under #765.

comment:7 in reply to: ↑ 6 Changed 9 years ago by vorner

  • Add Hours to Ticket changed from 0 to 1
  • Resolution set to complete
  • Status changed from reviewing to closed

Hello

Replying to stephen:

...and the bindings handle the rest.

That's what I call optimism :-) But seriously, I'm surprised that there is no fully-supported C++ binding it it were that easy.

It's always optimism to say that it does what it is designed to do, but it's easier to say than „it handles 94.6% of the rest“ ;-).

Anyway, the reason for not having C++ bindings is that actually, dbus is mostly for desktop and desktop applications which are written using a toolkit. Both Qt and glib have good bindings, but they are close to the philosophy of the library and I don't think we would like to start using Qt in BIND because of that. These days, nobody really writes in plain C++ (at last not for the desktop).

I suggest that you close this ticket now; it won't preclude anyone from adding comments, but you've done all the work you're likely to do on it. The comparison between alternatives can be done under #765.

Yes, it makes sense. OK.

comment:8 Changed 9 years ago by vorner

  • Estimated Difficulty changed from 0.0 to 1
Note: See TracTickets for help on using tickets.