From 149edfe3efa9f7d13702f164d921c35e8b5c3ef1 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sun, 19 Nov 2017 22:35:45 +0100 Subject: [PATCH] implement XEP-0156. Fixes #5795 --- gajim/common/connection.py | 29 +++++++++++++++++++++++++++++ gajim/common/resolver.py | 18 +++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/gajim/common/connection.py b/gajim/common/connection.py index 692dd2c0d..4a89b5956 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -181,6 +181,11 @@ class CommonConnection: self.get_config_values_or_default() + h = app.config.get_per('accounts', self.name, 'hostname') + if h: + app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii(h), + self._on_resolve_txt, type_='txt') + def _compute_resource(self): resource = app.config.get_per('accounts', self.name, 'resource') # All valid resource substitution strings should be added to this hash. @@ -1104,6 +1109,28 @@ class Connection(CommonConnection, ConnectionHandlers): i['ssl_port'] = ssl_p self._connect_to_next_host() + def _on_resolve_txt(self, host, result_array): + for res in result_array: + if res.startswith('_xmpp-client-xbosh='): + url = res[19:] + found = False + proxies = app.config.get_per('proxies') + for p in proxies: + if app.config.get_per('proxies', p, 'type') == 'bosh' \ + and app.config.get_per('proxies', p, 'bosh_uri') == url: + found = True + break + if not found: + h = app.config.get_per('accounts', self.name, 'hostname') + p = 'bosh_' + h + i = 0 + while p in proxies: + i += 1 + p = 'bosh_' + h + str(i) + app.config.add_per('proxies', p) + app.config.set_per('proxies', p, 'type', 'bosh') + app.config.set_per('proxies', p, 'bosh_uri', url) + def _connect_to_next_host(self, retry=False): log.debug('Connection to next host') @@ -2212,6 +2239,8 @@ class Connection(CommonConnection, ConnectionHandlers): self.on_connect_success = self._on_new_account self.on_connect_failure = self._on_new_account self.connect(config) + app.resolver.resolve('_xmppconnect.' + helpers.idn_to_ascii( + self._hostname), self._on_resolve_txt, type_='txt') def _on_new_account(self, con=None, con_type=None): if not con_type: diff --git a/gajim/common/resolver.py b/gajim/common/resolver.py index 6723652d5..173cf97e5 100644 --- a/gajim/common/resolver.py +++ b/gajim/common/resolver.py @@ -94,9 +94,8 @@ class GioResolver(CommonResolver): def start_resolve(self, host, type_): if type_ == 'txt': - # TXT record resolution isn't used anywhere at the moment so - # implementing it here isn't urgent - raise NotImplementedError("Gio resolver does not currently implement TXT records") + callback = functools.partial(self._on_ready_txt, host) + type_ = Gio.ResolverRecordType.TXT else: callback = functools.partial(self._on_ready_srv, host) type_ = Gio.ResolverRecordType.SRV @@ -125,6 +124,19 @@ class GioResolver(CommonResolver): ] super()._on_ready(host, 'srv', result_list) + def _on_ready_txt(self, host, source_object, result): + try: + variant_results = source_object.lookup_records_finish(result) + except GLib.Error as e: + if e.domain == 'g-resolver-error-quark': + result_list = [] + log.warning("Could not resolve host: %s", e.message) + else: + raise + else: + result_list = [res[0][0] for res in variant_results] + super()._on_ready(host, 'txt', result_list) + # below lines is on how to use API and assist in testing if __name__ == '__main__':