Re: EggDBus



On Mon, 2008-12-22 at 11:29 -0500, Dan Winship wrote:
> David Zeuthen wrote:
> > This mail is already too long but there's one more thing.
> 
> Yeah. Still digesting. But...
> 
> I have not done all that much with D-Bus, but one thing I noticed while
> doing the libsoup 2.4 API rewrite was that, at a very high level, D-Bus
> and XML-RPC are fairly similar, and so it would be neat if the code for
> connecting to or implementing an XML-RPC service with libsoup could use
> the same idioms as the code for connecting to or implementing a D-Bus
> service, rather than presenting more-or-less the same concepts to the
> developer in a completely different way. (And of course, using
> standardized idioms makes it easier to make bindings of the code.)

Oh, it's funny you mention XML-RPC. In a previous life I did a lot of
XML-RPC work including writing my own multi-threaded XML-RPC server in c
++.

FWIW, I've had this item for a while on the TODO list

 o  Very little of the core functionality is related to D-Bus; would
    it be useful to have EggIpcProxy, EggIpcConnection, EggIpcMessage,
    EggIpcMethodInvocation GInterfaces that all generated code uses?

    Then the existing EggDBus* classes simply implement these interfaces
    and the wrappers could be used with, say EggXmlRpc* or EggSoap
    implementations too.

    Maybe this is just the Architecture Astronaut talking.

However, I made a decision early on to just focus on D-Bus, mostly
because adding another layer of abstraction and indirection would take
my eyes off the ball. And also a concern that it would make it harder to
get buy-in for getting stuff like this into the core library stack (I'm
sometimes accused of being an architecture astronaut :-). 

That said, I've tried to design this stuff in a way so it's easy to
change if we wanted to do XML-RPC as well.

> From that perspective, the things that would be really nice to have at
> the glib level (below the level of actual D-Bus integration) are:
> 
>     - Easier-to-use GValue/"variant type" support. (I mostly ended up
>       implementing my API in terms of varargs methods that take
>       pairs of types and values, much like dbus-glib, except with
>       GTypes.) Especially, easier-to-use variant array and hash table
>       methods.

Yeah, I tried to solve that with EggDBusVariant, EggDBusHashMap and
EggDBusArraySeq. So far I'm very happy with these; it makes it very easy
to deal with these things from C.

>  (FWIW, the XML-RPC types are, in D-Bus terms, "i", "b",
>       "s", "d", "ay", "a{sv}", and "av", plus a datetime type that
>       doesn't directly map to any D-Bus type.)

Yeah. I think XML-RPC types can largely be considered a subset of the
D-Bus types. For the datetime we could add an extra ISO8601 data type or
something (don't think GTimeVal is enough; need to preserve the TZ I
think).

I think "a{sv}" (a struct type in XML-RPC) can easily be mapped to
EggDBusStructure (or a subclass) the same way we already do.

>     - An easy way to generate a client-side C type to GValue marshaller
>       and server-side GValue to C type marshaller for a given signature,
>       so people don't need to use the GValue/variant APIs directly if
>       they don't want to. glib-genmarshal is insufficient because it
>       makes signal-specific assumptions, and you need something where
>       you can specify what sort of special arguments are needed before
>       and after the generated ones (eg, a GError **), and because it
>       doesn't allow for asynchronous wrappers.

Right. The way I work around that is by generating code in the
GInterface. It's not ideal, I really want method and signal dispatching
to be generic. I think libffi might help here.

> Maybe there isn't really all that much opportunity for code sharing, but
> I figured I'd mention it while you're still pondering the exact
> direction of the APIs. It seems like the libgee/collections stuff might
> possibly help.

I think most of EggDBus can be used here. If we wanted to do this, we'd
create GInterfaces like

 EggIpcMessage
 EggIpcObjectProxy
 EggIpcConnection
 EggIpcMethodInvocation

and then the existing D-Bus classes (EggDBusMessage) would just
implement these interfaces. We'd also want to rename EggDBusVariant to
EggIpcVariant and EggDBusStructure to EggIpcStructure (ditto for
ArraySeq and HashMap but ideally these go into GLib proper).

Then you can implement EggXmlRpcMessage, EggXmlRpcConnection and so
forth.

Then we'd make the code generator use the EggIpc* interface types rather
than the existing D-Bus class types. Then all generated code (both
client and server side) can be used with any IPC mechanism implementing
the EggIpc* interfaces. On the server side you'd do

 if (EGG_DBUS_IS_METHOD_INVOCATION (method_invocation))
   {
      /* do security checks for D-Bus calls, e.g.: */

      pid_t = egg_dbus_method_invocation_get_pid_of_caller
        (EGG_DBUS_METHOD_INVOCATION (method_invocation));
   }
 else if (EGG_XML_RPC_IS_METHOD_INVOCATION (method_invocation))
   {
      /* do security checks for XML-RPC calls */
   }

but normally people don't need that (and if they do, we can make it
transparent via e.g. PolicyKit); for desktop apps (XML-RPC probably
isn't interesting for system services; too dangerous etc.) people
normally set up security on a more coarse-grained granularity.

Thus, adding this layer of abstraction wouldn't really make it much
harder for application programmers.

So if I'm writing an application, instead of just doing

  frob_impl = test_frob_impl_new ();
  tweak_impl = test_tweak_impl_new ();
  twiddle_impl = test_twiddle_impl_new ();

  egg_dbus_connection_register_interface (connection,
                                      "/com/example/TestObject",
                                      TEST_TYPE_FROB, frob_impl,
                                      TEST_TYPE_TWEAK, tweak_impl,
                                      TEST_TYPE_TWIDDLE, twiddle_impl,
                                      G_TYPE_INVALID);

you'd also do

  egg_xmlrpc_connection_register_interface (xmlrpc_connection,
                                      "/some/URI/somewhere",
                                      TEST_TYPE_FROB, frob_impl,
                                      TEST_TYPE_TWEAK, tweak_impl,
                                      TEST_TYPE_TWIDDLE, twiddle_impl,
                                      G_TYPE_INVALID);

and, presto, the application is now both on D-Bus and XML-RPC. Of course
the devil is in the details but I think an approach like this should
work...

Of course there's a bit of overhead (both conceptually and performance
wise) in supporting multiple IPC systems and there's always the risk
that we might paint ourselves into a corner if we did this. But I think
it would be interesting to investigate.

     David




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]