Posts Tagged ‘Application programming interface’

DBUS api

Saturday, July 4th, 2009

Some days ago i wrote a post about avahi, here is the second part of it, the rant about the API it provides.

import dbus, gobject, avahi
from dbus import DBusException
from dbus.mainloop.glib import DBusGMainLoop
 
# Looks for iTunes shares
 
TYPE = '_daap._tcp'
 
def service_resolved(*args):
    print 'service resolved'
    print 'name:', args[2]
    print 'address:', args[7]
    print 'port:', args[8]
 
def print_error(*args):
    print 'error_handler'
    print args[0]
 
def myhandler(interface, protocol, name, stype, domain, flags):
    print "Found service '%s' type '%s' domain '%s' " % (name, stype, domain)
 
    if flags & avahi.LOOKUP_RESULT_LOCAL:
            # local service, skip
            pass
 
    server.ResolveService(interface, protocol, name, stype,
        domain, avahi.PROTO_UNSPEC, dbus.UInt32(0),
        reply_handler=service_resolved, error_handler=print_error)
 
loop = DBusGMainLoop()
 
bus = dbus.SystemBus(mainloop=loop)
 
server = dbus.Interface( bus.get_object(avahi.DBUS_NAME, '/'),
        'org.freedesktop.Avahi.Server')
 
sbrowser = dbus.Interface(bus.get_object(avahi.DBUS_NAME,
        server.ServiceBrowserNew(avahi.IF_UNSPEC,
            avahi.PROTO_UNSPEC, TYPE, 'local', dbus.UInt32(0))),
        avahi.DBUS_INTERFACE_SERVICE_BROWSER)
 
sbrowser.connect_to_signal("ItemNew", myhandler)
 
gobject.MainLoop().run()

This is the example i cited in my earlier post as well. Let’s play a little game, whoever spots most retarded things in there wins ;) .

  • Requires event loop too to scan network
  • Depends on glib
  • Requires the definition of 3 new objects (bus, server, sbrowser) and 2 functions (ignoring the error reporting one) before you can get the most basic “client” functionality!
  • service_resolved get’s in a tuple (btw, it has 11 elements), leaving you without an idea what might be in there
  • you pass one interface into another, WTF?!!?

But remember that is just “client” side, you’ll get to call lots of overcomplicated functions on the publish side as well!

Remeber the *args from above? It surely must make sense once you see it’s content, right? Guess again.

(dbus.Int32(4), dbus.Int32(0), dbus.String(u'b00'), dbus.String(u'_pydra._tcp'), dbus.String(u'local'), dbus.String(u'b00.local'), dbus.Int32(0), dbus.String(u'75.17.116.98'), dbus.UInt16(11890), dbus.Array([dbus.Array([dbus.Byte(102)], signature=dbus.Signature('y')), dbus.Array([dbus.Byte(116)], signature=dbus.Signature('y')), dbus.Array([dbus.Byte(119)], signature=dbus.Signature('y'))], signature=dbus.Signature('ay')), dbus.UInt32(13L))

Let’s play the same game as above with this piece of code :-)

  • it has very lousy integration with python types
  • the TXT record is an array of arrays of bytes, just so that you can send a string (notice how avahi core developer says: “Yes indeed, python-dbus is a large pile of bugs. “) :/
  • notice the dbus.Array([dbus.Array([dbus.Byte(102)], i dared to send a normal string and all i got was the last character!
  • there must be a bright side? You can practice your function defining skills so that you can send strings!
Reblog this post [with Zemanta]

Avahi thoughts

Tuesday, June 30th, 2009
Diagram of Streaming Multicast
Image via Wikipedia

First a short intro to avahi, basically it is a ZeroConf implementation for linux, to make a long story short through use of multicast it is able to discover services as they appear (as well as scan network for those services).

This is a tale of a hacker deciding to take a pydra ticket. After verifying that avahi has python bindings i headed to their home page looking for docs. There is a “ProgrammingDocs” which looked like a good sign, imagine my horror when i read on that page

Though no real documentation about the DBUS API is available, you may browse the DBUS introspection data online

OK, so they pretty much don’t have docs, it can’t be that bad to work with it, right? Their API is to f**** complicated :-) , this is supposed to be the simplest of the “client” examples, this is the simplest of the “publisher” examples, fortunately the publisher wrapper is very nice to work with, but the fact that it exists hints that there is something wrong with the API.

As far as the protocol goes, first thing that struck me is that you can’t really distinguish between server and client, both take an active role. “publisher” advertisizes it’s service, while the “client” (or however you wanna call it) initiates the glib event loop and waits for asynchronous callback to happen. If we ignore the fact that you are forced to use certain event loop having continuous discovery is not a bad thing, it provies you a way to do discovery even if certain involved parties are temporary down, as well as the ability to see them as they join the network. What i’m saying is that forcing people to use event loop is a bad thing (as it is big overkill in simple cases).

If we get to my code, i choose to make the master the one discovering nodes, the reason for this is that this way i don’t have to make the node tell the master “hey i’m alive use me” (and of course implement the appropriate extension to the protocol). So basically a master is looking for nodes, when a node is put on network it advertisizes itself and master finds it and add’s it to it’s Node list.

Reblog this post [with Zemanta]
Blog Widget by LinkWithin