Request for the 1.0 release
Havoc Pennington
hp at redhat.com
Sat Feb 25 17:01:26 PST 2006
On Sun, 2006-02-26 at 00:46 +0100, Thiago Macieira wrote:
> Havoc Pennington wrote:
> >I think we could have a dbus_connection_set_allow_peer_to_crash_me() and
> >the apps in a desktop session could set this when talking to the system
> >or session bus. The bus itself I'd prefer to keep the validation turned
> >on.
>
> That depends on the underlying OS having support for the TCP Security
> Flag, as defined by RFC 3514.
haha ;-)
> And just as information, in DCOP, the distinction between object names and
> interfaces was lost a long time ago. Just as with the Hal example, the
> object name was mandated, so that callers knew what objects to talk to.
> It even happened quite often that the object name contain the
> word "interface" (prime example: the "MainApplication-Interface" object
> in all KDE applications). This became the standard practice, so the whole
> concept of interface was forgotten in DCOP, even though it is still
> supported by the library.
I think of the interface as purely a namespace on methods, really. There
isn't any real need for interfaces in the wire protocol unless we allow
overloading of two methods with the same name on the same object. In the
introspection data, interfaces are nice since you can have some kind of
default name for the proxy object. Right now, interfaces are mostly
optional from my point of view (we were just discussing changing that of
course)
> When two objects of the same type were added to the same application, they
> distinguished by appending a number -- for instance, mainwindow#1,
> mainwindow#2, etc.
In general I found the dcop way of doing this hard to understand also;
what I was trying to do with dbus was just map exactly to the concepts
(process, interface, pointer) that people already knew. Obviously it did
not work, since dozens of people have mailed the list in confusion about
this, but hey, I tried.
I still wonder if it will be clearer once people are using bindings
instead of libdbus; with libdbus it isn't obvious that the thing is
supposed to map to object-oriented concepts, while if you're using
objects already, maybe it is clearer that your object has interfaces and
that it has an object name.
I don't think we should change the model too much at this point, it will
just make the confusion worse (and require a lot of work), but the
various ideas about default namespaces, default interface/object names,
etc. are worth exploring.
> >It might be cute to have the idea of some kind of "default" interface
> >and "default" object so that callers can skip the interface and object
> >names, but nobody quite figured out how that would work yet.
>
> Interesting. This is the behaviour in DCOP.
>
> It is implemented by making a call to an empty object name -- analogous to
> the empty interface name case.
>
> Of course, it doesn't have to be an empty name. It could be a default name
> ("/default" or even "/").
I think if we said a method call or signal without an object path was
implied to have the path "/" then that would be fine. Just a matter of
coding it in dbus_message_get_path, and then adapting bindings/code
accordingly.
We would have to say perhaps that libraries can't register anything at
this path, only the application can register the default object, since
normally it should implement application-specific stuff. Or we could
invent a way to support multiple handlers at this path or something.
> By the same token, the default interface case can be handled either by an
> empty name or by a default name (say, "org.freedesktop.DBus.Default").
We already support omitting the interface I think (except the bug you
found)
> Which they can already do by opening *different* connections. As I said, I
> am contemplating always opening private DBusConnections in the bindings
> to prevent this kind of "stepping on my toes".
It's fine to do this in moderation, DBusConnection is designed to be
shared though (like the X display connection). The problem with lots of
different connections is, well, lots of different connections -
certainly we wouldn't want one per-object or
per-library-in-the-desktop-stack. The DBusConnection object isn't small,
and file descriptors have some overhead too.
One main loop has to "own" each connection though, so in practice an app
or library has to know if it's the one that's responsible for the main
loop stuff.
> By the way, in case the user did not set the organizationDomain for his
> app, the binding defaults to a prefix of "local"
> (i.e., "local.MyClassName"). According to the recent drafts for Multicast
> DNS (mDNS), the "local" top-level domain is to be reserved for link-local
> resolution. I have abused the notion to determine that an interface is
> local to an application, since no entity can register a DNS domain ending
> in "local".
Sounds good. We might be able to use this more widely...
> >There's a signal on DBusGProxy called "destroy", which is emitted when
> >the app on the other end goes away. So people can connect a handler to
> >"destroy" and know when their proxy becomes invalid.
>
> How do you know when the object ceases to be valid on the remote app, but
> the remote app is still there?
There's no "dbus standard" way to do this; objects have to define their
own policy, whether it's "never goes away," "leases," "explicit
create/destroy," or whatever it is. glib bindings have no special
support for it.
dbus does let you implement reliable "distributed refcounting" (or
similar) since you can track if a process crashes and clean up its
refcounts if it does. But that's usually a kind of high-overhead
high-pain approach, vs. just making objects last forever, or returning
an error if an object goes away, or some other simple hack ;-)
> This "destroyed" signal, does it behave like a D-Bus signal? I mean, I
> know it's synthesised by the binding, but does it contain interface
> information too? (owner and path are unique to the object, signal name
> is "destroyed").
DBusGProxy has accessors to get the interface and such -
dbus_g_proxy_get_interface(), etc.
The way the glib bindings work is that you create a proxy and bind it to
a bus-name/interface/object-name, then GObject signals are emitted from
the proxy and you can use the proxy as a handle to make method calls:
dbus_g_proxy_call(proxy, "Frobate", &error,
DBUS_TYPE_STRING, "my argument", DBUS_TYPE_INVALID);
So if you get a signal on "proxy" you can call
dbus_g_proxy_get_interface(proxy) to see what it's from.
You can generate a header file to make things typesafe, an example from
glib/examples/statemachine/statemachine.xml:
static
#ifdef G_HAVE_INLINE
inline
#endif
gboolean
com_example_StateMachine_get_info (DBusGProxy *proxy, char ** OUT_name,
char ** OUT_state, GError **error)
{
return dbus_g_proxy_call (proxy, "GetInfo", error, G_TYPE_INVALID,
G_TYPE_STRING, OUT_name, G_TYPE_STRING, OUT_state, G_TYPE_INVALID);
}
We don't bother creating a new type for the proxy itself though as you
can see. There could be a runtime check there which would be as typesafe
as glib/gtk ever are, like:
g_return_if_fail(strcmp(dbus_g_proxy_get_interface(proxy), "whatever")
== 0);
To _implement_ an object, dbus-binding-tool creates metainformation
similar to what moc generates (in fact I used the Qt4 idea of putting it
all in a single static string). You have to register this
metainformation with your implementation object's GType (along with the
the class struct aka vtable).
For an instance of a type with registered metainformation, you can
register it with a DBusConnection under an object name and the bindings
will know how to introspect the metainformation in order to export the
object over dbus.
Havoc
More information about the dbus
mailing list