bind to next available port

updating port also publishes the new port
keep 1st, last as unicode
This commit is contained in:
Dimitur Kirov 2006-10-02 20:45:49 +00:00
parent ac53b4537c
commit b7ceb9ddf7
4 changed files with 150 additions and 107 deletions

View File

@ -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()

View File

@ -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:

View File

@ -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:

View File

@ -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):