From 0fdd201b8f383188b5f283313ee30115ef8f1896 Mon Sep 17 00:00:00 2001 From: Morgan Collett Date: Mon, 09 Jul 2007 13:24:06 +0000 Subject: Merge http://people.freedesktop.org/~smcv/git/presence-service --- diff --git a/src/activity.py b/src/activity.py index 0cc16e7..019ac65 100644 --- a/src/activity.py +++ b/src/activity.py @@ -181,6 +181,11 @@ class Activity(ExportedGObject): assert self._room, self._room conn = self._tp.get_connection() + if CONN_INTERFACE_ACTIVITY_PROPERTIES not in conn: + # we should already have warned about this somewhere - + # certainly, don't emit a warning per activity! + return + def got_properties_err(e): _logger.warning('Failed to get initial activity properties ' 'for %s: %s', self._id, e) @@ -817,6 +822,10 @@ class Activity(ExportedGObject): conn = self._tp.get_connection() + if CONN_INTERFACE_ACTIVITY_PROPERTIES not in conn: + # we should already have warned about this somewhere + return + def properties_set(e=None): if e is None: _logger.debug('Successfully set activity properties for %s', diff --git a/src/buddy.py b/src/buddy.py index d8d5694..8fa8a98 100644 --- a/src/buddy.py +++ b/src/buddy.py @@ -566,6 +566,9 @@ class Buddy(ExportedGObject): conn = tp.get_connection() handle, identifier = self._handles[tp] + if CONN_INTERFACE_AVATARS not in conn: + return + if icon is None: icon = buddy_icon_cache.get_icon(conn.object_path, identifier, new_avatar_token) @@ -648,6 +651,12 @@ class GenericOwner(Buddy): uses SetActivities on BuddyInfo channel """ conn = tp.get_connection() + + if CONN_INTERFACE_BUDDY_INFO not in conn: + _logger.warning('%s does not support BuddyInfo - unable to ' + 'set activities') + return + conn[CONN_INTERFACE_BUDDY_INFO].SetActivities( self._activities_by_connection[tp].iteritems(), reply_handler=_noop, @@ -675,6 +684,12 @@ class GenericOwner(Buddy): _logger.debug("Setting current activity to '%s' (handle %s)", cur_activity, cur_activity_handle) conn = tp.get_connection() + + if CONN_INTERFACE_BUDDY_INFO not in conn: + _logger.warning('%s does not support BuddyInfo - unable to ' + 'set current activity') + return + conn[CONN_INTERFACE_BUDDY_INFO].SetCurrentActivity(cur_activity, cur_activity_handle, reply_handler=_noop, @@ -684,6 +699,12 @@ class GenericOwner(Buddy): def _set_self_alias(self, tp): self_handle = self._handles[tp][0] conn = tp.get_connection() + + if CONN_INTERFACE_ALIASING not in conn: + _logger.warning('%s does not support aliasing - unable to ' + 'set my own alias') + return False + conn[CONN_INTERFACE_ALIASING].SetAliases({self_handle: self._nick}, reply_handler=_noop, error_handler=lambda e: @@ -710,6 +731,11 @@ class GenericOwner(Buddy): del props['ip4-address'] if connected: + if CONN_INTERFACE_BUDDY_INFO not in conn: + _logger.warning('%s does not support BuddyInfo - unable to ' + 'set my own buddy properties') + return False + conn[CONN_INTERFACE_BUDDY_INFO].SetProperties(props, reply_handler=_noop, error_handler=lambda e: @@ -761,6 +787,11 @@ class GenericOwner(Buddy): conn = tp.get_connection() icon_data = self._icon + if CONN_INTERFACE_AVATARS not in conn: + _logger.warning('%s does not support Avatars - unable to ' + 'set my own avatar on this connection') + return + m = new_md5() m.update(icon_data) digest = m.hexdigest() diff --git a/src/linklocal_plugin.py b/src/linklocal_plugin.py index b60eb15..10924e1 100644 --- a/src/linklocal_plugin.py +++ b/src/linklocal_plugin.py @@ -68,15 +68,19 @@ class LinkLocalPlugin(TelepathyPlugin): if unique_name: self._have_avahi = True if not had_avahi: - _logger.info('Avahi appeared on the system bus (%s) - ' - 'starting...', unique_name) - self.start() + if self._backoff_id > 0: + _logger.info('Avahi appeared on the system bus (%s) - ' + 'will start when retry time is reached') + else: + _logger.info('Avahi appeared on the system bus (%s) - ' + 'starting...', unique_name) + self.start() else: self._have_avahi = False if had_avahi: _logger.info('Avahi disappeared from the system bus - ' 'stopping...') - self.stop() + self._stop() def cleanup(self): TelepathyPlugin.cleanup(self) @@ -85,7 +89,7 @@ class LinkLocalPlugin(TelepathyPlugin): self._watch = None def _could_connect(self): - return self._have_avahi + return TelepathyPlugin._could_connect(self) and self._have_avahi def _get_account_info(self): """Retrieve connection manager parameters for this account diff --git a/src/presenceservice.py b/src/presenceservice.py index fd5409c..0dfd7f9 100644 --- a/src/presenceservice.py +++ b/src/presenceservice.py @@ -767,6 +767,11 @@ def main(test_num=0, randomize=False): loop = gobject.MainLoop() DBusGMainLoop(set_as_default=True) + if dbus.version < (0, 82, 0): + _logger.error('dbus-python %s is too old (0.82.0 is required). ' + 'The PS is unlikely to work correctly.', + dbus.__version__) + if test_num > 0: from pstest import TestPresenceService ps = TestPresenceService(test_num, randomize) diff --git a/src/server_plugin.py b/src/server_plugin.py index c589877..7c275b1 100644 --- a/src/server_plugin.py +++ b/src/server_plugin.py @@ -68,12 +68,12 @@ class ServerPlugin(TelepathyPlugin): if address: _logger.debug("::: valid IP4 address, conn_status %s", self._conn_status) - if self._conn_status == CONNECTION_STATUS_DISCONNECTED: - _logger.debug("::: will connect") + # this is a no-op if starting would be inappropriate right now + if self._conn_status != CONNECTION_STATUS_DISCONNECTED: self.start() else: _logger.debug("::: invalid IP4 address, will disconnect") - self.stop() + self._stop() def _get_account_info(self): """Retrieve connection manager parameters for this account @@ -126,7 +126,8 @@ class ServerPlugin(TelepathyPlugin): return None def _could_connect(self): - return bool(self._ip4am.props.address) + return bool(self._ip4am.props.address and + TelepathyPlugin._could_connect(self)) def _server_is_trusted(self, hostname): """Return True if the server with the given hostname is trusted to @@ -240,7 +241,8 @@ class ServerPlugin(TelepathyPlugin): if local_pending: # accept pending subscriptions # FIXME: do this async - publish[CHANNEL_INTERFACE_GROUP].AddMembers(local_pending, '') + self._publish_channel[CHANNEL_INTERFACE_GROUP].AddMembers( + local_pending, '') # request subscriptions from people subscribed to us if we're not # subscribed to them diff --git a/src/telepathy_plugin.py b/src/telepathy_plugin.py index d95b642..a9ddfe0 100644 --- a/src/telepathy_plugin.py +++ b/src/telepathy_plugin.py @@ -112,8 +112,8 @@ class TelepathyPlugin(gobject.GObject): #: The connection's status self._conn_status = CONNECTION_STATUS_DISCONNECTED - #: GLib signal ID for reconnections - self._reconnect_id = 0 + #: GLib source ID indicating when we may try to reconnect + self._backoff_id = 0 #: Parameters for the connection manager self._account = self._get_account_info() @@ -156,8 +156,16 @@ class TelepathyPlugin(gobject.GObject): raise NotImplementedError def _reconnect_cb(self): - """Attempt to reconnect to the server""" + """Attempt to reconnect to the server after the back-off time has + elapsed. + """ + if self._backoff_id > 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = 0 + + # this is a no-op unless _could_connect() returns True self.start() + return False def _init_connection(self): @@ -182,17 +190,6 @@ class TelepathyPlugin(gobject.GObject): self._new_channel_cb) self._matches.append(m) - # hack - conn._valid_interfaces.add(CONN_INTERFACE_PRESENCE) - conn._valid_interfaces.add(CONN_INTERFACE_BUDDY_INFO) - conn._valid_interfaces.add(CONN_INTERFACE_ACTIVITY_PROPERTIES) - conn._valid_interfaces.add(CONN_INTERFACE_AVATARS) - conn._valid_interfaces.add(CONN_INTERFACE_ALIASING) - - m = conn[CONN_INTERFACE_PRESENCE].connect_to_signal('PresenceUpdate', - self._presence_update_cb) - self._matches.append(m) - self._conn = conn status = self._conn[CONN_INTERFACE].GetStatus() @@ -203,9 +200,11 @@ class TelepathyPlugin(gobject.GObject): _logger.debug('%r: Connect() succeeded', self) def connect_error(e): _logger.debug('%r: Connect() failed: %s', self, e) - if not self._reconnect_id: - self._reconnect_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, - self._reconnect_cb) + # we don't allow ourselves to retry more often than this + if self._backoff_id != 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, + self._reconnect_cb) self._conn[CONN_INTERFACE].Connect(reply_handler=connect_reply, error_handler=connect_error) @@ -239,26 +238,30 @@ class TelepathyPlugin(gobject.GObject): _logger.debug("%r: connected", self) self._connected_cb() elif status == CONNECTION_STATUS_DISCONNECTED: - self.stop() + self._conn = None + self._stop() _logger.debug("%r: disconnected (reason %r)", self, reason) if reason == CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED: # FIXME: handle connection failure; retry later? pass else: - # If disconnected, but still have a network connection, retry - # If disconnected and no network connection, do nothing here - # and let the IP4AddressMonitor address-changed signal handle - # reconnection - if self._could_connect() and not self._reconnect_id: - self._reconnect_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, + # Try again later. We'll detect whether we have a network + # connection after the retry period elapses. The fact that + # this timer is running also serves as a marker to indicate + # that we shouldn't try to go back online yet. + if self._backoff_id: + gobject.source_remove(self._backoff_id) + self._backoff_id = gobject.timeout_add(self._RECONNECT_TIMEOUT, self._reconnect_cb) self.emit('status', self._conn_status, int(reason)) def _could_connect(self): - return True + # Don't allow connection unless the reconnect timeout has elapsed, + # or this is the first attempt + return (self._backoff_id == 0) - def stop(self): + def _stop(self): """If we still have a connection, disconnect it""" matches = self._matches @@ -277,12 +280,12 @@ class TelepathyPlugin(gobject.GObject): if self._online_contacts: self._contacts_offline(self._online_contacts) - if self._reconnect_id > 0: - gobject.source_remove(self._reconnect_id) - self._reconnect_id = 0 - def cleanup(self): - self.stop() + self._stop() + + if self._backoff_id > 0: + gobject.source_remove(self._backoff_id) + self._backoff_id = 0 def _contacts_offline(self, handles): """Handle contacts going offline (send message, update set)""" @@ -404,6 +407,13 @@ class TelepathyPlugin(gobject.GObject): # FIXME: retry if getting the channel times out + interfaces = self._conn.get_valid_interfaces() + + # FIXME: this is a hack, but less harmful than the previous one - + # the next version of telepathy-python will contain a better fix + for iface in self._conn[CONN_INTERFACE].GetInterfaces(): + interfaces.add(iface) + # request both handles at the same time to reduce round-trips pub_handle, sub_handle = self._conn[CONN_INTERFACE].RequestHandles( HANDLE_TYPE_LIST, ['publish', 'subscribe']) @@ -434,8 +444,18 @@ class TelepathyPlugin(gobject.GObject): self.self_identifier = self._conn[CONN_INTERFACE].InspectHandles( HANDLE_TYPE_CONTACT, [self.self_handle])[0] - # Request presence for everyone we're subscribed to - self._conn[CONN_INTERFACE_PRESENCE].RequestPresence(subscribe_handles) + if CONN_INTERFACE_PRESENCE in self._conn: + # Ask to be notified about presence changes + m = self._conn[CONN_INTERFACE_PRESENCE].connect_to_signal( + 'PresenceUpdate', self._presence_update_cb) + self._matches.append(m) + + # Request presence for everyone we're subscribed to + self._conn[CONN_INTERFACE_PRESENCE].RequestPresence( + subscribe_handles) + else: + _logger.warning('%s does not support Connection.Interface.' + 'Presence', self._conn.object_path) def start(self): """Start up the Telepathy networking connections @@ -448,13 +468,11 @@ class TelepathyPlugin(gobject.GObject): otherwise initiate a connection and transfer control to _connect_reply_cb or _connect_error_cb """ + if self._conn is not None: + return _logger.debug("%r: Starting up...", self) - if self._reconnect_id > 0: - gobject.source_remove(self._reconnect_id) - self._reconnect_id = 0 - # Only init connection if we have a valid IP address if self._could_connect(): self._init_connection() -- cgit v0.9.1