Improve behaviour when no avahi-daemon is present or being stopped while running

This commit is contained in:
Stefan Bethge 2006-08-01 00:44:51 +00:00
parent d7719e73b3
commit da06dfb6ca
2 changed files with 95 additions and 58 deletions

View file

@ -189,22 +189,25 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
if self.connection: if self.connection:
return self.connection, '' return self.connection, ''
self.zeroconf.connect() if self.zeroconf.connect():
self.connection = client_zeroconf.ClientZeroconf(self.zeroconf) self.connection = client_zeroconf.ClientZeroconf(self.zeroconf)
self.roster = self.connection.getRoster() self.roster = self.connection.getRoster()
self.dispatch('ROSTER', self.roster) self.dispatch('ROSTER', self.roster)
#display contacts already detected and resolved #display contacts already detected and resolved
for jid in self.roster.keys(): for jid in self.roster.keys():
display_jid = self.zeroconf.check_jid(jid) display_jid = self.zeroconf.check_jid(jid)
self.dispatch('ROSTER_INFO', (display_jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid))) self.dispatch('ROSTER_INFO', (display_jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid)))
self.dispatch('NOTIFY', (display_jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0)) self.dispatch('NOTIFY', (display_jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0))
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
# refresh all contacts data all 10 seconds # refresh all contacts data every second
self.call_resolve_timeout = True self.call_resolve_timeout = True
gobject.timeout_add(1000, self._on_resolve_timeout) gobject.timeout_add(1000, self._on_resolve_timeout)
else:
pass
# display visual notification that we could not connect to avahi
def connect_and_init(self, show, msg, signed): def connect_and_init(self, show, msg, signed):
self.continue_connect_info = [show, msg, signed] self.continue_connect_info = [show, msg, signed]
@ -230,36 +233,41 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
if not show in STATUS_LIST: if not show in STATUS_LIST:
return -1 return -1
check = True #to check for errors from zeroconf
# 'connect' # 'connect'
if show != 'offline' and not self.connected: if show != 'offline' and not self.connected:
self.on_purpose = False self.on_purpose = False
self.connect_and_init(show, msg, '') self.connect_and_init(show, msg, '')
if show != 'invisible': if show != 'invisible':
self.zeroconf.announce() check = self.zeroconf.announce()
else: else:
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
# 'disconnect' # 'disconnect'
elif show == 'offline' and self.connected: elif show == 'offline' and self.connected:
self.connected = 0 self.connected = 0
self.dispatch('STATUS', 'offline')
self.disconnect() self.disconnect()
self.dispatch('STATUS', 'offline')
# update status # update status
elif show != 'offline' and self.connected: elif show != 'offline' and self.connected:
was_invisible = self.connected == STATUS_LIST.index('invisible') was_invisible = self.connected == STATUS_LIST.index('invisible')
self.connected = STATUS_LIST.index(show) self.connected = STATUS_LIST.index(show)
if show == 'invisible': if show == 'invisible':
self.zeroconf.remove_announce() check = check and self.zeroconf.remove_announce()
return elif was_invisible:
if was_invisible: check = check and self.zeroconf.announce()
self.zeroconf.announce() if self.connection and not show == 'invisible':
if self.connection:
txt = {} txt = {}
txt['status'] = show txt['status'] = show
txt['msg'] = msg txt['msg'] = msg
self.zeroconf.update_txt(txt) check = check and self.zeroconf.update_txt(txt)
self.dispatch('STATUS', show)
if check:
self.dispatch('STATUS', show)
else:
self.dispatch('STATUS', 'offline')
def get_status(self): def get_status(self):
return STATUS_LIST[self.connected] return STATUS_LIST[self.connected]

View file

@ -42,6 +42,7 @@ class Zeroconf:
self.service_browsers = {} self.service_browsers = {}
self.contacts = {} # all current local contacts with data self.contacts = {} # all current local contacts with data
self.entrygroup = None self.entrygroup = None
self.connected = False
## handlers for dbus callbacks ## handlers for dbus callbacks
@ -85,7 +86,9 @@ class Zeroconf:
def check_jid(self, jid): def check_jid(self, jid):
# TODO: at least miranda uses bad service names(only host name), so change them - probabaly not so nice... need to find a better solution # TODO: at least miranda uses bad service names(only host name), so change them - probabaly not so nice... need to find a better solution
# this is necessary so they don't get displayed as a transport
# [dkirov] maybe turn it into host+'@'+host, instead ? # [dkirov] maybe turn it into host+'@'+host, instead ?
# [sb] that would mean we can't do recreate below
if jid.find('@') == -1: if jid.find('@') == -1:
return 'bad-client@' + jid return 'bad-client@' + jid
else: else:
@ -150,8 +153,8 @@ class Zeroconf:
# the name is already present, so recreate # the name is already present, so recreate
if state == avahi.ENTRY_GROUP_COLLISION: if state == avahi.ENTRY_GROUP_COLLISION:
self.service_add_fail_callback('Local name collision, recreating.') self.service_add_fail_callback('Local name collision, recreating.')
elif state == avahi.ENTRY_GROUP_FAILURE:
# elif state == avahi.ENTRY_GROUP_FAILURE: print 'zeroconf.py: ENTRY_GROUP_FAILURE reached(that should not happen)'
# make zeroconf-valid names # make zeroconf-valid names
def replace_show(self, show): def replace_show(self, show):
@ -164,34 +167,51 @@ class Zeroconf:
return show return show
def create_service(self): def create_service(self):
if not self.entrygroup: try:
# create an EntryGroup for publishing if not self.entrygroup:
self.entrygroup = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP) # create an EntryGroup for publishing
self.entrygroup.connect_to_signal('StateChanged', self.entrygroup_state_changed_callback) self.entrygroup = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP)
self.entrygroup.connect_to_signal('StateChanged', self.entrygroup_state_changed_callback)
self.txt['port.p2pj'] = self.port self.txt['port.p2pj'] = self.port
self.txt['version'] = 1 self.txt['version'] = 1
self.txt['txtvers'] = 1 self.txt['txtvers'] = 1
# replace gajim's status messages with proper ones # replace gajim's show messages with compatible ones
if self.txt.has_key('status'): if self.txt.has_key('status'):
self.txt['status'] = self.replace_show(self.txt['status']) self.txt['status'] = self.replace_show(self.txt['status'])
# print "Publishing service '%s' of type %s" % (self.name, self.stype) # print "Publishing service '%s' of type %s" % (self.name, self.stype)
self.entrygroup.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), self.name, self.stype, '', '', self.port, avahi.dict_to_txt_array(self.txt), reply_handler=self.service_added_callback, error_handler=self.service_add_fail_callback) self.entrygroup.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), self.name, self.stype, '', '', self.port, avahi.dict_to_txt_array(self.txt), reply_handler=self.service_added_callback, error_handler=self.service_add_fail_callback)
self.entrygroup.Commit(reply_handler=self.service_committed_callback, error_handler=self.print_error_callback) self.entrygroup.Commit(reply_handler=self.service_committed_callback, error_handler=self.print_error_callback)
return True
except dbus.dbus_bindings.DBusException, e:
gajim.log.debug(str(e))
return False
def announce(self): def announce(self):
state = self.server.GetState() if self.connected:
state = self.server.GetState()
if state == avahi.SERVER_RUNNING: if state == avahi.SERVER_RUNNING:
self.create_service() self.create_service()
return True
else:
return False
def remove_announce(self): def remove_announce(self):
if self.entrygroup: try:
self.entrygroup.Reset() if self.entrygroup.GetState() != avahi.ENTRY_GROUP_FAILURE:
self.entrygroup.Free() self.entrygroup.Reset()
self.entrygroup = None self.entrygroup.Free()
self.entrygroup = None
return True
else:
return False
except dbus.dbus_bindings.DBusException, e:
print "zeroconf.py: Can't remove service, avahi daemon not running?"
def browse_domain(self, interface, protocol, domain): def browse_domain(self, interface, protocol, domain):
self.new_service_type(interface, protocol, self.stype, domain, '') self.new_service_type(interface, protocol, self.stype, domain, '')
@ -199,15 +219,20 @@ class Zeroconf:
# connect to dbus # connect to dbus
def connect(self): def connect(self):
self.bus = dbus.SystemBus() self.bus = dbus.SystemBus()
self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, \
avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
try: try:
# is there any way to check, if a dbus name exists?
# that might make the Introspect Error go away...
self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, \
avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
self.server.connect_to_signal('StateChanged', self.server_state_changed_callback) self.server.connect_to_signal('StateChanged', self.server_state_changed_callback)
except dbus.dbus_bindings.DBusException, e: except dbus.dbus_bindings.DBusException, e:
# Avahi service is not present # Avahi service is not present
gajim.log.debug(str(e)) gajim.log.debug(str(e))
self.remove_announce() return False
return
self.connected = True
# start browsing # start browsing
if self.domain is None: if self.domain is None:
# Explicitly browse .local # Explicitly browse .local
@ -222,10 +247,13 @@ class Zeroconf:
else: else:
self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain) self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
return True
def disconnect(self): def disconnect(self):
self.connected = False
self.remove_announce() self.remove_announce()
# refresh data manually - really ok or too much traffic? # refresh txt data of all contacts manually (no callback available)
def resolve_all(self): def resolve_all(self):
for val in self.contacts.values(): for val in self.contacts.values():
#val:(name, domain, interface, protocol, host, address, port, txt) #val:(name, domain, interface, protocol, host, address, port, txt)
@ -249,10 +277,11 @@ class Zeroconf:
self.txt['status'] = self.replace_show(txt['status']) self.txt['status'] = self.replace_show(txt['status'])
txt = avahi.dict_to_txt_array(self.txt) txt = avahi.dict_to_txt_array(self.txt)
if self.entrygroup:
self.entrygroup.UpdateServiceTxt(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), self.name, self.stype,'', txt, reply_handler=self.service_updated_callback, error_handler=self.print_error_callback) self.entrygroup.UpdateServiceTxt(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0), self.name, self.stype,'', txt, reply_handler=self.service_updated_callback, error_handler=self.print_error_callback)
# self.entrygroup.Commit() # TODO: necessary? return True
else:
return False
def send (self, msg, sock): def send (self, msg, sock):
print 'send:'+msg print 'send:'+msg