Commit 95711855 authored by Philipp Hörist's avatar Philipp Hörist
Browse files

Websocket: Resolve uri via https

parent 4a1195ce
......@@ -18,10 +18,13 @@
import logging
from collections import namedtuple
from gi.repository import Soup
import nbxmpp
from nbxmpp.util import Observable
from nbxmpp.resolver import GioResolver
from nbxmpp.const import ConnectionType
from nbxmpp.const import ConnectionProtocol
from nbxmpp.util import parse_websocket_uri
log = logging.getLogger('nbxmpp.addresses')
......@@ -130,8 +133,58 @@ class ServerAddresses(Observable):
self._on_request_resolved()
return
GioResolver().resolve_alternatives(self._domain,
self._on_alternatives_result)
self._resolve_alternatives()
def _resolve_alternatives(self) -> None:
session = Soup.Session()
session.props.user_agent = f'nbxmpp/{nbxmpp.__version__}'
message = Soup.Message.new(
'GET', f'https://{self._domain}/.well-known/host-meta')
session.queue_message(message, self._on_alternatives_result)
def _on_alternatives_result(self,
_session: Soup.Session,
message: Soup.Message) -> None:
status = message.props.status_code
if status != Soup.Status.OK:
error = message.props.reason_phrase
log.info('Failed to retrieve host-meta file: %s %s', status, error)
self._on_request_resolved()
return
response_body = message.props.response_body
if response_body is None or not response_body.data:
log.info('No response body data found')
self._on_request_resolved()
return
try:
uri = parse_websocket_uri(response_body.data)
except ValueError as error:
log.info('Error parsing websocket uri: %s', error)
self._on_request_resolved()
return
if uri.startswith('wss'):
type_ = ConnectionType.DIRECT_TLS
elif uri.startswith('ws'):
type_ = ConnectionType.PLAIN
else:
log.warning('Invalid websocket uri: %s', uri)
self._on_request_resolved()
return
addr = ServerAddress(domain=self._domain,
service=None,
host=None,
uri=uri,
protocol=ConnectionProtocol.WEBSOCKET,
type=type_,
proxy=None)
self._addresses.append(addr)
self._on_request_resolved()
def cancel_resolve(self):
self.remove_subscriptions()
......@@ -161,31 +214,6 @@ class ServerAddresses(Observable):
def set_proxy(self, proxy):
self._proxy = proxy
def _on_alternatives_result(self, uri):
if uri is None:
self._on_request_resolved()
return
if uri.startswith('wss'):
type_ = ConnectionType.DIRECT_TLS
elif uri.startswith('ws'):
type_ = ConnectionType.PLAIN
else:
log.warning('Invalid websocket uri: %s', uri)
self._on_request_resolved()
return
addr = ServerAddress(domain=self._domain,
service=None,
host=None,
uri=uri,
protocol=ConnectionProtocol.WEBSOCKET,
type=type_,
proxy=None)
self._addresses.append(addr)
self._on_request_resolved()
def _on_request_resolved(self):
self._is_resolved = True
self.notify('resolved')
......
......@@ -172,6 +172,7 @@ class _Namespaces:
XHTML: str = 'http://www.w3.org/1999/xhtml'
XMPP_STREAMS: str = 'urn:ietf:params:xml:ns:xmpp-streams'
X_OOB: str = 'jabber:x:oob'
XRD: str = 'http://docs.oasis-open.org/ns/xri/xrd-1.0'
Namespace: _Namespaces = _Namespaces()
......@@ -30,6 +30,7 @@ import re
import logging
from logging import LoggerAdapter
from collections import defaultdict
import xml.etree.ElementTree as ET
from functools import lru_cache
......@@ -434,3 +435,24 @@ class LogAdapter(LoggerAdapter):
def process(self, msg, kwargs):
return '(%s) %s' % (self.extra['context'], msg), kwargs
def parse_websocket_uri(data: str) -> str:
'''
Example:
<?xml version='1.0' encoding='utf-8'?>
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
<Link rel='urn:xmpp:alt-connections:xbosh'
href='https://bosh.domain.org/'/>
<Link rel='urn:xmpp:alt-connections:websocket'
href='wss://ws.domain.org/'/>
</XRD>
'''
host_meta_xml = ET.fromstring(data)
for link in host_meta_xml.findall(f'{{{Namespace.XRD}}}Link'):
if link.attrib.get('rel') == 'urn:xmpp:alt-connections:websocket':
href = link.attrib.get('href')
if href is None:
raise ValueError('No href attr found')
return href
raise ValueError('no websocket uri found')
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment