Question

I'm trying to port some code, that currently uses the Avahi raw dbus interface, to using the Avahi gobject interface (via gobject introspection from python.)

I have gotten the ServiceBrowser, but I can't get the ServiceResolver to work. Here is my code:

#!/usr/bin/env python

import logging

from gi.repository import Avahi

logging.basicConfig(level=logging.DEBUG)
ac_log = logging.getLogger('Avahi.Client')
sb_log = logging.getLogger('Avahi.ServiceBrowser')
sr_log = logging.getLogger('Avahi.ServiceResolver')

def ac_state_changed(client, state):
    ac_log.debug('state_changed: {}'.format(state))

avahi_client = Avahi.Client(flags=0,)
avahi_client.connect('state-changed', ac_state_changed)
avahi_client.start()

def sb_new_service(browser, interface, protocol, name, type, domain, flags ):
    sb_log.debug('new: {}'.format(name))
    if not (flags & Avahi.LookupResultFlags.GA_LOOKUP_RESULT_LOCAL):
        sb_log.debug('resolving: {}'.format(name))
        service_resolver = Avahi.ServiceResolver(
            interface=interface,
            protocol=protocol,
            name=name,
            type=type,
            domain=domain,
            aprotocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC,
            flags=0,)
        service_resolver.connect('found', sr_found)
        service_resolver.connect('failure', sr_failure)
        service_resolver.attach(avahi_client)

def sb_all_for_now(*args):
    sb_log.debug('all_for_now')
    seen_all = True

def sb_failure(*args):
    sb_log.error('failure: {}'.format(args))

def sr_found(*args):
    sr_log.debug('found: {}'.format(args))

def sr_failure(*args):
    sr_log.error('failure: {}'.format(args))


service_browser = Avahi.ServiceBrowser(
    domain='local',
    flags=0,
    interface=-1,
    protocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC,
    type='_workstation._tcp')

service_browser.connect("new_service", sb_new_service)
service_browser.connect("failure", sb_failure)
service_browser.attach(avahi_client)


from gi.repository import GObject

mainloop = GObject.MainLoop()
mainloop.run()

example output:

DEBUG:Avahi.Client:state_changed: <enum GA_CLIENT_STATE_S_RUNNING of type GaClientState>
DEBUG:Avahi.ServiceBrowser:new: Mobi [d8:d3:85:e8:26:3d]
DEBUG:Avahi.ServiceBrowser:resolving: Mobi [d8:d3:85:e8:26:3d]
DEBUG:Avahi.ServiceBrowser:new: garyvdm [00:1d:09:a5:10:54]
DEBUG:Avahi.ServiceBrowser:new: noddy [00:15:c5:c6:46:4b]
DEBUG:Avahi.ServiceBrowser:resolving: noddy [00:15:c5:c6:46:4b]
DEBUG:Avahi.ServiceBrowser:new: crack [00:1c:26:20:e0:1d]
DEBUG:Avahi.ServiceBrowser:resolving: crack [00:1c:26:20:e0:1d]
DEBUG:Avahi.ServiceBrowser:new: opium [00:1d:09:c1:ed:cf]
DEBUG:Avahi.ServiceBrowser:resolving: opium [00:1d:09:c1:ed:cf]
DEBUG:Avahi.ServiceBrowser:new: gerard-vm [00:0c:29:d0:2a:af]
DEBUG:Avahi.ServiceBrowser:resolving: gerard-vm [00:0c:29:d0:2a:af]
DEBUG:Avahi.ServiceBrowser:all_for_now
^CTraceback (most recent call last):
  File "pacshare/xfer.py", line 65, in <module>
    mainloop.run()
KeyboardInterrupt

I left it running for about 1min before I pressed ctrl-c. As you can see, I'm calling the ServiceResolver, but the sr_found and sr_failure methods never get called. How can I get this to work?

(I can't find any other code that does this on http://code.ohloh.net/, so I suspect I may be the first person trying to do this)

Was it helpful?

Solution

Basically your code works just right. The only problem it has is reference counting.

When the python interpreter reaches the end of sb_new_service(), it will delete all objects that are no longer being referenced. As you have specified service_resolver as a local variable, this object will also be deleted. To prevent this from happening, you could just add service_resolver to a (global) list of resolvers like this:

resolvers = []

def sb_new_service(browser, interface, protocol, name, type, domain, flags ):
    sb_log.debug('new: {}'.format(name))
    if not (flags & Avahi.LookupResultFlags.GA_LOOKUP_RESULT_LOCAL):
        sb_log.debug('resolving: {}'.format(name))
        service_resolver = Avahi.ServiceResolver(
            interface=interface,
            protocol=protocol,
            name=name,
            type=type,
            domain=domain,
            aprotocol=Avahi.Protocol.GA_PROTOCOL_UNSPEC,
            flags=0,)
        service_resolver.connect('found', sr_found)
        service_resolver.connect('failure', sr_failure)
        service_resolver.attach(avahi_client)
        global resolvers
        resolvers.append(service_resolver)

Then your code should work fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top