Add MSC4040 `matrix-fed` service lookups (#16137)
parent
c9cec2daed
commit
b1d71c687a
|
@ -0,0 +1 @@
|
||||||
|
Support resolving homeservers using `matrix-fed` DNS SRV records from [MSC4040](https://github.com/matrix-org/matrix-spec-proposals/pull/4040).
|
|
@ -329,6 +329,17 @@ class MatrixConnectionAdapter(HTTPAdapter):
|
||||||
raise ValueError("Invalid host:port '%s'" % (server_name,))
|
raise ValueError("Invalid host:port '%s'" % (server_name,))
|
||||||
return out[0], port, out[0]
|
return out[0], port, out[0]
|
||||||
|
|
||||||
|
# Look up SRV for Matrix 1.8 `matrix-fed` service first
|
||||||
|
try:
|
||||||
|
srv = srvlookup.lookup("matrix-fed", "tcp", server_name)[0]
|
||||||
|
print(
|
||||||
|
f"SRV lookup on _matrix-fed._tcp.{server_name} gave {srv}",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return srv.host, srv.port, server_name
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# Fall back to deprecated `matrix` service
|
||||||
try:
|
try:
|
||||||
srv = srvlookup.lookup("matrix", "tcp", server_name)[0]
|
srv = srvlookup.lookup("matrix", "tcp", server_name)[0]
|
||||||
print(
|
print(
|
||||||
|
@ -337,6 +348,7 @@ class MatrixConnectionAdapter(HTTPAdapter):
|
||||||
)
|
)
|
||||||
return srv.host, srv.port, server_name
|
return srv.host, srv.port, server_name
|
||||||
except Exception:
|
except Exception:
|
||||||
|
# Fall even further back to just port 8448
|
||||||
return server_name, 8448, server_name
|
return server_name, 8448, server_name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -399,15 +399,34 @@ class MatrixHostnameEndpoint:
|
||||||
if port or _is_ip_literal(host):
|
if port or _is_ip_literal(host):
|
||||||
return [Server(host, port or 8448)]
|
return [Server(host, port or 8448)]
|
||||||
|
|
||||||
|
# Check _matrix-fed._tcp SRV record.
|
||||||
logger.debug("Looking up SRV record for %s", host.decode(errors="replace"))
|
logger.debug("Looking up SRV record for %s", host.decode(errors="replace"))
|
||||||
|
server_list = await self._srv_resolver.resolve_service(
|
||||||
|
b"_matrix-fed._tcp." + host
|
||||||
|
)
|
||||||
|
|
||||||
|
if server_list:
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug(
|
||||||
|
"Got %s from SRV lookup for %s",
|
||||||
|
", ".join(map(str, server_list)),
|
||||||
|
host.decode(errors="replace"),
|
||||||
|
)
|
||||||
|
return server_list
|
||||||
|
|
||||||
|
# No _matrix-fed._tcp SRV record, fallback to legacy _matrix._tcp SRV record.
|
||||||
|
logger.debug(
|
||||||
|
"Looking up deprecated SRV record for %s", host.decode(errors="replace")
|
||||||
|
)
|
||||||
server_list = await self._srv_resolver.resolve_service(b"_matrix._tcp." + host)
|
server_list = await self._srv_resolver.resolve_service(b"_matrix._tcp." + host)
|
||||||
|
|
||||||
if server_list:
|
if server_list:
|
||||||
logger.debug(
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
"Got %s from SRV lookup for %s",
|
logger.debug(
|
||||||
", ".join(map(str, server_list)),
|
"Got %s from deprecated SRV lookup for %s",
|
||||||
host.decode(errors="replace"),
|
", ".join(map(str, server_list)),
|
||||||
)
|
host.decode(errors="replace"),
|
||||||
|
)
|
||||||
return server_list
|
return server_list
|
||||||
|
|
||||||
# No SRV records, so we fallback to host and 8448
|
# No SRV records, so we fallback to host and 8448
|
||||||
|
|
|
@ -15,7 +15,7 @@ import base64
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Generator, List, Optional, cast
|
from typing import Generator, List, Optional, cast
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, call, patch
|
||||||
|
|
||||||
import treq
|
import treq
|
||||||
from netaddr import IPSet
|
from netaddr import IPSet
|
||||||
|
@ -651,9 +651,9 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
# .well-known request fails.
|
# .well-known request fails.
|
||||||
self.reactor.pump((0.4,))
|
self.reactor.pump((0.4,))
|
||||||
|
|
||||||
# now there should be a SRV lookup
|
# now there should be two SRV lookups
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.testserv1"
|
[call(b"_matrix-fed._tcp.testserv1"), call(b"_matrix._tcp.testserv1")]
|
||||||
)
|
)
|
||||||
|
|
||||||
# we should fall back to a direct connection
|
# we should fall back to a direct connection
|
||||||
|
@ -737,9 +737,9 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
# .well-known request fails.
|
# .well-known request fails.
|
||||||
self.reactor.pump((0.4,))
|
self.reactor.pump((0.4,))
|
||||||
|
|
||||||
# now there should be a SRV lookup
|
# now there should be two SRV lookups
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.testserv"
|
[call(b"_matrix-fed._tcp.testserv"), call(b"_matrix._tcp.testserv")]
|
||||||
)
|
)
|
||||||
|
|
||||||
# we should fall back to a direct connection
|
# we should fall back to a direct connection
|
||||||
|
@ -788,9 +788,12 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
content=b'{ "m.server": "target-server" }',
|
content=b'{ "m.server": "target-server" }',
|
||||||
)
|
)
|
||||||
|
|
||||||
# there should be a SRV lookup
|
# there should be two SRV lookups
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.target-server"
|
[
|
||||||
|
call(b"_matrix-fed._tcp.target-server"),
|
||||||
|
call(b"_matrix._tcp.target-server"),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# now we should get a connection to the target server
|
# now we should get a connection to the target server
|
||||||
|
@ -878,9 +881,12 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
|
|
||||||
self.reactor.pump((0.1,))
|
self.reactor.pump((0.1,))
|
||||||
|
|
||||||
# there should be a SRV lookup
|
# there should be two SRV lookups
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.target-server"
|
[
|
||||||
|
call(b"_matrix-fed._tcp.target-server"),
|
||||||
|
call(b"_matrix._tcp.target-server"),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# now we should get a connection to the target server
|
# now we should get a connection to the target server
|
||||||
|
@ -942,9 +948,9 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
client_factory, expected_sni=b"testserv", content=b"NOT JSON"
|
client_factory, expected_sni=b"testserv", content=b"NOT JSON"
|
||||||
)
|
)
|
||||||
|
|
||||||
# now there should be a SRV lookup
|
# now there should be two SRV lookups
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.testserv"
|
[call(b"_matrix-fed._tcp.testserv"), call(b"_matrix._tcp.testserv")]
|
||||||
)
|
)
|
||||||
|
|
||||||
# we should fall back to a direct connection
|
# we should fall back to a direct connection
|
||||||
|
@ -1016,14 +1022,14 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
# there should be no requests
|
# there should be no requests
|
||||||
self.assertEqual(len(http_proto.requests), 0)
|
self.assertEqual(len(http_proto.requests), 0)
|
||||||
|
|
||||||
# and there should be a SRV lookup instead
|
# and there should be two SRV lookups instead
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.testserv"
|
[call(b"_matrix-fed._tcp.testserv"), call(b"_matrix._tcp.testserv")]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_hostname_srv(self) -> None:
|
def test_get_hostname_srv(self) -> None:
|
||||||
"""
|
"""
|
||||||
Test the behaviour when there is a single SRV record
|
Test the behaviour when there is a single SRV record for _matrix-fed.
|
||||||
"""
|
"""
|
||||||
self.agent = self._make_agent()
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
@ -1039,7 +1045,51 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
|
|
||||||
# the request for a .well-known will have failed with a DNS lookup error.
|
# the request for a .well-known will have failed with a DNS lookup error.
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_called_once_with(
|
||||||
b"_matrix._tcp.testserv"
|
b"_matrix-fed._tcp.testserv"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure treq is trying to connect
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients[0]
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 8443)
|
||||||
|
|
||||||
|
# make a test server, and wire up the client
|
||||||
|
http_server = self._make_connection(client_factory, expected_sni=b"testserv")
|
||||||
|
|
||||||
|
self.assertEqual(len(http_server.requests), 1)
|
||||||
|
request = http_server.requests[0]
|
||||||
|
self.assertEqual(request.method, b"GET")
|
||||||
|
self.assertEqual(request.path, b"/foo/bar")
|
||||||
|
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"testserv"])
|
||||||
|
|
||||||
|
# finish the request
|
||||||
|
request.finish()
|
||||||
|
self.reactor.pump((0.1,))
|
||||||
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
|
def test_get_hostname_srv_legacy(self) -> None:
|
||||||
|
"""
|
||||||
|
Test the behaviour when there is a single SRV record for _matrix.
|
||||||
|
"""
|
||||||
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
# Return no entries for the _matrix-fed lookup, and a response for _matrix.
|
||||||
|
self.mock_resolver.resolve_service.side_effect = [
|
||||||
|
[],
|
||||||
|
[Server(host=b"srvtarget", port=8443)],
|
||||||
|
]
|
||||||
|
self.reactor.lookups["srvtarget"] = "1.2.3.4"
|
||||||
|
|
||||||
|
test_d = self._make_get_request(b"matrix-federation://testserv/foo/bar")
|
||||||
|
|
||||||
|
# Nothing happened yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
# the request for a .well-known will have failed with a DNS lookup error.
|
||||||
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
|
[call(b"_matrix-fed._tcp.testserv"), call(b"_matrix._tcp.testserv")]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Make sure treq is trying to connect
|
# Make sure treq is trying to connect
|
||||||
|
@ -1065,7 +1115,7 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_get_well_known_srv(self) -> None:
|
def test_get_well_known_srv(self) -> None:
|
||||||
"""Test the behaviour when the .well-known redirects to a place where there
|
"""Test the behaviour when the .well-known redirects to a place where there
|
||||||
is a SRV.
|
is a _matrix-fed SRV record.
|
||||||
"""
|
"""
|
||||||
self.agent = self._make_agent()
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
@ -1096,7 +1146,72 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
|
|
||||||
# there should be a SRV lookup
|
# there should be a SRV lookup
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_called_once_with(
|
||||||
b"_matrix._tcp.target-server"
|
b"_matrix-fed._tcp.target-server"
|
||||||
|
)
|
||||||
|
|
||||||
|
# now we should get a connection to the target of the SRV record
|
||||||
|
self.assertEqual(len(clients), 2)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients[1]
|
||||||
|
self.assertEqual(host, "5.6.7.8")
|
||||||
|
self.assertEqual(port, 8443)
|
||||||
|
|
||||||
|
# make a test server, and wire up the client
|
||||||
|
http_server = self._make_connection(
|
||||||
|
client_factory, expected_sni=b"target-server"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(http_server.requests), 1)
|
||||||
|
request = http_server.requests[0]
|
||||||
|
self.assertEqual(request.method, b"GET")
|
||||||
|
self.assertEqual(request.path, b"/foo/bar")
|
||||||
|
self.assertEqual(
|
||||||
|
request.requestHeaders.getRawHeaders(b"host"), [b"target-server"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# finish the request
|
||||||
|
request.finish()
|
||||||
|
self.reactor.pump((0.1,))
|
||||||
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
|
def test_get_well_known_srv_legacy(self) -> None:
|
||||||
|
"""Test the behaviour when the .well-known redirects to a place where there
|
||||||
|
is a _matrix SRV record.
|
||||||
|
"""
|
||||||
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
self.reactor.lookups["testserv"] = "1.2.3.4"
|
||||||
|
self.reactor.lookups["srvtarget"] = "5.6.7.8"
|
||||||
|
|
||||||
|
test_d = self._make_get_request(b"matrix-federation://testserv/foo/bar")
|
||||||
|
|
||||||
|
# Nothing happened yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
# there should be an attempt to connect on port 443 for the .well-known
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients[0]
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 443)
|
||||||
|
|
||||||
|
# Return no entries for the _matrix-fed lookup, and a response for _matrix.
|
||||||
|
self.mock_resolver.resolve_service.side_effect = [
|
||||||
|
[],
|
||||||
|
[Server(host=b"srvtarget", port=8443)],
|
||||||
|
]
|
||||||
|
|
||||||
|
self._handle_well_known_connection(
|
||||||
|
client_factory,
|
||||||
|
expected_sni=b"testserv",
|
||||||
|
content=b'{ "m.server": "target-server" }',
|
||||||
|
)
|
||||||
|
|
||||||
|
# there should be two SRV lookups
|
||||||
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
|
[
|
||||||
|
call(b"_matrix-fed._tcp.target-server"),
|
||||||
|
call(b"_matrix._tcp.target-server"),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# now we should get a connection to the target of the SRV record
|
# now we should get a connection to the target of the SRV record
|
||||||
|
@ -1158,8 +1273,11 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.reactor.pump((0.4,))
|
self.reactor.pump((0.4,))
|
||||||
|
|
||||||
# now there should have been a SRV lookup
|
# now there should have been a SRV lookup
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
b"_matrix._tcp.xn--bcher-kva.com"
|
[
|
||||||
|
call(b"_matrix-fed._tcp.xn--bcher-kva.com"),
|
||||||
|
call(b"_matrix._tcp.xn--bcher-kva.com"),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# We should fall back to port 8448
|
# We should fall back to port 8448
|
||||||
|
@ -1188,7 +1306,7 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.successResultOf(test_d)
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
def test_idna_srv_target(self) -> None:
|
def test_idna_srv_target(self) -> None:
|
||||||
"""test the behaviour when the target of a SRV record has idna chars"""
|
"""test the behaviour when the target of a _matrix-fed SRV record has idna chars"""
|
||||||
self.agent = self._make_agent()
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
self.mock_resolver.resolve_service.return_value = [
|
self.mock_resolver.resolve_service.return_value = [
|
||||||
|
@ -1204,7 +1322,57 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.assertNoResult(test_d)
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_called_once_with(
|
||||||
b"_matrix._tcp.xn--bcher-kva.com"
|
b"_matrix-fed._tcp.xn--bcher-kva.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure treq is trying to connect
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients[0]
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 8443)
|
||||||
|
|
||||||
|
# make a test server, and wire up the client
|
||||||
|
http_server = self._make_connection(
|
||||||
|
client_factory, expected_sni=b"xn--bcher-kva.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(http_server.requests), 1)
|
||||||
|
request = http_server.requests[0]
|
||||||
|
self.assertEqual(request.method, b"GET")
|
||||||
|
self.assertEqual(request.path, b"/foo/bar")
|
||||||
|
self.assertEqual(
|
||||||
|
request.requestHeaders.getRawHeaders(b"host"), [b"xn--bcher-kva.com"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# finish the request
|
||||||
|
request.finish()
|
||||||
|
self.reactor.pump((0.1,))
|
||||||
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
|
def test_idna_srv_target_legacy(self) -> None:
|
||||||
|
"""test the behaviour when the target of a _matrix SRV record has idna chars"""
|
||||||
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
# Return no entries for the _matrix-fed lookup, and a response for _matrix.
|
||||||
|
self.mock_resolver.resolve_service.side_effect = [
|
||||||
|
[],
|
||||||
|
[Server(host=b"xn--trget-3qa.com", port=8443)],
|
||||||
|
] # târget.com
|
||||||
|
self.reactor.lookups["xn--trget-3qa.com"] = "1.2.3.4"
|
||||||
|
|
||||||
|
test_d = self._make_get_request(
|
||||||
|
b"matrix-federation://xn--bcher-kva.com/foo/bar"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Nothing happened yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
|
[
|
||||||
|
call(b"_matrix-fed._tcp.xn--bcher-kva.com"),
|
||||||
|
call(b"_matrix._tcp.xn--bcher-kva.com"),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Make sure treq is trying to connect
|
# Make sure treq is trying to connect
|
||||||
|
@ -1394,7 +1562,7 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.assertIsNone(r.delegated_server)
|
self.assertIsNone(r.delegated_server)
|
||||||
|
|
||||||
def test_srv_fallbacks(self) -> None:
|
def test_srv_fallbacks(self) -> None:
|
||||||
"""Test that other SRV results are tried if the first one fails."""
|
"""Test that other SRV results are tried if the first one fails for _matrix-fed SRV."""
|
||||||
self.agent = self._make_agent()
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
self.mock_resolver.resolve_service.return_value = [
|
self.mock_resolver.resolve_service.return_value = [
|
||||||
|
@ -1409,7 +1577,7 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.assertNoResult(test_d)
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
self.mock_resolver.resolve_service.assert_called_once_with(
|
self.mock_resolver.resolve_service.assert_called_once_with(
|
||||||
b"_matrix._tcp.testserv"
|
b"_matrix-fed._tcp.testserv"
|
||||||
)
|
)
|
||||||
|
|
||||||
# We should see an attempt to connect to the first server
|
# We should see an attempt to connect to the first server
|
||||||
|
@ -1449,6 +1617,103 @@ class MatrixFederationAgentTests(unittest.TestCase):
|
||||||
self.reactor.pump((0.1,))
|
self.reactor.pump((0.1,))
|
||||||
self.successResultOf(test_d)
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
|
def test_srv_fallbacks_legacy(self) -> None:
|
||||||
|
"""Test that other SRV results are tried if the first one fails for _matrix SRV."""
|
||||||
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
# Return no entries for the _matrix-fed lookup, and a response for _matrix.
|
||||||
|
self.mock_resolver.resolve_service.side_effect = [
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
Server(host=b"target.com", port=8443),
|
||||||
|
Server(host=b"target.com", port=8444),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
self.reactor.lookups["target.com"] = "1.2.3.4"
|
||||||
|
|
||||||
|
test_d = self._make_get_request(b"matrix-federation://testserv/foo/bar")
|
||||||
|
|
||||||
|
# Nothing happened yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
self.mock_resolver.resolve_service.assert_has_calls(
|
||||||
|
[call(b"_matrix-fed._tcp.testserv"), call(b"_matrix._tcp.testserv")]
|
||||||
|
)
|
||||||
|
|
||||||
|
# We should see an attempt to connect to the first server
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients.pop(0)
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 8443)
|
||||||
|
|
||||||
|
# Fonx the connection
|
||||||
|
client_factory.clientConnectionFailed(None, Exception("nope"))
|
||||||
|
|
||||||
|
# There's a 300ms delay in HostnameEndpoint
|
||||||
|
self.reactor.pump((0.4,))
|
||||||
|
|
||||||
|
# Hasn't failed yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
# We shouldnow see an attempt to connect to the second server
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients.pop(0)
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 8444)
|
||||||
|
|
||||||
|
# make a test server, and wire up the client
|
||||||
|
http_server = self._make_connection(client_factory, expected_sni=b"testserv")
|
||||||
|
|
||||||
|
self.assertEqual(len(http_server.requests), 1)
|
||||||
|
request = http_server.requests[0]
|
||||||
|
self.assertEqual(request.method, b"GET")
|
||||||
|
self.assertEqual(request.path, b"/foo/bar")
|
||||||
|
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"testserv"])
|
||||||
|
|
||||||
|
# finish the request
|
||||||
|
request.finish()
|
||||||
|
self.reactor.pump((0.1,))
|
||||||
|
self.successResultOf(test_d)
|
||||||
|
|
||||||
|
def test_srv_no_fallback_to_legacy(self) -> None:
|
||||||
|
"""Test that _matrix SRV results are not tried if the _matrix-fed one fails."""
|
||||||
|
self.agent = self._make_agent()
|
||||||
|
|
||||||
|
# Return a failing entry for _matrix-fed.
|
||||||
|
self.mock_resolver.resolve_service.side_effect = [
|
||||||
|
[Server(host=b"target.com", port=8443)],
|
||||||
|
[],
|
||||||
|
]
|
||||||
|
self.reactor.lookups["target.com"] = "1.2.3.4"
|
||||||
|
|
||||||
|
test_d = self._make_get_request(b"matrix-federation://testserv/foo/bar")
|
||||||
|
|
||||||
|
# Nothing happened yet
|
||||||
|
self.assertNoResult(test_d)
|
||||||
|
|
||||||
|
# Only the _matrix-fed is checked, _matrix is ignored.
|
||||||
|
self.mock_resolver.resolve_service.assert_called_once_with(
|
||||||
|
b"_matrix-fed._tcp.testserv"
|
||||||
|
)
|
||||||
|
|
||||||
|
# We should see an attempt to connect to the first server
|
||||||
|
clients = self.reactor.tcpClients
|
||||||
|
self.assertEqual(len(clients), 1)
|
||||||
|
(host, port, client_factory, _timeout, _bindAddress) = clients.pop(0)
|
||||||
|
self.assertEqual(host, "1.2.3.4")
|
||||||
|
self.assertEqual(port, 8443)
|
||||||
|
|
||||||
|
# Fonx the connection
|
||||||
|
client_factory.clientConnectionFailed(None, Exception("nope"))
|
||||||
|
|
||||||
|
# There's a 300ms delay in HostnameEndpoint
|
||||||
|
self.reactor.pump((0.4,))
|
||||||
|
|
||||||
|
# Failed to resolve a server.
|
||||||
|
self.assertFailure(test_d, Exception)
|
||||||
|
|
||||||
|
|
||||||
class TestCachePeriodFromHeaders(unittest.TestCase):
|
class TestCachePeriodFromHeaders(unittest.TestCase):
|
||||||
def test_cache_control(self) -> None:
|
def test_cache_control(self) -> None:
|
||||||
|
|
Loading…
Reference in New Issue