From b7ceb9ddf7105381608ef645ccc1c4c441f21ec7 Mon Sep 17 00:00:00 2001 From: Dimitur Kirov Date: Mon, 2 Oct 2006 20:45:49 +0000 Subject: [PATCH] bind to next available port updating port also publishes the new port keep 1st, last as unicode --- src/common/zeroconf/client_zeroconf.py | 97 +++++++++++++-- src/common/zeroconf/connection_zeroconf.py | 132 +++++++++------------ src/common/zeroconf/zeroconf.py | 11 +- src/config.py | 17 ++- 4 files changed, 150 insertions(+), 107 deletions(-) diff --git a/src/common/zeroconf/client_zeroconf.py b/src/common/zeroconf/client_zeroconf.py index 9f6005b6f..f28de2135 100644 --- a/src/common/zeroconf/client_zeroconf.py +++ b/src/common/zeroconf/client_zeroconf.py @@ -18,7 +18,8 @@ from common.xmpp.idlequeue import IdleObject from common.xmpp import dispatcher_nb, simplexml from common.xmpp.client import * from common.xmpp.simplexml import ustr -from dialogs import BindPortError +from common.zeroconf import zeroconf + from common.xmpp.protocol import * import socket import errno @@ -459,13 +460,86 @@ class P2PConnection(IdleObject, PlugIn): class ClientZeroconf: - def __init__(self, zeroconf, caller): - self.roster = roster_zeroconf.Roster(zeroconf) + def __init__(self, caller): self.caller = caller - self.start_listener(zeroconf.port) + self.zeroconf = None + self.roster = None + self.last_msg = '' self.connections = {} self.recipient_to_hash = {} self.ip_to_hash = {} + + def test_avahi(self): + #~ self.avahi_error = False + try: + import avahi + except ImportError: + #~ self.avahi_error = True + return False + return True + + def connect(self, show, msg): + self.port = self.start_listener(self.caller.port) + if not self.port: + return + self.zeroconf_init(show, msg) + if not self.zeroconf.connect(): + self.disconnect() + return + self.roster = roster_zeroconf.Roster(self.zeroconf) + + def remove_announce(self): + return self.zeroconf.remove_announce() + + def announce(self): + return self.zeroconf.announce() + + def set_show_msg(self, show, msg): + self.zeroconf.txt['msg'] = msg + self.last_msg = msg + return self.zeroconf.update_txt(show) + + def resolve_all(self): + self.zeroconf.resolve_all() + + def reannounce(self, txt): + #~ if self.zeroconf: + self.remove_announce() + self.zeroconf.txt = txt + self.zeroconf.port = self.port + self.zeroconf.username = self.caller.username + return self.announce() + + + def zeroconf_init(self, show, msg): + self.zeroconf = zeroconf.Zeroconf(self.caller._on_new_service, + self.caller._on_remove_service, self.caller._on_name_conflictCB, + self.caller._on_disconnected, self.caller.username, self.caller.host, + self.port) + self.zeroconf.txt['msg'] = msg + self.zeroconf.txt['status'] = show + self.zeroconf.txt['1st'] = self.caller.first + self.zeroconf.txt['last'] = self.caller.last + self.zeroconf.txt['jid'] = self.caller.jabber_id + self.zeroconf.txt['email'] = self.caller.email + self.zeroconf.username = self.caller.username + self.zeroconf.host = self.caller.host + self.zeroconf.port = self.port + self.last_msg = msg + + def disconnect(self): + if self.listener: + self.listener.disconnect() + self.listener = None + if self.zeroconf: + self.zeroconf.disconnect() + self.zeroconf = None + if self.roster: + self.roster.zeroconf = None + self.roster._data = None + self.roster = None + #~ self.caller.show = 'offline' + #~ self.caller.dispatch('STATUS', 'offline') def kill_all_connections(self): for connection in self.connections.values(): @@ -492,14 +566,13 @@ class ClientZeroconf: break def start_listener(self, port): - self.listener = ZeroconfListener(port, self) - self.listener.bind() - if self.listener.started is False: - self.listener = None - # We cannot bind port, call error - # dialog from dialogs.py and fail - BindPortError(port) - return None + for p in range(port, port + 5): + self.listener = ZeroconfListener(p, self) + self.listener.bind() + if self.listener.started: + return p + self.listener = None + return False def getRoster(self): return self.roster.getRoster() diff --git a/src/common/zeroconf/connection_zeroconf.py b/src/common/zeroconf/connection_zeroconf.py index b7d86ac11..ba7c5f74d 100644 --- a/src/common/zeroconf/connection_zeroconf.py +++ b/src/common/zeroconf/connection_zeroconf.py @@ -42,7 +42,6 @@ import notify from common import helpers from common import gajim from common import GnuPG -from common.zeroconf import zeroconf from common.zeroconf import connection_handlers_zeroconf from common.zeroconf import client_zeroconf from connection_handlers_zeroconf import * @@ -87,17 +86,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.get_config_values_or_default() - self.avahi_error = False - try: - import avahi - except ImportError: - self.avahi_error = True - - if not self.avahi_error: - self.zeroconf = zeroconf.Zeroconf(self._on_new_service, - self._on_remove_service, self._on_name_conflictCB, - self._on_disconnected, self.username, self.host, self.port) - self.muc_jid = {} # jid of muc server for each transport type self.vcard_supported = False @@ -185,7 +173,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): def _on_resolve_timeout(self): if self.connected: - self.zeroconf.resolve_all() + self.connection.resolve_all() diffs = self.roster.getDiffs() for key in diffs: self.roster.setItem(key) @@ -218,71 +206,72 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): def connect(self, data = None, show = 'online', msg = ''): self.get_config_values_or_default() - - self.zeroconf.txt['status'] = show - self.zeroconf.txt['msg'] = msg - self.zeroconf.txt['1st'] = self.first - self.zeroconf.txt['last'] = self.last - self.zeroconf.txt['jid'] = self.jabber_id - self.zeroconf.txt['email'] = self.email - self.zeroconf.username = self.username - self.zeroconf.host = self.host - self.zeroconf.port = self.port - - if self.zeroconf.connect(): - if not self.connection: - self.connection = client_zeroconf.ClientZeroconf(self.zeroconf, self) - else: - self.zeroconf.announce() - self.roster = self.connection.getRoster() - self.dispatch('ROSTER', self.roster) - - #display contacts already detected and resolved - for jid in self.roster.keys(): - self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid))) - self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0)) - - self.connected = STATUS_LIST.index(show) - - # refresh all contacts data every five seconds - self.call_resolve_timeout = True - gobject.timeout_add(5000, self._on_resolve_timeout) + if not self.connection: + self.connection = client_zeroconf.ClientZeroconf(self) + if not self.connection.test_avahi(): + self.dispatch('STATUS', 'offline') + self.status = 'offline' + self.dispatch('CONNECTION_LOST', + (_('Could not connect to "%s"') % self.name, + _('Please check if Avahi is installed.'))) + return + self.connection.connect(show, msg) + if not self.connection.listener: + self.status = 'offline' + self.dispatch('CONNECTION_LOST', + (_('Could not start local service') % self.name, + _('Unable to bind to port "%d".' % self.port))) + return else: - self.dispatch('STATUS', 'offline') - self.status = 'offline' + self.connection.announce() + self.roster = self.connection.getRoster() + self.dispatch('ROSTER', self.roster) + + #display contacts already detected and resolved + for jid in self.roster.keys(): + self.dispatch('ROSTER_INFO', (jid, self.roster.getName(jid), 'both', 'no', self.roster.getGroups(jid))) + self.dispatch('NOTIFY', (jid, self.roster.getStatus(jid), self.roster.getMessage(jid), 'local', 0, None, 0)) + + self.connected = STATUS_LIST.index(show) + + # refresh all contacts data every five seconds + self.call_resolve_timeout = True + gobject.timeout_add(5000, self._on_resolve_timeout) + return True def disconnect(self, on_purpose = False): self.connected = 0 self.time_to_reconnect = None if self.connection: - if self.connection.listener: - self.connection.listener.disconnect() + self.connection.disconnect() self.connection = None # stop calling the timeout self.call_resolve_timeout = False - self.zeroconf.disconnect() + - def reconnect(self): + def reannounce(self): if self.connected: txt = {} txt['1st'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_first_name') txt['last'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_last_name') txt['jid'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_jabber_id') txt['email'] = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'zeroconf_email') - - self.zeroconf.remove_announce() - self.zeroconf.txt = txt - self.zeroconf.port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'custom_port') - self.zeroconf.username = self.username - self.zeroconf.announce() + self.connection.reannounce(txt) - def restart_listener(self): + def update_details(self): if self.connection: port = gajim.config.get_per('accounts', gajim.ZEROCONF_ACC_NAME, 'custom_port') - self.connection.kill_all_connections() - if self.connection.listener: - self.connection.listener.disconnect() - self.connection.start_listener(port) + if self.connection: + if port != self.port: + self.port = port + last_msg = self.connection.last_msg + self.disconnect() + if not self.connect(show = self.status, msg = last_msg): + return + if self.status != 'invisible': + self.connection.announce() + else: + self.reannounce() def change_status(self, show, msg, sync = False, auto = False): if not show in STATUS_LIST: @@ -290,22 +279,14 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.status = show check = True #to check for errors from zeroconf - - if self.avahi_error: - self.dispatch('STATUS', 'offline') - self.status = 'offline' - self.dispatch('CONNECTION_LOST', - (_('Could not connect to "%s"') % self.name, - _('Please check if Avahi is installed.'))) - return - # 'connect' if show != 'offline' and not self.connected: - self.connect(None, show, msg) + if not self.connect(None, show, msg): + return if show != 'invisible': - check = self.zeroconf.announce() + check = self.connection.announce() else: - self.connected = STATUS_LIST.index(show) + self.connected = STATUS_LIST.index(show) # 'disconnect' elif show == 'offline' and self.connected: @@ -317,14 +298,11 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): was_invisible = self.connected == STATUS_LIST.index('invisible') self.connected = STATUS_LIST.index(show) if show == 'invisible': - check = check and self.zeroconf.remove_announce() + check = check and self.connection.remove_announce() elif was_invisible: - check = check and self.zeroconf.announce() + check = check and self.connection.announce() if self.connection and not show == 'invisible': - txt = {} - txt['status'] = show - txt['msg'] = msg - check = check and self.zeroconf.update_txt(txt) + check = check and self.connection.set_show_msg(show, msg) #stay offline when zeroconf does something wrong if check: diff --git a/src/common/zeroconf/zeroconf.py b/src/common/zeroconf/zeroconf.py index fccf1a635..1977b6f81 100755 --- a/src/common/zeroconf/zeroconf.py +++ b/src/common/zeroconf/zeroconf.py @@ -324,14 +324,9 @@ class Zeroconf: def get_contact(self, jid): return self.contacts[jid] - def update_txt(self, txt): - # update only new non-empty keys - for key in txt.keys(): - if txt[key]: - self.txt[key]=txt[key] - - if txt.has_key('status'): - self.txt['status'] = self.replace_show(txt['status']) + def update_txt(self, show = None): + if show: + self.txt['status'] = self.replace_show(show) txt = avahi.dict_to_txt_array(self.txt) if self.connected and self.entrygroup: diff --git a/src/config.py b/src/config.py index 316f24050..d787e48f8 100644 --- a/src/config.py +++ b/src/config.py @@ -3215,16 +3215,16 @@ class ZeroconfPropertiesWindow: config['sync_with_global_status'] = st st = self.xml.get_widget('first_name_entry').get_text() - config['zeroconf_first_name'] = st + config['zeroconf_first_name'] = st.decode('utf-8') st = self.xml.get_widget('last_name_entry').get_text() - config['zeroconf_last_name'] = st + config['zeroconf_last_name'] = st.decode('utf-8') st = self.xml.get_widget('jabber_id_entry').get_text() - config['zeroconf_jabber_id'] = st + config['zeroconf_jabber_id'] = st.decode('utf-8') st = self.xml.get_widget('email_entry').get_text() - config['zeroconf_email'] = st + config['zeroconf_email'] = st.decode('utf-8') use_custom_port = self.xml.get_widget('custom_port_checkbutton').get_active() config['use_custom_host'] = use_custom_port @@ -3258,12 +3258,9 @@ class ZeroconfPropertiesWindow: gajim.config.set_per('accounts', gajim.ZEROCONF_ACC_NAME, opt, config[opt]) if gajim.connections.has_key(gajim.ZEROCONF_ACC_NAME): - if port != old_port: - # restart listener if port has changed - gajim.connections[gajim.ZEROCONF_ACC_NAME].restart_listener() - if reconnect: - gajim.connections[gajim.ZEROCONF_ACC_NAME].reconnect() - + if port != old_port or reconnect: + gajim.connections[gajim.ZEROCONF_ACC_NAME].update_details() + self.window.destroy() def on_gpg_choose_button_clicked(self, widget, data = None):