diff options
Diffstat (limited to 'services/presence/server_plugin.py')
-rw-r--r-- | services/presence/server_plugin.py | 124 |
1 files changed, 70 insertions, 54 deletions
diff --git a/services/presence/server_plugin.py b/services/presence/server_plugin.py index efb97fc..63de279 100644 --- a/services/presence/server_plugin.py +++ b/services/presence/server_plugin.py @@ -136,11 +136,22 @@ class ServerPlugin(gobject.GObject): self._owner.connect("icon-changed", self._owner_icon_changed_cb) self._account = self._get_account_info() - - self._conn = self._init_connection() self._conn_status = CONNECTION_STATUS_DISCONNECTED - self._reconnect_id = 0 + # Monitor IPv4 address as an indicator of the network connection + self._ip4am = psutils.IP4AddressMonitor.get_instance() + self._ip4am.connect('address-changed', self._ip4_address_changed_cb) + + def _ip4_address_changed_cb(self, ip4am, address): + logging.debug("::: IP4 address now %s" % address) + if address: + logging.debug("::: valid IP4 address, conn_status %s" % self._conn_status) + if self._conn_status == CONNECTION_STATUS_DISCONNECTED: + logging.debug("::: will connect") + self.start() + else: + logging.debug("::: invalid IP4 address, will disconnect") + self.cleanup() def _owner_property_changed_cb(self, owner, properties): """Local user's configuration properties have changed @@ -229,6 +240,14 @@ class ServerPlugin(gobject.GObject): """Retrieve our telepathy.client.Connection object""" return self._conn + def _connect_reply_cb(self): + """Handle connection success""" + pass + + def _connect_error_cb(self, exception): + """Handle connection failure""" + logging.debug("Connect error: %s" % exception) + def _init_connection(self): """Set up our connection @@ -262,7 +281,12 @@ class ServerPlugin(gobject.GObject): conn[CONN_INTERFACE_PRESENCE].connect_to_signal('PresenceUpdate', self._presence_update_cb) - return conn + self._conn = conn + status = self._conn[CONN_INTERFACE].GetStatus() + if status == CONNECTION_STATUS_DISCONNECTED: + self._conn[CONN_INTERFACE].Connect(reply_handler=self._connect_reply_cb, + error_handler=self._connect_error_cb) + self._handle_connection_status_change(self._conn, status) def _request_list_channel(self, name): """Request a contact-list channel from Telepathy @@ -297,16 +321,14 @@ class ServerPlugin(gobject.GObject): if local_pending: # accept pending subscriptions - #print 'pending: %r' % local_pending publish[CHANNEL_INTERFACE_GROUP].AddMembers(local_pending, '') - not_subscribed = list(set(publish_handles) - set(subscribe_handles)) self_handle = self._conn[CONN_INTERFACE].GetSelfHandle() self._online_contacts[self_handle] = self._account['account'] - for handle in not_subscribed: - # request subscriptions from people subscribed to us if we're not subscribed to them - subscribe[CHANNEL_INTERFACE_GROUP].AddMembers([self_handle], '') + # request subscriptions from people subscribed to us if we're not subscribed to them + not_subscribed = list(set(publish_handles) - set(subscribe_handles)) + subscribe[CHANNEL_INTERFACE_GROUP].AddMembers(not_subscribed, '') if CONN_INTERFACE_BUDDY_INFO not in self._conn.get_valid_interfaces(): logging.debug('OLPC information not available') @@ -334,8 +356,8 @@ class ServerPlugin(gobject.GObject): self._set_self_avatar() # Request presence for everyone on the channel - self._conn[CONN_INTERFACE_PRESENCE].GetPresence(subscribe_handles, - ignore_reply=True) + subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() + self._conn[CONN_INTERFACE_PRESENCE].RequestPresence(subscribe_handles) return True def _set_self_avatar_cb(self, token): @@ -504,31 +526,38 @@ class ServerPlugin(gobject.GObject): return handle return None - def _status_changed_cb(self, state, reason): - """Handle notification of connection-status change - - state -- CONNECTION_STATUS_* - reason -- integer code describing the reason... - """ - if state == CONNECTION_STATUS_CONNECTING: - self._conn_status = state - logging.debug("State: connecting...") - elif state == CONNECTION_STATUS_CONNECTED: + def _handle_connection_status_change(self, status, reason): + if status == self._conn_status: + return + + if status == CONNECTION_STATUS_CONNECTING: + self._conn_status = status + logging.debug("status: connecting...") + elif status == CONNECTION_STATUS_CONNECTED: if self._connected_cb(): - logging.debug("State: connected") - self._conn_status = state + logging.debug("status: connected") + self._conn_status = status else: self.cleanup() - logging.debug("State: was connected, but an error occurred") - elif state == CONNECTION_STATUS_DISCONNECTED: + logging.debug("status: was connected, but an error occurred") + elif status == CONNECTION_STATUS_DISCONNECTED: self.cleanup() - logging.debug("State: disconnected (reason %r)" % reason) + logging.debug("status: disconnected (reason %r)" % reason) if reason == CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED: # FIXME: handle connection failure; retry later? pass self.emit('status', self._conn_status, int(reason)) + def _status_changed_cb(self, status, reason): + """Handle notification of connection-status change + + status -- CONNECTION_STATUS_* + reason -- integer code describing the reason... + """ + logging.debug("::: connection status changed to %s" % status) + self._handle_connection_status_change(status, reason) + def start(self): """Start up the Telepathy networking connections @@ -541,35 +570,13 @@ class ServerPlugin(gobject.GObject): _connect_reply_cb or _connect_error_cb """ logging.debug("Starting up...") - # If the connection is already connected query initial contacts - conn_status = self._conn[CONN_INTERFACE].GetStatus() - if conn_status == CONNECTION_STATUS_CONNECTED: - self._connected_cb() - subscribe = self._request_list_channel('subscribe') - subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() - self._conn[CONN_INTERFACE_PRESENCE].RequestPresence(subscribe_handles) - elif conn_status == CONNECTION_STATUS_CONNECTING: - pass - else: - self._conn[CONN_INTERFACE].Connect(reply_handler=self._connect_reply_cb, - error_handler=self._connect_error_cb) - - def _connect_reply_cb(self): - """Handle connection success""" - if self._reconnect_id > 0: - gobject.source_remove(self._reconnect_id) - - def _reconnect(self): - """Reset number-of-attempted connections and re-attempt""" - self._reconnect_id = 0 - self.start() - return False - def _connect_error_cb(self, exception): - """Handle connection failure""" - logging.debug("Connect error: %s" % exception) - if not self._reconnect_id: - self._reconnect_id = gobject.timeout_add(10000, self._reconnect) + # Only init connection if we have a valid IP address + if self._ip4am.props.address: + logging.debug("::: Have IP4 address %s, will connect" % self._ip4am.props.address) + self._init_connection() + else: + logging.debug("::: No IP4 address, postponing connection") def cleanup(self): """If we still have a connection, disconnect it""" @@ -578,6 +585,12 @@ class ServerPlugin(gobject.GObject): self._conn = None self._conn_status = CONNECTION_STATUS_DISCONNECTED + for handle in self._online_contacts.keys(): + self._contact_offline(handle) + self._online_contacts = {} + self._joined_activites = [] + self._activites = {} + def _contact_offline(self, handle): """Handle contact going offline (send message, update set)""" if not self._online_contacts.has_key(handle): @@ -659,6 +672,9 @@ class ServerPlugin(gobject.GObject): timestamp, statuses = presence[handle] online = handle in self._online_contacts for status, params in statuses.items(): + if not online and status == "offline": + # weren't online in the first place... + continue jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] olstr = "ONLINE" if not online: olstr = "OFFLINE" |