Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorgan Collett <morgan.collett@gmail.com>2007-07-09 13:24:06 (GMT)
committer Morgan Collett <morgan.collett@gmail.com>2007-07-09 13:24:06 (GMT)
commit0fdd201b8f383188b5f283313ee30115ef8f1896 (patch)
tree8c7a964104a58534162cc5ca485a67405372d4c9
parentf7c174aa82bbafa6ebdc33930acb9f8aaa37e689 (diff)
parentc9c66a6b53699090f6b863cfa249395ffca653d6 (diff)
Merge http://people.freedesktop.org/~smcv/git/presence-service
-rw-r--r--src/activity.py9
-rw-r--r--src/buddy.py31
-rw-r--r--src/linklocal_plugin.py14
-rw-r--r--src/presenceservice.py5
-rw-r--r--src/server_plugin.py12
-rw-r--r--src/telepathy_plugin.py92
6 files changed, 116 insertions, 47 deletions
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()