SRV records are now properly supported (swich to another SRV record when first one is not available)
This commit is contained in:
parent
e0bf58cba7
commit
e8069e56ad
|
@ -30,6 +30,8 @@ import traceback
|
||||||
import threading
|
import threading
|
||||||
import select
|
import select
|
||||||
import socket
|
import socket
|
||||||
|
import random
|
||||||
|
random.seed()
|
||||||
import signal
|
import signal
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||||
|
@ -1415,6 +1417,30 @@ class Connection:
|
||||||
elif event == common.xmpp.transports.DATA_SENT:
|
elif event == common.xmpp.transports.DATA_SENT:
|
||||||
self.dispatch('STANZA_SENT', unicode(data))
|
self.dispatch('STANZA_SENT', unicode(data))
|
||||||
|
|
||||||
|
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']
|
||||||
|
to_return = h
|
||||||
|
return h
|
||||||
|
|
||||||
def connect(self, data = None):
|
def connect(self, data = None):
|
||||||
"""Connect and authenticate to the Jabber server
|
"""Connect and authenticate to the Jabber server
|
||||||
Returns connection, and connection type ('tls', 'ssl', 'tcp', '')
|
Returns connection, and connection type ('tls', 'ssl', 'tcp', '')
|
||||||
|
@ -1480,36 +1506,47 @@ class Connection:
|
||||||
p = custom_p
|
p = custom_p
|
||||||
use_srv = False
|
use_srv = False
|
||||||
|
|
||||||
|
hosts = []
|
||||||
# SRV resolver
|
# SRV resolver
|
||||||
if use_srv and (HAVE_DNSPYTHON or HAVE_PYDNS):
|
if use_srv and (HAVE_DNSPYTHON or HAVE_PYDNS):
|
||||||
possible_queries = ['_xmpp-client._tcp.' + h]
|
query = '_xmpp-client._tcp.' + h
|
||||||
|
try:
|
||||||
for query in possible_queries:
|
if HAVE_DNSPYTHON:
|
||||||
try:
|
answers = [x for x in dns.resolver.query(query, 'SRV')]
|
||||||
if HAVE_DNSPYTHON:
|
if answers:
|
||||||
answers = [x for x in dns.resolver.query(query, 'SRV')]
|
for a in answers:
|
||||||
if answers:
|
hosts.append({'host': str(a.target),
|
||||||
h = str(answers[0].target)
|
'port': int(a.port),
|
||||||
p = int(answers[0].port)
|
'prio': int(a.priority),
|
||||||
break
|
'weight': int(a.weight)})
|
||||||
elif HAVE_PYDNS:
|
elif HAVE_PYDNS:
|
||||||
# ensure we haven't cached an old configuration
|
# ensure we haven't cached an old configuration
|
||||||
DNS.ParseResolvConf()
|
DNS.ParseResolvConf()
|
||||||
response = DNS.Request().req(query, qtype = 'SRV')
|
response = DNS.Request().req(query, qtype = 'SRV')
|
||||||
answers = response.answers
|
answers = response.answers
|
||||||
if len(answers) > 0:
|
if len(answers) > 0:
|
||||||
# ignore the priority and weight for now
|
# ignore the priority and weight for now
|
||||||
_t, _t, p, h = answers[0]['data']
|
for a in answers:
|
||||||
del _t
|
prio, weight, port, host = answers[0]['data']
|
||||||
p = int(p)
|
hosts.append({'host': host,
|
||||||
break
|
'port': port,
|
||||||
except:
|
'prio': prio,
|
||||||
gajim.log.debug('An error occurred while looking up %s' % query)
|
'weight': weight})
|
||||||
|
except:
|
||||||
|
gajim.log.debug('An error occurred while looking up %s' % query)
|
||||||
# end of SRV resolver
|
# end of SRV resolver
|
||||||
|
|
||||||
con_type = con.connect((h, p), proxy = proxy, secure = secur)
|
if len(hosts) == 0: # SRV fails or misconfigred on the server
|
||||||
if not self.connected: # We went offline during connecting process
|
hosts = [ {'host': h, 'port': p, 'prio': 10, 'weight': 10} ]
|
||||||
return None, ''
|
|
||||||
|
con_type = None
|
||||||
|
while len(hosts) and not con_type:
|
||||||
|
host = self.select_next_host(hosts)
|
||||||
|
con_type = con.connect((host['host'], host['port']), proxy = proxy,
|
||||||
|
secure = secur)
|
||||||
|
if not self.connected: # We went offline during connecting process
|
||||||
|
return None, ''
|
||||||
|
hosts.remove(host)
|
||||||
if not con_type:
|
if not con_type:
|
||||||
gajim.log.debug('Could not connect to %s' % h)
|
gajim.log.debug('Could not connect to %s' % h)
|
||||||
if not self.retrycount:
|
if not self.retrycount:
|
||||||
|
|
Loading…
Reference in New Issue