added timeout for resolving

added proper dispatch signals so contacts get shown
fixed some errors with roster data
This commit is contained in:
Stefan Bethge 2006-06-13 21:19:39 +00:00
parent 40fc5202a5
commit 7da0b4c220
4 changed files with 125 additions and 109 deletions

View File

@ -296,3 +296,44 @@ class ConnectionHandlersZeroconf(ConnectionVcard):
i += 1 i += 1
return dic 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

View File

@ -34,6 +34,8 @@ import signal
if os.name != 'nt': if os.name != 'nt':
signal.signal(signal.SIGPIPE, signal.SIG_DFL) signal.signal(signal.SIGPIPE, signal.SIG_DFL)
import gobject
from common import helpers from common import helpers
from common import gajim from common import gajim
from common import GnuPG from common import GnuPG
@ -54,30 +56,26 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.name = name self.name = name
self.zeroconf = zeroconf.Zeroconf(self._on_new_service, self._on_remove_service) self.zeroconf = zeroconf.Zeroconf(self._on_new_service, self._on_remove_service)
self.connected = 0 # offline self.connected = 0 # offline
self.connection = None # dummy connection variable self.connection = None
# this property is used to prevent double connections
# self.last_connection = None # last ClientCommon instance
self.gpg = None self.gpg = None
self.is_zeroconf = True self.is_zeroconf = True
self.status = '' self.status = ''
self.old_show = '' self.old_show = ''
# increase/decrease default timeout for server responses
self.try_connecting_for_foo_secs = 45 self.call_resolve_timeout = False
# holds the actual hostname to which we are connected
# self.connected_hostname = None #self.time_to_reconnect = None
self.time_to_reconnect = None #self.new_account_info = None
self.new_account_info = None #self.bookmarks = []
self.bookmarks = []
self.on_purpose = False self.on_purpose = False
self.last_io = gajim.idlequeue.current_time() #self.last_io = gajim.idlequeue.current_time()
self.last_sent = [] #self.last_sent = []
self.last_history_line = {} #self.last_history_line = {}
self.password = gajim.config.get_per('accounts', name, 'password')
# self.server_resource = gajim.config.get_per('accounts', name, 'resource') #we don't need a password
# if gajim.config.get_per('accounts', self.name, 'keep_alives_enabled'): self.password = 'dummy' # gajim.config.get_per('accounts', name, 'password')
# self.keepalives = gajim.config.get_per('accounts', self.name,'keep_alive_every_foo_secs')
# else:
# self.keepalives = 0
self.privacy_rules_supported = False self.privacy_rules_supported = False
# Do we continue connection when we get roster (send presence,get vcard...) # Do we continue connection when we get roster (send presence,get vcard...)
self.continue_connect_info = None self.continue_connect_info = None
@ -92,6 +90,9 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.retrycount = 0 self.retrycount = 0
self.jids_for_auto_auth = [] # list of jid to auto-authorize 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__ # END __init__
def put_event(self, ev): def put_event(self, ev):
if gajim.handlers.has_key(ev[0]): if gajim.handlers.has_key(ev[0]):
@ -103,20 +104,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
def _reconnect(self): 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') gajim.log.debug('reconnect')
signed = self.get_signed_msg(self.status) signed = self.get_signed_msg(self.status)
@ -131,32 +118,9 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
# make sure previous connection is completely closed # make sure previous connection is completely closed
self.last_connection = None self.last_connection = None
self.connection = None self.connection = None
self.call_resolve_timeout = False
self.zeroconf.disconnect() 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): def quit(self, kill_core):
if kill_core and self.connected > 1: if kill_core and self.connected > 1:
@ -188,14 +152,25 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.dispatch('BAD_PASSPHRASE', ()) self.dispatch('BAD_PASSPHRASE', ())
return signed 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): def _on_new_service(self,jid):
self.roster.setItem(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)) self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), '', 'Gajim', 0, None, 0))
def _on_remove_service(self,jid): def _on_remove_service(self,jid):
self.roster.delItem(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'): def connect(self, data = None, show = 'online'):
if self.connection: if self.connection:
@ -207,6 +182,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.dispatch('ROSTER', self.roster) self.dispatch('ROSTER', self.roster)
self.connected = STATUS_LIST.index(show) 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): def connect_and_init(self, show, msg, signed):
self.continue_connect_info = [show, msg, signed] self.continue_connect_info = [show, msg, signed]
@ -215,13 +194,13 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
self.connect('',show) self.connect('',show)
def change_status(self, show, msg, sync = False, auto = False): 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: if not show in STATUS_LIST:
return -1 return -1
# 'connect' # 'connect'
if show != 'offline' and not self.connected: 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.on_purpose = False
self.connect_and_init(show, msg, '') self.connect_and_init(show, msg, '')
if show != 'invisible': if show != 'invisible':
@ -231,22 +210,21 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
# 'disconnect' # 'disconnect'
elif show == 'offline' and self.connected: elif show == 'offline' and self.connected:
print "disconnect in change_status" print "connection_zeroconf.py: disconnect in change_status"
self.connected = 0 self.connected = 0
self.dispatch('STATUS', 'offline') self.dispatch('STATUS', 'offline')
self.disconnect() self.disconnect()
#self._on_disconnected()
# update status # update status
elif show != 'offline' and self.connected: 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') 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() self.zeroconf.remove_announce()
return return
if was_invisible: if was_invisible:
print "announce after invisible in change_status" print "connection_zeroconf.py: reannounce after invisible in change_status"
self.zeroconf.announce() self.zeroconf.announce()
if self.connection: if self.connection:
txt = {} txt = {}

View File

@ -6,17 +6,12 @@ class Roster:
self.zeroconf = zeroconf # our zeroconf instance self.zeroconf = zeroconf # our zeroconf instance
def getRoster(self): def getRoster(self):
print 'getRoster in Roster' print 'roster_zeroconf.py: getRoster'
self._data = self.zeroconf.get_contacts() self._data = self.zeroconf.get_contacts().copy()
return self 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 = ''): 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) \ (service_jid, domain, interface, protocol, host, address, port, txt) \
= self.zeroconf.get_contact(jid) = self.zeroconf.get_contact(jid)
@ -29,67 +24,66 @@ class Roster:
self._data[jid]['address'] = address self._data[jid]['address'] = address
self._data[jid]['host'] = host self._data[jid]['host'] = host
self._data[jid]['port'] = port self._data[jid]['port'] = port
self._data[jid]['txt'] = txt
txt_dict = self.zeroconf.txt_array_to_dict(txt) txt_dict = self.zeroconf.txt_array_to_dict(txt)
if txt_dict.has_key('status'): if txt_dict.has_key('status'):
status = txt_dict['status'] status = txt_dict['status']
else: else:
status = '' status = ''
if status == 'avail': status = 'online' if status == 'avail': status = 'online'
self._data[jid]['txt_dict'] = txt_dict
self._data[jid]['status'] = status self._data[jid]['status'] = status
self._data[jid]['show'] = status self._data[jid]['show'] = status
print self._data[jid]
# print self._data[jid]
def delItem(self, jid): def delItem(self, jid):
print 'delItem %s in Roster' % jid print 'roster_zeroconf.py: delItem %s' % jid
if self._data.has_key(jid): if self._data.has_key(jid):
del self._data[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): def __getitem__(self,jid):
print '__getitem__ in Roster' print 'roster_zeroconf.py: __getitem__'
return self._data[jid] return self._data[jid]
def getItems(self): def getItems(self):
print 'getItems in Roster' print 'roster_zeroconf.py: getItems'
# Return list of all [bare] JIDs that the roster is currently tracks. # Return list of all [bare] JIDs that the roster currently tracks.
return self._data.keys() return self._data.keys()
def keys(self): def keys(self):
print 'keys in Roster' print 'roster_zeroconf.py: keys'
return self._data.keys() return self._data.keys()
def getRaw(self): def getRaw(self):
print 'getRaw in Roster' print 'roster_zeroconf.py: getRaw'
return self._data return self._data
def getResources(self, jid): def getResources(self, jid):
print 'getResources(%s) in Roster' % jid print 'roster_zeroconf.py: getResources(%s)' % jid
return {} return {}
def getStatus(self, jid): def getGroups(self, jid):
print 'getStatus %s in Roster' % jid print 'roster_zeroconf.py: getGroups(%s)' % jid
txt = self._data[jid]['txt'] return self._data[jid]['groups']
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 == '': def getStatus(self, jid):
return 'online' print 'roster_zeroconf.py: getStatus %s' % jid
else: return self._data[jid]['status']
return status
def getShow(self, jid): def getShow(self, jid):
print 'getShow in Roster' print 'roster_zeroconf.py: getShow'
return getStatus(jid) return getStatus(jid)
def getPriority(jid): def getPriority(jid):
return 5 return 5
def getSubscription(self,jid): def getSubscription(self,jid):
print 'getSubscription in Roster' print 'roster_zeroconf.py: getSubscription'
return 'both' return 'both'
def Subscribe(self,jid): def Subscribe(self,jid):

View File

@ -18,7 +18,9 @@ class Zeroconf:
self.domain = None # specific domain to browse self.domain = None # specific domain to browse
self.stype = '_presence._tcp' self.stype = '_presence._tcp'
self.port = 5298 # listening port that gets announced 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.txt = {} # service data
self.new_serviceCB = new_serviceCB self.new_serviceCB = new_serviceCB
@ -35,6 +37,7 @@ class Zeroconf:
print "Error:", str(err) print "Error:", str(err)
def new_service_callback(self, interface, protocol, name, stype, domain, flags): def new_service_callback(self, interface, protocol, name, stype, domain, flags):
if name != self.name:
print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol) print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol)
#synchronous resolving #synchronous resolving
@ -186,7 +189,6 @@ class Zeroconf:
def disconnect(self): def disconnect(self):
self.remove_announce() self.remove_announce()
# refresh data manually - really ok or too much traffic? # refresh data manually - really ok or too much traffic?
def resolve_all(self): def resolve_all(self):
for val in self.contacts.values(): for val in self.contacts.values():
@ -194,12 +196,13 @@ class Zeroconf:
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),\ self.stype, val[1], avahi.PROTO_UNSPEC, dbus.UInt32(0),\
reply_handler=self.service_resolved_all_callback, error_handler=self.print_error_callback) reply_handler=self.service_resolved_all_callback, error_handler=self.print_error_callback)
print "zeroconf.py: resolve_all"
def get_contacts(self): def get_contacts(self):
self.resolve_all()
return self.contacts return self.contacts
def get_contact(self, jid): def get_contact(self, jid):
if self.contacts.has_key(jid):
return self.contacts[jid] return self.contacts[jid]
def update_txt(self, txt): def update_txt(self, txt):