From 7da0b4c220feafca3362ebe6944a1d7f1ea4a66f Mon Sep 17 00:00:00 2001 From: Stefan Bethge Date: Tue, 13 Jun 2006 21:19:39 +0000 Subject: [PATCH] added timeout for resolving added proper dispatch signals so contacts get shown fixed some errors with roster data --- src/common/connection_handlers_zeroconf.py | 41 ++++++++ src/common/connection_zeroconf.py | 112 +++++++++------------ src/common/roster_zeroconf.py | 58 +++++------ src/common/zeroconf.py | 23 +++-- 4 files changed, 125 insertions(+), 109 deletions(-) diff --git a/src/common/connection_handlers_zeroconf.py b/src/common/connection_handlers_zeroconf.py index 6eaf9dd05..f0f17b7df 100644 --- a/src/common/connection_handlers_zeroconf.py +++ b/src/common/connection_handlers_zeroconf.py @@ -295,4 +295,45 @@ class ConnectionHandlersZeroconf(ConnectionVcard): dic[i]['values'] = [dic[i]['options'][0]['values'][0]] i += 1 return dic + + def remove_transfers_for_contact(self, contact): + ''' stop all active transfer for contact ''' + '''for file_props in self.files_props.values(): + if self.is_transfer_stoped(file_props): + continue + receiver_jid = unicode(file_props['receiver']).split('/')[0] + if contact.jid == receiver_jid: + file_props['error'] = -5 + self.remove_transfer(file_props) + self.dispatch('FILE_REQUEST_ERROR', (contact.jid, file_props)) + sender_jid = unicode(file_props['sender']).split('/')[0] + if contact.jid == sender_jid: + file_props['error'] = -3 + self.remove_transfer(file_props) + ''' + pass + def remove_all_transfers(self): + ''' stops and removes all active connections from the socks5 pool ''' + ''' + for file_props in self.files_props.values(): + self.remove_transfer(file_props, remove_from_list = False) + del(self.files_props) + self.files_props = {} + ''' + pass + + def remove_transfer(self, file_props, remove_from_list = True): + ''' + if file_props is None: + return + self.disconnect_transfer(file_props) + sid = file_props['sid'] + gajim.socks5queue.remove_file_props(self.name, sid) + + if remove_from_list: + if self.files_props.has_key('sid'): + del(self.files_props['sid']) + ''' + pass + diff --git a/src/common/connection_zeroconf.py b/src/common/connection_zeroconf.py index 921792af4..f666be930 100644 --- a/src/common/connection_zeroconf.py +++ b/src/common/connection_zeroconf.py @@ -34,6 +34,8 @@ import signal if os.name != 'nt': signal.signal(signal.SIGPIPE, signal.SIG_DFL) +import gobject + from common import helpers from common import gajim from common import GnuPG @@ -54,30 +56,26 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.name = name self.zeroconf = zeroconf.Zeroconf(self._on_new_service, self._on_remove_service) self.connected = 0 # offline - self.connection = None # dummy connection variable - # this property is used to prevent double connections -# self.last_connection = None # last ClientCommon instance + self.connection = None self.gpg = None self.is_zeroconf = True self.status = '' self.old_show = '' - # increase/decrease default timeout for server responses - self.try_connecting_for_foo_secs = 45 - # holds the actual hostname to which we are connected -# self.connected_hostname = None - self.time_to_reconnect = None - self.new_account_info = None - self.bookmarks = [] + + self.call_resolve_timeout = False + + #self.time_to_reconnect = None + #self.new_account_info = None + #self.bookmarks = [] + self.on_purpose = False - self.last_io = gajim.idlequeue.current_time() - self.last_sent = [] - self.last_history_line = {} - self.password = gajim.config.get_per('accounts', name, 'password') -# self.server_resource = gajim.config.get_per('accounts', name, 'resource') -# if gajim.config.get_per('accounts', self.name, 'keep_alives_enabled'): -# self.keepalives = gajim.config.get_per('accounts', self.name,'keep_alive_every_foo_secs') -# else: -# self.keepalives = 0 + #self.last_io = gajim.idlequeue.current_time() + #self.last_sent = [] + #self.last_history_line = {} + + #we don't need a password + self.password = 'dummy' # gajim.config.get_per('accounts', name, 'password') + self.privacy_rules_supported = False # Do we continue connection when we get roster (send presence,get vcard...) self.continue_connect_info = None @@ -91,7 +89,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.on_connect_failure = None self.retrycount = 0 self.jids_for_auto_auth = [] # list of jid to auto-authorize - + + gajim.config.set_per('accounts', name, 'name', self.zeroconf.username) + gajim.config.set_per('accounts', name, 'hostname', self.zeroconf.host) + # END __init__ def put_event(self, ev): if gajim.handlers.has_key(ev[0]): @@ -103,20 +104,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): def _reconnect(self): - '''# Do not try to reco while we are already trying - self.time_to_reconnect = None - if self.connected < 2: #connection failed - gajim.log.debug('reconnect') - self.retrycount += 1 - signed = self.get_signed_msg(self.status) - self.on_connect_auth = self._init_roster - self.connect_and_init(self.old_show, self.status, signed) - else: - # reconnect succeeded - self.time_to_reconnect = None - self.retrycount = 0 - ''' - gajim.log.debug('reconnect') signed = self.get_signed_msg(self.status) @@ -131,32 +118,9 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): # make sure previous connection is completely closed self.last_connection = None self.connection = None + self.call_resolve_timeout = False self.zeroconf.disconnect() - def select_next_host(self, hosts): - hosts_best_prio = [] - best_prio = 65535 - sum_weight = 0 - for h in hosts: - if h['prio'] < best_prio: - hosts_best_prio = [h] - best_prio = h['prio'] - sum_weight = h['weight'] - elif h['prio'] == best_prio: - hosts_best_prio.append(h) - sum_weight += h['weight'] - if len(hosts_best_prio) == 1: - return hosts_best_prio[0] - r = random.randint(0, sum_weight) - min_w = sum_weight - # We return the one for which has the minimum weight and weight >= r - for h in hosts_best_prio: - if h['weight'] >= r: - if h['weight'] <= min_w: - min_w = h['weight'] - return h - - def quit(self, kill_core): if kill_core and self.connected > 1: @@ -188,24 +152,39 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.dispatch('BAD_PASSPHRASE', ()) return signed + def _on_resolve_timeout(self): + if self.connected: + self.zeroconf.resolve_all() + return self.call_resolve_timeout + + # callbacks called from zeroconf def _on_new_service(self,jid): self.roster.setItem(jid) - #self.dispatch('ROSTER', self.roster) + self.dispatch('ROSTER_INFO', (jid, jid, 'both', 'no', self.roster.getGroups(jid))) self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), '', 'Gajim', 0, None, 0)) + def _on_remove_service(self,jid): self.roster.delItem(jid) - #self.dispatch('NOTIFY', self, ) + # 'NOTIFY' (account, (jid, status, status message, resource, priority, + # keyID, timestamp)) + self.dispatch('NOTIFY', (jid, 'offline', '', 'Gajim', 0 +, None, 0)) + def connect(self, data = None, show = 'online'): if self.connection: return self.connection, '' - + self.zeroconf.connect() self.connection = client_zeroconf.ClientZeroconf(self.zeroconf) self.roster = self.connection.getRoster() self.dispatch('ROSTER', self.roster) self.connected = STATUS_LIST.index(show) + + # refresh all contacts data all 10 seconds + self.call_timeout = True + gobject.timeout_add(10000, self._on_resolve_timeout) def connect_and_init(self, show, msg, signed): self.continue_connect_info = [show, msg, signed] @@ -215,13 +194,13 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.connect('',show) def change_status(self, show, msg, sync = False, auto = False): - print "change_status: show: %s msg: %s" % (show, msg) + print "connection_zeroconf.py: show: %s msg: %s in change_status" % (show, msg) if not show in STATUS_LIST: return -1 # 'connect' if show != 'offline' and not self.connected: - print "connect in change_status" + print "connection_zeroconf.py: connect in change_status" self.on_purpose = False self.connect_and_init(show, msg, '') if show != 'invisible': @@ -231,22 +210,21 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): # 'disconnect' elif show == 'offline' and self.connected: - print "disconnect in change_status" + print "connection_zeroconf.py: disconnect in change_status" self.connected = 0 self.dispatch('STATUS', 'offline') self.disconnect() - #self._on_disconnected() # update status elif show != 'offline' and self.connected: - print "update in change_status" + print "connection_zeroconf.py: update in change_status" was_invisible = self.connected == STATUS_LIST.index('invisible') self.connected = STATUS_LIST.index(show) if show == 'invisible': self.zeroconf.remove_announce() return if was_invisible: - print "announce after invisible in change_status" + print "connection_zeroconf.py: reannounce after invisible in change_status" self.zeroconf.announce() if self.connection: txt = {} diff --git a/src/common/roster_zeroconf.py b/src/common/roster_zeroconf.py index 480afbe76..6ec8bf070 100644 --- a/src/common/roster_zeroconf.py +++ b/src/common/roster_zeroconf.py @@ -6,17 +6,12 @@ class Roster: self.zeroconf = zeroconf # our zeroconf instance def getRoster(self): - print 'getRoster in Roster' - self._data = self.zeroconf.get_contacts() + print 'roster_zeroconf.py: getRoster' + self._data = self.zeroconf.get_contacts().copy() return self - def getItem(self, jid): - print 'getItem(%s) in Roster' % jid - if self._data.has_key(jid): - return self._data[jid] - def setItem(self, jid, name = '', groups = ''): - print 'setItem %s in Roster' % jid + print 'roster_zeroconf.py: setItem %s' % jid (service_jid, domain, interface, protocol, host, address, port, txt) \ = self.zeroconf.get_contact(jid) @@ -29,67 +24,66 @@ class Roster: self._data[jid]['address'] = address self._data[jid]['host'] = host self._data[jid]['port'] = port - self._data[jid]['txt'] = txt txt_dict = self.zeroconf.txt_array_to_dict(txt) if txt_dict.has_key('status'): status = txt_dict['status'] else: status = '' if status == 'avail': status = 'online' + self._data[jid]['txt_dict'] = txt_dict self._data[jid]['status'] = status self._data[jid]['show'] = status - print self._data[jid] + + # print self._data[jid] def delItem(self, jid): - print 'delItem %s in Roster' % jid + print 'roster_zeroconf.py: delItem %s' % jid if self._data.has_key(jid): del self._data[jid] + def getItem(self, jid): + print 'roster_zeroconf.py: getItem: %s' % jid + if self._data.has_key(jid): + return self._data[jid] + def __getitem__(self,jid): - print '__getitem__ in Roster' + print 'roster_zeroconf.py: __getitem__' return self._data[jid] def getItems(self): - print 'getItems in Roster' - # Return list of all [bare] JIDs that the roster is currently tracks. + print 'roster_zeroconf.py: getItems' + # Return list of all [bare] JIDs that the roster currently tracks. return self._data.keys() def keys(self): - print 'keys in Roster' + print 'roster_zeroconf.py: keys' return self._data.keys() def getRaw(self): - print 'getRaw in Roster' + print 'roster_zeroconf.py: getRaw' return self._data def getResources(self, jid): - print 'getResources(%s) in Roster' % jid + print 'roster_zeroconf.py: getResources(%s)' % jid return {} + + def getGroups(self, jid): + print 'roster_zeroconf.py: getGroups(%s)' % jid + return self._data[jid]['groups'] def getStatus(self, jid): - print 'getStatus %s in Roster' % jid - txt = self._data[jid]['txt'] - txt_dict = self.zeroconf.txt_array_to_dict(txt) - if txt_dict.has_key('status'): - status = txt_dict['status'] - else: - status = '' - - if status == 'avail' or status == '': - return 'online' - else: - return status + print 'roster_zeroconf.py: getStatus %s' % jid + return self._data[jid]['status'] def getShow(self, jid): - print 'getShow in Roster' + print 'roster_zeroconf.py: getShow' return getStatus(jid) - def getPriority(jid): return 5 def getSubscription(self,jid): - print 'getSubscription in Roster' + print 'roster_zeroconf.py: getSubscription' return 'both' def Subscribe(self,jid): diff --git a/src/common/zeroconf.py b/src/common/zeroconf.py index 518491f80..af052b0a8 100755 --- a/src/common/zeroconf.py +++ b/src/common/zeroconf.py @@ -18,7 +18,9 @@ class Zeroconf: self.domain = None # specific domain to browse self.stype = '_presence._tcp' self.port = 5298 # listening port that gets announced - self.name = getpass.getuser()+'@'+socket.gethostname() # service name + self.username = getpass.getuser() + self.host = socket.gethostname() + self.name = self.username+'@'+ self.host # service name self.txt = {} # service data self.new_serviceCB = new_serviceCB @@ -35,10 +37,11 @@ class Zeroconf: print "Error:", str(err) def new_service_callback(self, interface, protocol, name, stype, domain, flags): - print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol) - - #synchronous resolving - self.server.ResolveService( int(interface), int(protocol), name, stype, \ + if name != self.name: + print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol) + + #synchronous resolving + self.server.ResolveService( int(interface), int(protocol), name, stype, \ domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), \ reply_handler=self.service_resolved_callback, error_handler=self.print_error_callback) @@ -186,21 +189,21 @@ class Zeroconf: def disconnect(self): self.remove_announce() - # refresh data manually - really ok or too much traffic? def resolve_all(self): for val in self.contacts.values(): #val:(name, domain, interface, protocol, host, address, port, txt) - self.server.ResolveService( int(val[2]), int(val[3]), val[0], \ + self.server.ResolveService(int(val[2]), int(val[3]), val[0], \ self.stype, val[1], avahi.PROTO_UNSPEC, dbus.UInt32(0),\ reply_handler=self.service_resolved_all_callback, error_handler=self.print_error_callback) - + print "zeroconf.py: resolve_all" + def get_contacts(self): - self.resolve_all() return self.contacts def get_contact(self, jid): - return self.contacts[jid] + if self.contacts.has_key(jid): + return self.contacts[jid] def update_txt(self, txt): # update only given keys