Merge branch 'develop' of github.com:matrix-org/synapse into anoa/dm_room_upgrade

This commit is contained in:
Andrew Morgan 2019-01-28 14:08:24 +00:00
commit 4026d555fa
32 changed files with 557 additions and 124 deletions

View file

@ -18,7 +18,7 @@ instructions that may be required are listed later in this document.
.. code:: bash .. code:: bash
pip install --upgrade --process-dependency-links matrix-synapse pip install --upgrade matrix-synapse
# restart synapse # restart synapse
synctl restart synctl restart

View file

@ -1 +1 @@
Synapse will now take advantage of native UPSERT functionality in PostgreSQL 9.5+ and SQLite 3.24+. Synapse will now take advantage of native UPSERT functionality in PostgreSQL 9.5+.

1
changelog.d/4466.misc Normal file
View file

@ -0,0 +1 @@
Synapse will now take advantage of native UPSERT functionality in PostgreSQL 9.5+ and SQLite 3.24+.

1
changelog.d/4468.misc Normal file
View file

@ -0,0 +1 @@
Move SRV logic into the Agent layer

1
changelog.d/4470.misc Normal file
View file

@ -0,0 +1 @@
Add infrastructure to support different event formats

1
changelog.d/4471.misc Normal file
View file

@ -0,0 +1 @@
Synapse will now take advantage of native UPSERT functionality in PostgreSQL 9.5+.

1
changelog.d/4476.misc Normal file
View file

@ -0,0 +1 @@
Fix quoting for allowed_local_3pids example config

1
changelog.d/4485.misc Normal file
View file

@ -0,0 +1 @@
Remove deprecated --process-dependency-links option from UPGRADE.rst

1
changelog.d/4487.misc Normal file
View file

@ -0,0 +1 @@
Fix idna and ipv6 literal handling in MatrixFederationAgent

1
changelog.d/4488.feature Normal file
View file

@ -0,0 +1 @@
Implement MSC1708 (.well-known routing for server-server federation)

View file

@ -84,11 +84,11 @@ class RegistrationConfig(Config):
# #
# allowed_local_3pids: # allowed_local_3pids:
# - medium: email # - medium: email
# pattern: ".*@matrix\\.org" # pattern: '.*@matrix\\.org'
# - medium: email # - medium: email
# pattern: ".*@vector\\.im" # pattern: '.*@vector\\.im'
# - medium: msisdn # - medium: msisdn
# pattern: "\\+44" # pattern: '\\+44'
# If set, allows registration by anyone who also has the shared # If set, allows registration by anyone who also has the shared
# secret, even if registration is otherwise disabled. # secret, even if registration is otherwise disabled.

View file

@ -18,7 +18,11 @@ from distutils.util import strtobool
import six import six
from synapse.api.constants import KNOWN_ROOM_VERSIONS, EventFormatVersions from synapse.api.constants import (
KNOWN_EVENT_FORMAT_VERSIONS,
KNOWN_ROOM_VERSIONS,
EventFormatVersions,
)
from synapse.util.caches import intern_dict from synapse.util.caches import intern_dict
from synapse.util.frozenutils import freeze from synapse.util.frozenutils import freeze
@ -256,3 +260,21 @@ def room_version_to_event_format(room_version):
raise RuntimeError("Unrecognized room version %s" % (room_version,)) raise RuntimeError("Unrecognized room version %s" % (room_version,))
return EventFormatVersions.V1 return EventFormatVersions.V1
def event_type_from_format_version(format_version):
"""Returns the python type to use to construct an Event object for the
given event format version.
Args:
format_version (int): The event format version
Returns:
type: A type that can be initialized as per the initializer of
`FrozenEvent`
"""
if format_version not in KNOWN_EVENT_FORMAT_VERSIONS:
raise Exception(
"No event format %r" % (format_version,)
)
return FrozenEvent

View file

@ -15,12 +15,39 @@
import copy import copy
from synapse.api.constants import RoomVersions
from synapse.types import EventID from synapse.types import EventID
from synapse.util.stringutils import random_string from synapse.util.stringutils import random_string
from . import EventBase, FrozenEvent, _event_dict_property from . import EventBase, FrozenEvent, _event_dict_property
def get_event_builder(room_version, key_values={}, internal_metadata_dict={}):
"""Generate an event builder appropriate for the given room version
Args:
room_version (str): Version of the room that we're creating an
event builder for
key_values (dict): Fields used as the basis of the new event
internal_metadata_dict (dict): Used to create the `_EventInternalMetadata`
object.
Returns:
EventBuilder
"""
if room_version in {
RoomVersions.V1,
RoomVersions.V2,
RoomVersions.VDH_TEST,
RoomVersions.STATE_V2_TEST,
}:
return EventBuilder(key_values, internal_metadata_dict)
else:
raise Exception(
"No event format defined for version %r" % (room_version,)
)
class EventBuilder(EventBase): class EventBuilder(EventBase):
def __init__(self, key_values={}, internal_metadata_dict={}): def __init__(self, key_values={}, internal_metadata_dict={}):
signatures = copy.deepcopy(key_values.pop("signatures", {})) signatures = copy.deepcopy(key_values.pop("signatures", {}))
@ -58,7 +85,29 @@ class EventBuilderFactory(object):
return e_id.to_string() return e_id.to_string()
def new(self, key_values={}): def new(self, room_version, key_values={}):
"""Generate an event builder appropriate for the given room version
Args:
room_version (str): Version of the room that we're creating an
event builder for
key_values (dict): Fields used as the basis of the new event
Returns:
EventBuilder
"""
# There's currently only the one event version defined
if room_version not in {
RoomVersions.V1,
RoomVersions.V2,
RoomVersions.VDH_TEST,
RoomVersions.STATE_V2_TEST,
}:
raise Exception(
"No event format defined for version %r" % (room_version,)
)
key_values["event_id"] = self.create_event_id() key_values["event_id"] = self.create_event_id()
time_now = int(self.clock.time_msec()) time_now = int(self.clock.time_msec())

View file

@ -23,7 +23,7 @@ from twisted.internet.defer import DeferredList
from synapse.api.constants import MAX_DEPTH, EventTypes, Membership from synapse.api.constants import MAX_DEPTH, EventTypes, Membership
from synapse.api.errors import Codes, SynapseError from synapse.api.errors import Codes, SynapseError
from synapse.crypto.event_signing import check_event_content_hash from synapse.crypto.event_signing import check_event_content_hash
from synapse.events import FrozenEvent from synapse.events import event_type_from_format_version
from synapse.events.utils import prune_event from synapse.events.utils import prune_event
from synapse.http.servlet import assert_params_in_dict from synapse.http.servlet import assert_params_in_dict
from synapse.types import get_domain_from_id from synapse.types import get_domain_from_id
@ -302,11 +302,12 @@ def _is_invite_via_3pid(event):
) )
def event_from_pdu_json(pdu_json, outlier=False): def event_from_pdu_json(pdu_json, event_format_version, outlier=False):
"""Construct a FrozenEvent from an event json received over federation """Construct a FrozenEvent from an event json received over federation
Args: Args:
pdu_json (object): pdu as received over federation pdu_json (object): pdu as received over federation
event_format_version (int): The event format version
outlier (bool): True to mark this event as an outlier outlier (bool): True to mark this event as an outlier
Returns: Returns:
@ -330,8 +331,8 @@ def event_from_pdu_json(pdu_json, outlier=False):
elif depth > MAX_DEPTH: elif depth > MAX_DEPTH:
raise SynapseError(400, "Depth too large", Codes.BAD_JSON) raise SynapseError(400, "Depth too large", Codes.BAD_JSON)
event = FrozenEvent( event = event_type_from_format_version(event_format_version)(
pdu_json pdu_json,
) )
event.internal_metadata.outlier = outlier event.internal_metadata.outlier = outlier

View file

@ -170,13 +170,13 @@ class FederationClient(FederationBase):
@defer.inlineCallbacks @defer.inlineCallbacks
@log_function @log_function
def backfill(self, dest, context, limit, extremities): def backfill(self, dest, room_id, limit, extremities):
"""Requests some more historic PDUs for the given context from the """Requests some more historic PDUs for the given context from the
given destination server. given destination server.
Args: Args:
dest (str): The remote home server to ask. dest (str): The remote home server to ask.
context (str): The context to backfill. room_id (str): The room_id to backfill.
limit (int): The maximum number of PDUs to return. limit (int): The maximum number of PDUs to return.
extremities (list): List of PDU id and origins of the first pdus extremities (list): List of PDU id and origins of the first pdus
we have seen from the context we have seen from the context
@ -191,12 +191,15 @@ class FederationClient(FederationBase):
return return
transaction_data = yield self.transport_layer.backfill( transaction_data = yield self.transport_layer.backfill(
dest, context, extremities, limit) dest, room_id, extremities, limit)
logger.debug("backfill transaction_data=%s", repr(transaction_data)) logger.debug("backfill transaction_data=%s", repr(transaction_data))
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
pdus = [ pdus = [
event_from_pdu_json(p, outlier=False) event_from_pdu_json(p, format_ver, outlier=False)
for p in transaction_data["pdus"] for p in transaction_data["pdus"]
] ]
@ -240,6 +243,8 @@ class FederationClient(FederationBase):
pdu_attempts = self.pdu_destination_tried.setdefault(event_id, {}) pdu_attempts = self.pdu_destination_tried.setdefault(event_id, {})
format_ver = room_version_to_event_format(room_version)
signed_pdu = None signed_pdu = None
for destination in destinations: for destination in destinations:
now = self._clock.time_msec() now = self._clock.time_msec()
@ -255,7 +260,7 @@ class FederationClient(FederationBase):
logger.debug("transaction_data %r", transaction_data) logger.debug("transaction_data %r", transaction_data)
pdu_list = [ pdu_list = [
event_from_pdu_json(p, outlier=outlier) event_from_pdu_json(p, format_ver, outlier=outlier)
for p in transaction_data["pdus"] for p in transaction_data["pdus"]
] ]
@ -349,12 +354,16 @@ class FederationClient(FederationBase):
destination, room_id, event_id=event_id, destination, room_id, event_id=event_id,
) )
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
pdus = [ pdus = [
event_from_pdu_json(p, outlier=True) for p in result["pdus"] event_from_pdu_json(p, format_ver, outlier=True)
for p in result["pdus"]
] ]
auth_chain = [ auth_chain = [
event_from_pdu_json(p, outlier=True) event_from_pdu_json(p, format_ver, outlier=True)
for p in result.get("auth_chain", []) for p in result.get("auth_chain", [])
] ]
@ -362,8 +371,6 @@ class FederationClient(FederationBase):
ev.event_id for ev in itertools.chain(pdus, auth_chain) ev.event_id for ev in itertools.chain(pdus, auth_chain)
]) ])
room_version = yield self.store.get_room_version(room_id)
signed_pdus = yield self._check_sigs_and_hash_and_fetch( signed_pdus = yield self._check_sigs_and_hash_and_fetch(
destination, destination,
[p for p in pdus if p.event_id not in seen_events], [p for p in pdus if p.event_id not in seen_events],
@ -462,13 +469,14 @@ class FederationClient(FederationBase):
destination, room_id, event_id, destination, room_id, event_id,
) )
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
auth_chain = [ auth_chain = [
event_from_pdu_json(p, outlier=True) event_from_pdu_json(p, format_ver, outlier=True)
for p in res["auth_chain"] for p in res["auth_chain"]
] ]
room_version = yield self.store.get_room_version(room_id)
signed_auth = yield self._check_sigs_and_hash_and_fetch( signed_auth = yield self._check_sigs_and_hash_and_fetch(
destination, auth_chain, destination, auth_chain,
outlier=True, room_version=room_version, outlier=True, room_version=room_version,
@ -605,7 +613,7 @@ class FederationClient(FederationBase):
pdu_dict.pop("origin_server_ts", None) pdu_dict.pop("origin_server_ts", None)
pdu_dict.pop("unsigned", None) pdu_dict.pop("unsigned", None)
builder = self.event_builder_factory.new(pdu_dict) builder = self.event_builder_factory.new(room_version, pdu_dict)
add_hashes_and_signatures( add_hashes_and_signatures(
builder, builder,
self.hs.hostname, self.hs.hostname,
@ -621,7 +629,7 @@ class FederationClient(FederationBase):
"make_" + membership, destinations, send_request, "make_" + membership, destinations, send_request,
) )
def send_join(self, destinations, pdu): def send_join(self, destinations, pdu, event_format_version):
"""Sends a join event to one of a list of homeservers. """Sends a join event to one of a list of homeservers.
Doing so will cause the remote server to add the event to the graph, Doing so will cause the remote server to add the event to the graph,
@ -631,6 +639,7 @@ class FederationClient(FederationBase):
destinations (str): Candidate homeservers which are probably destinations (str): Candidate homeservers which are probably
participating in the room. participating in the room.
pdu (BaseEvent): event to be sent pdu (BaseEvent): event to be sent
event_format_version (int): The event format version
Return: Return:
Deferred: resolves to a dict with members ``origin`` (a string Deferred: resolves to a dict with members ``origin`` (a string
@ -676,12 +685,12 @@ class FederationClient(FederationBase):
logger.debug("Got content: %s", content) logger.debug("Got content: %s", content)
state = [ state = [
event_from_pdu_json(p, outlier=True) event_from_pdu_json(p, event_format_version, outlier=True)
for p in content.get("state", []) for p in content.get("state", [])
] ]
auth_chain = [ auth_chain = [
event_from_pdu_json(p, outlier=True) event_from_pdu_json(p, event_format_version, outlier=True)
for p in content.get("auth_chain", []) for p in content.get("auth_chain", [])
] ]
@ -759,7 +768,10 @@ class FederationClient(FederationBase):
logger.debug("Got response to send_invite: %s", pdu_dict) logger.debug("Got response to send_invite: %s", pdu_dict)
pdu = event_from_pdu_json(pdu_dict) room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
pdu = event_from_pdu_json(pdu_dict, format_ver)
# Check signatures are correct. # Check signatures are correct.
pdu = yield self._check_sigs_and_hash(pdu) pdu = yield self._check_sigs_and_hash(pdu)
@ -837,13 +849,14 @@ class FederationClient(FederationBase):
content=send_content, content=send_content,
) )
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
auth_chain = [ auth_chain = [
event_from_pdu_json(e) event_from_pdu_json(e, format_ver)
for e in content["auth_chain"] for e in content["auth_chain"]
] ]
room_version = yield self.store.get_room_version(room_id)
signed_auth = yield self._check_sigs_and_hash_and_fetch( signed_auth = yield self._check_sigs_and_hash_and_fetch(
destination, auth_chain, outlier=True, room_version=room_version, destination, auth_chain, outlier=True, room_version=room_version,
) )
@ -887,13 +900,14 @@ class FederationClient(FederationBase):
timeout=timeout, timeout=timeout,
) )
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
events = [ events = [
event_from_pdu_json(e) event_from_pdu_json(e, format_ver)
for e in content.get("events", []) for e in content.get("events", [])
] ]
room_version = yield self.store.get_room_version(room_id)
signed_events = yield self._check_sigs_and_hash_and_fetch( signed_events = yield self._check_sigs_and_hash_and_fetch(
destination, events, outlier=False, room_version=room_version, destination, events, outlier=False, room_version=room_version,
) )

View file

@ -34,6 +34,7 @@ from synapse.api.errors import (
SynapseError, SynapseError,
) )
from synapse.crypto.event_signing import compute_event_signature from synapse.crypto.event_signing import compute_event_signature
from synapse.events import room_version_to_event_format
from synapse.federation.federation_base import FederationBase, event_from_pdu_json from synapse.federation.federation_base import FederationBase, event_from_pdu_json
from synapse.federation.persistence import TransactionActions from synapse.federation.persistence import TransactionActions
from synapse.federation.units import Edu, Transaction from synapse.federation.units import Edu, Transaction
@ -178,14 +179,13 @@ class FederationServer(FederationBase):
continue continue
try: try:
# In future we will actually use the room version to parse the room_version = yield self.store.get_room_version(room_id)
# PDU into an event. format_ver = room_version_to_event_format(room_version)
yield self.store.get_room_version(room_id)
except NotFoundError: except NotFoundError:
logger.info("Ignoring PDU for unknown room_id: %s", room_id) logger.info("Ignoring PDU for unknown room_id: %s", room_id)
continue continue
event = event_from_pdu_json(p) event = event_from_pdu_json(p, format_ver)
pdus_by_room.setdefault(room_id, []).append(event) pdus_by_room.setdefault(room_id, []).append(event)
pdu_results = {} pdu_results = {}
@ -370,7 +370,9 @@ class FederationServer(FederationBase):
@defer.inlineCallbacks @defer.inlineCallbacks
def on_invite_request(self, origin, content, room_version): def on_invite_request(self, origin, content, room_version):
pdu = event_from_pdu_json(content) format_ver = room_version_to_event_format(room_version)
pdu = event_from_pdu_json(content, format_ver)
origin_host, _ = parse_server_name(origin) origin_host, _ = parse_server_name(origin)
yield self.check_server_matches_acl(origin_host, pdu.room_id) yield self.check_server_matches_acl(origin_host, pdu.room_id)
ret_pdu = yield self.handler.on_invite_request(origin, pdu) ret_pdu = yield self.handler.on_invite_request(origin, pdu)
@ -378,9 +380,12 @@ class FederationServer(FederationBase):
defer.returnValue({"event": ret_pdu.get_pdu_json(time_now)}) defer.returnValue({"event": ret_pdu.get_pdu_json(time_now)})
@defer.inlineCallbacks @defer.inlineCallbacks
def on_send_join_request(self, origin, content): def on_send_join_request(self, origin, content, room_id):
logger.debug("on_send_join_request: content: %s", content) logger.debug("on_send_join_request: content: %s", content)
pdu = event_from_pdu_json(content)
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
pdu = event_from_pdu_json(content, format_ver)
origin_host, _ = parse_server_name(origin) origin_host, _ = parse_server_name(origin)
yield self.check_server_matches_acl(origin_host, pdu.room_id) yield self.check_server_matches_acl(origin_host, pdu.room_id)
@ -410,9 +415,12 @@ class FederationServer(FederationBase):
}) })
@defer.inlineCallbacks @defer.inlineCallbacks
def on_send_leave_request(self, origin, content): def on_send_leave_request(self, origin, content, room_id):
logger.debug("on_send_leave_request: content: %s", content) logger.debug("on_send_leave_request: content: %s", content)
pdu = event_from_pdu_json(content)
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
pdu = event_from_pdu_json(content, format_ver)
origin_host, _ = parse_server_name(origin) origin_host, _ = parse_server_name(origin)
yield self.check_server_matches_acl(origin_host, pdu.room_id) yield self.check_server_matches_acl(origin_host, pdu.room_id)
@ -458,13 +466,14 @@ class FederationServer(FederationBase):
origin_host, _ = parse_server_name(origin) origin_host, _ = parse_server_name(origin)
yield self.check_server_matches_acl(origin_host, room_id) yield self.check_server_matches_acl(origin_host, room_id)
room_version = yield self.store.get_room_version(room_id)
format_ver = room_version_to_event_format(room_version)
auth_chain = [ auth_chain = [
event_from_pdu_json(e) event_from_pdu_json(e, format_ver)
for e in content["auth_chain"] for e in content["auth_chain"]
] ]
room_version = yield self.store.get_room_version(room_id)
signed_auth = yield self._check_sigs_and_hash_and_fetch( signed_auth = yield self._check_sigs_and_hash_and_fetch(
origin, auth_chain, outlier=True, room_version=room_version, origin, auth_chain, outlier=True, room_version=room_version,
) )

View file

@ -469,7 +469,7 @@ class FederationSendLeaveServlet(BaseFederationServlet):
@defer.inlineCallbacks @defer.inlineCallbacks
def on_PUT(self, origin, content, query, room_id, event_id): def on_PUT(self, origin, content, query, room_id, event_id):
content = yield self.handler.on_send_leave_request(origin, content) content = yield self.handler.on_send_leave_request(origin, content, room_id)
defer.returnValue((200, content)) defer.returnValue((200, content))
@ -487,7 +487,7 @@ class FederationSendJoinServlet(BaseFederationServlet):
def on_PUT(self, origin, content, query, context, event_id): def on_PUT(self, origin, content, query, context, event_id):
# TODO(paul): assert that context/event_id parsed from path actually # TODO(paul): assert that context/event_id parsed from path actually
# match those given in content # match those given in content
content = yield self.handler.on_send_join_request(origin, content) content = yield self.handler.on_send_join_request(origin, content, context)
defer.returnValue((200, content)) defer.returnValue((200, content))

View file

@ -1061,7 +1061,7 @@ class FederationHandler(BaseHandler):
""" """
logger.debug("Joining %s to %s", joinee, room_id) logger.debug("Joining %s to %s", joinee, room_id)
origin, event = yield self._make_and_verify_event( origin, event, event_format_version = yield self._make_and_verify_event(
target_hosts, target_hosts,
room_id, room_id,
joinee, joinee,
@ -1091,7 +1091,9 @@ class FederationHandler(BaseHandler):
target_hosts.insert(0, origin) target_hosts.insert(0, origin)
except ValueError: except ValueError:
pass pass
ret = yield self.federation_client.send_join(target_hosts, event) ret = yield self.federation_client.send_join(
target_hosts, event, event_format_version,
)
origin = ret["origin"] origin = ret["origin"]
state = ret["state"] state = ret["state"]
@ -1164,13 +1166,18 @@ class FederationHandler(BaseHandler):
""" """
event_content = {"membership": Membership.JOIN} event_content = {"membership": Membership.JOIN}
builder = self.event_builder_factory.new({ room_version = yield self.store.get_room_version(room_id)
"type": EventTypes.Member,
"content": event_content, builder = self.event_builder_factory.new(
"room_id": room_id, room_version,
"sender": user_id, {
"state_key": user_id, "type": EventTypes.Member,
}) "content": event_content,
"room_id": room_id,
"sender": user_id,
"state_key": user_id,
}
)
try: try:
event, context = yield self.event_creation_handler.create_new_client_event( event, context = yield self.event_creation_handler.create_new_client_event(
@ -1304,7 +1311,7 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def do_remotely_reject_invite(self, target_hosts, room_id, user_id): def do_remotely_reject_invite(self, target_hosts, room_id, user_id):
origin, event = yield self._make_and_verify_event( origin, event, event_format_version = yield self._make_and_verify_event(
target_hosts, target_hosts,
room_id, room_id,
user_id, user_id,
@ -1336,7 +1343,7 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def _make_and_verify_event(self, target_hosts, room_id, user_id, membership, def _make_and_verify_event(self, target_hosts, room_id, user_id, membership,
content={}, params=None): content={}, params=None):
origin, pdu, _ = yield self.federation_client.make_membership_event( origin, event, format_ver = yield self.federation_client.make_membership_event(
target_hosts, target_hosts,
room_id, room_id,
user_id, user_id,
@ -1345,9 +1352,7 @@ class FederationHandler(BaseHandler):
params=params, params=params,
) )
logger.debug("Got response to make_%s: %s", membership, pdu) logger.debug("Got response to make_%s: %s", membership, event)
event = pdu
# We should assert some things. # We should assert some things.
# FIXME: Do this in a nicer way # FIXME: Do this in a nicer way
@ -1355,7 +1360,7 @@ class FederationHandler(BaseHandler):
assert(event.user_id == user_id) assert(event.user_id == user_id)
assert(event.state_key == user_id) assert(event.state_key == user_id)
assert(event.room_id == room_id) assert(event.room_id == room_id)
defer.returnValue((origin, event)) defer.returnValue((origin, event, format_ver))
@defer.inlineCallbacks @defer.inlineCallbacks
@log_function @log_function
@ -1364,13 +1369,17 @@ class FederationHandler(BaseHandler):
leave event for the room and return that. We do *not* persist or leave event for the room and return that. We do *not* persist or
process it until the other server has signed it and sent it back. process it until the other server has signed it and sent it back.
""" """
builder = self.event_builder_factory.new({ room_version = yield self.store.get_room_version(room_id)
"type": EventTypes.Member, builder = self.event_builder_factory.new(
"content": {"membership": Membership.LEAVE}, room_version,
"room_id": room_id, {
"sender": user_id, "type": EventTypes.Member,
"state_key": user_id, "content": {"membership": Membership.LEAVE},
}) "room_id": room_id,
"sender": user_id,
"state_key": user_id,
}
)
event, context = yield self.event_creation_handler.create_new_client_event( event, context = yield self.event_creation_handler.create_new_client_event(
builder=builder, builder=builder,
@ -2266,14 +2275,16 @@ class FederationHandler(BaseHandler):
} }
if (yield self.auth.check_host_in_room(room_id, self.hs.hostname)): if (yield self.auth.check_host_in_room(room_id, self.hs.hostname)):
builder = self.event_builder_factory.new(event_dict) room_version = yield self.store.get_room_version(room_id)
builder = self.event_builder_factory.new(room_version, event_dict)
EventValidator().validate_new(builder) EventValidator().validate_new(builder)
event, context = yield self.event_creation_handler.create_new_client_event( event, context = yield self.event_creation_handler.create_new_client_event(
builder=builder builder=builder
) )
event, context = yield self.add_display_name_to_third_party_invite( event, context = yield self.add_display_name_to_third_party_invite(
event_dict, event, context room_version, event_dict, event, context
) )
try: try:
@ -2304,14 +2315,18 @@ class FederationHandler(BaseHandler):
Returns: Returns:
Deferred: resolves (to None) Deferred: resolves (to None)
""" """
builder = self.event_builder_factory.new(event_dict) room_version = yield self.store.get_room_version(room_id)
# NB: event_dict has a particular specced format we might need to fudge
# if we change event formats too much.
builder = self.event_builder_factory.new(room_version, event_dict)
event, context = yield self.event_creation_handler.create_new_client_event( event, context = yield self.event_creation_handler.create_new_client_event(
builder=builder, builder=builder,
) )
event, context = yield self.add_display_name_to_third_party_invite( event, context = yield self.add_display_name_to_third_party_invite(
event_dict, event, context room_version, event_dict, event, context
) )
try: try:
@ -2331,7 +2346,8 @@ class FederationHandler(BaseHandler):
yield member_handler.send_membership_event(None, event, context) yield member_handler.send_membership_event(None, event, context)
@defer.inlineCallbacks @defer.inlineCallbacks
def add_display_name_to_third_party_invite(self, event_dict, event, context): def add_display_name_to_third_party_invite(self, room_version, event_dict,
event, context):
key = ( key = (
EventTypes.ThirdPartyInvite, EventTypes.ThirdPartyInvite,
event.content["third_party_invite"]["signed"]["token"] event.content["third_party_invite"]["signed"]["token"]
@ -2355,7 +2371,7 @@ class FederationHandler(BaseHandler):
# auth checks. If we need the invite and don't have it then the # auth checks. If we need the invite and don't have it then the
# auth check code will explode appropriately. # auth check code will explode appropriately.
builder = self.event_builder_factory.new(event_dict) builder = self.event_builder_factory.new(room_version, event_dict)
EventValidator().validate_new(builder) EventValidator().validate_new(builder)
event, context = yield self.event_creation_handler.create_new_client_event( event, context = yield self.event_creation_handler.create_new_client_event(
builder=builder, builder=builder,

View file

@ -278,7 +278,15 @@ class EventCreationHandler(object):
""" """
yield self.auth.check_auth_blocking(requester.user.to_string()) yield self.auth.check_auth_blocking(requester.user.to_string())
builder = self.event_builder_factory.new(event_dict) if event_dict["type"] == EventTypes.Create and event_dict["state_key"] == "":
room_version = event_dict["content"]["room_version"]
else:
try:
room_version = yield self.store.get_room_version(event_dict["room_id"])
except NotFoundError:
raise AuthError(403, "Unknown room")
builder = self.event_builder_factory.new(room_version, event_dict)
self.validator.validate_new(builder) self.validator.validate_new(builder)

View file

@ -14,14 +14,16 @@
# limitations under the License. # limitations under the License.
import logging import logging
import attr
from netaddr import IPAddress
from zope.interface import implementer from zope.interface import implementer
from twisted.internet import defer from twisted.internet import defer
from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS
from twisted.web.client import URI, Agent, HTTPConnectionPool from twisted.web.client import URI, Agent, HTTPConnectionPool
from twisted.web.http_headers import Headers
from twisted.web.iweb import IAgent from twisted.web.iweb import IAgent
from synapse.http.endpoint import parse_server_name
from synapse.http.federation.srv_resolver import SrvResolver, pick_server_from_list from synapse.http.federation.srv_resolver import SrvResolver, pick_server_from_list
from synapse.util.logcontext import make_deferred_yieldable from synapse.util.logcontext import make_deferred_yieldable
@ -85,35 +87,35 @@ class MatrixFederationAgent(object):
response from being received (including problems that prevent the request response from being received (including problems that prevent the request
from being sent). from being sent).
""" """
parsed_uri = URI.fromBytes(uri, defaultPort=-1)
res = yield self._route_matrix_uri(parsed_uri)
parsed_uri = URI.fromBytes(uri) # set up the TLS connection params
server_name_bytes = parsed_uri.netloc #
host, port = parse_server_name(server_name_bytes.decode("ascii"))
# XXX disabling TLS is really only supported here for the benefit of the # XXX disabling TLS is really only supported here for the benefit of the
# unit tests. We should make the UTs cope with TLS rather than having to make # unit tests. We should make the UTs cope with TLS rather than having to make
# the code support the unit tests. # the code support the unit tests.
if self._tls_client_options_factory is None: if self._tls_client_options_factory is None:
tls_options = None tls_options = None
else: else:
tls_options = self._tls_client_options_factory.get_options(host) tls_options = self._tls_client_options_factory.get_options(
res.tls_server_name.decode("ascii")
)
if port is not None: # make sure that the Host header is set correctly
target = (host, port) if headers is None:
headers = Headers()
else: else:
service_name = b"_matrix._tcp.%s" % (server_name_bytes, ) headers = headers.copy()
server_list = yield self._srv_resolver.resolve_service(service_name)
if not server_list: if not headers.hasHeader(b'host'):
target = (host, 8448) headers.addRawHeader(b'host', res.host_header)
logger.debug("No SRV record for %s, using %s", host, target)
else:
target = pick_server_from_list(server_list)
class EndpointFactory(object): class EndpointFactory(object):
@staticmethod @staticmethod
def endpointForURI(_uri): def endpointForURI(_uri):
logger.info("Connecting to %s:%s", target[0], target[1]) logger.info("Connecting to %s:%s", res.target_host, res.target_port)
ep = HostnameEndpoint(self._reactor, host=target[0], port=target[1]) ep = HostnameEndpoint(self._reactor, res.target_host, res.target_port)
if tls_options is not None: if tls_options is not None:
ep = wrapClientTLS(tls_options, ep) ep = wrapClientTLS(tls_options, ep)
return ep return ep
@ -123,3 +125,111 @@ class MatrixFederationAgent(object):
agent.request(method, uri, headers, bodyProducer) agent.request(method, uri, headers, bodyProducer)
) )
defer.returnValue(res) defer.returnValue(res)
@defer.inlineCallbacks
def _route_matrix_uri(self, parsed_uri):
"""Helper for `request`: determine the routing for a Matrix URI
Args:
parsed_uri (twisted.web.client.URI): uri to route. Note that it should be
parsed with URI.fromBytes(uri, defaultPort=-1) to set the `port` to -1
if there is no explicit port given.
Returns:
Deferred[_RoutingResult]
"""
# check for an IP literal
try:
ip_address = IPAddress(parsed_uri.host.decode("ascii"))
except Exception:
# not an IP address
ip_address = None
if ip_address:
port = parsed_uri.port
if port == -1:
port = 8448
defer.returnValue(_RoutingResult(
host_header=parsed_uri.netloc,
tls_server_name=parsed_uri.host,
target_host=parsed_uri.host,
target_port=port,
))
if parsed_uri.port != -1:
# there is an explicit port
defer.returnValue(_RoutingResult(
host_header=parsed_uri.netloc,
tls_server_name=parsed_uri.host,
target_host=parsed_uri.host,
target_port=parsed_uri.port,
))
# try a SRV lookup
service_name = b"_matrix._tcp.%s" % (parsed_uri.host,)
server_list = yield self._srv_resolver.resolve_service(service_name)
if not server_list:
target_host = parsed_uri.host
port = 8448
logger.debug(
"No SRV record for %s, using %s:%i",
parsed_uri.host.decode("ascii"), target_host.decode("ascii"), port,
)
else:
target_host, port = pick_server_from_list(server_list)
logger.debug(
"Picked %s:%i from SRV records for %s",
target_host.decode("ascii"), port, parsed_uri.host.decode("ascii"),
)
defer.returnValue(_RoutingResult(
host_header=parsed_uri.netloc,
tls_server_name=parsed_uri.host,
target_host=target_host,
target_port=port,
))
@attr.s
class _RoutingResult(object):
"""The result returned by `_route_matrix_uri`.
Contains the parameters needed to direct a federation connection to a particular
server.
Where a SRV record points to several servers, this object contains a single server
chosen from the list.
"""
host_header = attr.ib()
"""
The value we should assign to the Host header (host:port from the matrix
URI, or .well-known).
:type: bytes
"""
tls_server_name = attr.ib()
"""
The server name we should set in the SNI (typically host, without port, from the
matrix URI or .well-known)
:type: bytes
"""
target_host = attr.ib()
"""
The hostname (or IP literal) we should route the TCP connection to (the target of the
SRV record, or the hostname from the URL/.well-known)
:type: bytes
"""
target_port = attr.ib()
"""
The port we should route the TCP connection to (the target of the SRV record, or
the port from the URL/.well-known, or 8448)
:type: int
"""

View file

@ -255,7 +255,6 @@ class MatrixFederationHttpClient(object):
headers_dict = { headers_dict = {
b"User-Agent": [self.version_string_bytes], b"User-Agent": [self.version_string_bytes],
b"Host": [destination_bytes],
} }
with limiter: with limiter:

View file

@ -17,7 +17,7 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from synapse.events import FrozenEvent from synapse.events import event_type_from_format_version
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.http.servlet import parse_json_object_from_request from synapse.http.servlet import parse_json_object_from_request
from synapse.replication.http._base import ReplicationEndpoint from synapse.replication.http._base import ReplicationEndpoint
@ -70,6 +70,7 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint):
event_payloads.append({ event_payloads.append({
"event": event.get_pdu_json(), "event": event.get_pdu_json(),
"event_format_version": event.format_version,
"internal_metadata": event.internal_metadata.get_dict(), "internal_metadata": event.internal_metadata.get_dict(),
"rejected_reason": event.rejected_reason, "rejected_reason": event.rejected_reason,
"context": serialized_context, "context": serialized_context,
@ -94,9 +95,12 @@ class ReplicationFederationSendEventsRestServlet(ReplicationEndpoint):
event_and_contexts = [] event_and_contexts = []
for event_payload in event_payloads: for event_payload in event_payloads:
event_dict = event_payload["event"] event_dict = event_payload["event"]
format_ver = content["event_format_version"]
internal_metadata = event_payload["internal_metadata"] internal_metadata = event_payload["internal_metadata"]
rejected_reason = event_payload["rejected_reason"] rejected_reason = event_payload["rejected_reason"]
event = FrozenEvent(event_dict, internal_metadata, rejected_reason)
EventType = event_type_from_format_version(format_ver)
event = EventType(event_dict, internal_metadata, rejected_reason)
context = yield EventContext.deserialize( context = yield EventContext.deserialize(
self.store, event_payload["context"], self.store, event_payload["context"],

View file

@ -17,7 +17,7 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from synapse.events import FrozenEvent from synapse.events import event_type_from_format_version
from synapse.events.snapshot import EventContext from synapse.events.snapshot import EventContext
from synapse.http.servlet import parse_json_object_from_request from synapse.http.servlet import parse_json_object_from_request
from synapse.replication.http._base import ReplicationEndpoint from synapse.replication.http._base import ReplicationEndpoint
@ -74,6 +74,7 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint):
payload = { payload = {
"event": event.get_pdu_json(), "event": event.get_pdu_json(),
"event_format_version": event.format_version,
"internal_metadata": event.internal_metadata.get_dict(), "internal_metadata": event.internal_metadata.get_dict(),
"rejected_reason": event.rejected_reason, "rejected_reason": event.rejected_reason,
"context": serialized_context, "context": serialized_context,
@ -90,9 +91,12 @@ class ReplicationSendEventRestServlet(ReplicationEndpoint):
content = parse_json_object_from_request(request) content = parse_json_object_from_request(request)
event_dict = content["event"] event_dict = content["event"]
format_ver = content["event_format_version"]
internal_metadata = content["internal_metadata"] internal_metadata = content["internal_metadata"]
rejected_reason = content["rejected_reason"] rejected_reason = content["rejected_reason"]
event = FrozenEvent(event_dict, internal_metadata, rejected_reason)
EventType = event_type_from_format_version(format_ver)
event = EventType(event_dict, internal_metadata, rejected_reason)
requester = Requester.deserialize(self.store, content["requester"]) requester = Requester.deserialize(self.store, content["requester"])
context = yield EventContext.deserialize(self.store, content["context"]) context = yield EventContext.deserialize(self.store, content["context"])

View file

@ -15,7 +15,6 @@
import struct import struct
import threading import threading
from sqlite3 import sqlite_version_info
from synapse.storage.prepare_database import prepare_database from synapse.storage.prepare_database import prepare_database
@ -34,10 +33,14 @@ class Sqlite3Engine(object):
@property @property
def can_native_upsert(self): def can_native_upsert(self):
""" """
Do we support native UPSERTs? This requires SQLite3 3.24+, plus some Do we support native UPSERTs?
more work we haven't done yet to tell what was inserted vs updated.
""" """
return sqlite_version_info >= (3, 24, 0) # SQLite3 3.24+ supports them, but empirically the unit tests don't work
# when its enabled.
# FIXME: Figure out what is wrong so we can re-enable native upserts
# return self.module.sqlite_version_info >= (3, 24, 0)
return False
def check_database(self, txn): def check_database(self, txn):
pass pass

View file

@ -23,7 +23,7 @@ from twisted.internet import defer
from synapse.api.constants import EventFormatVersions from synapse.api.constants import EventFormatVersions
from synapse.api.errors import NotFoundError from synapse.api.errors import NotFoundError
from synapse.events import FrozenEvent from synapse.events import FrozenEvent, event_type_from_format_version # noqa: F401
# these are only included to make the type annotations work # these are only included to make the type annotations work
from synapse.events.snapshot import EventContext # noqa: F401 from synapse.events.snapshot import EventContext # noqa: F401
from synapse.events.utils import prune_event from synapse.events.utils import prune_event
@ -412,11 +412,7 @@ class EventsWorkerStore(SQLBaseStore):
# of a event format version, so it must be a V1 event. # of a event format version, so it must be a V1 event.
format_version = EventFormatVersions.V1 format_version = EventFormatVersions.V1
# TODO: When we implement new event formats we'll need to use a original_ev = event_type_from_format_version(format_version)(
# different event python type
assert format_version == EventFormatVersions.V1
original_ev = FrozenEvent(
event_dict=d, event_dict=d,
internal_metadata_dict=internal_metadata, internal_metadata_dict=internal_metadata,
rejected_reason=rejected_reason, rejected_reason=rejected_reason,

View file

@ -131,6 +131,10 @@ class MatrixFederationAgentTests(TestCase):
request = http_server.requests[0] request = http_server.requests[0]
self.assertEqual(request.method, b'GET') self.assertEqual(request.method, b'GET')
self.assertEqual(request.path, b'/foo/bar') self.assertEqual(request.path, b'/foo/bar')
self.assertEqual(
request.requestHeaders.getRawHeaders(b'host'),
[b'testserv:8448']
)
content = request.content.read() content = request.content.read()
self.assertEqual(content, b'') self.assertEqual(content, b'')
@ -162,11 +166,7 @@ class MatrixFederationAgentTests(TestCase):
""" """
Test the behaviour when the server name contains an explicit IP (with no port) Test the behaviour when the server name contains an explicit IP (with no port)
""" """
# there will be a getaddrinfo on the IP
# the SRV lookup will return an empty list (XXX: why do we even do an SRV lookup?)
self.mock_resolver.resolve_service.side_effect = lambda _: []
# then there will be a getaddrinfo on the IP
self.reactor.lookups["1.2.3.4"] = "1.2.3.4" self.reactor.lookups["1.2.3.4"] = "1.2.3.4"
test_d = self._make_get_request(b"matrix://1.2.3.4/foo/bar") test_d = self._make_get_request(b"matrix://1.2.3.4/foo/bar")
@ -174,10 +174,6 @@ class MatrixFederationAgentTests(TestCase):
# Nothing happened yet # Nothing happened yet
self.assertNoResult(test_d) self.assertNoResult(test_d)
self.mock_resolver.resolve_service.assert_called_once_with(
b"_matrix._tcp.1.2.3.4",
)
# Make sure treq is trying to connect # Make sure treq is trying to connect
clients = self.reactor.tcpClients clients = self.reactor.tcpClients
self.assertEqual(len(clients), 1) self.assertEqual(len(clients), 1)
@ -195,6 +191,92 @@ class MatrixFederationAgentTests(TestCase):
request = http_server.requests[0] request = http_server.requests[0]
self.assertEqual(request.method, b'GET') self.assertEqual(request.method, b'GET')
self.assertEqual(request.path, b'/foo/bar') self.assertEqual(request.path, b'/foo/bar')
self.assertEqual(
request.requestHeaders.getRawHeaders(b'host'),
[b'1.2.3.4'],
)
# finish the request
request.finish()
self.reactor.pump((0.1,))
self.successResultOf(test_d)
def test_get_ipv6_address(self):
"""
Test the behaviour when the server name contains an explicit IPv6 address
(with no port)
"""
# there will be a getaddrinfo on the IP
self.reactor.lookups["::1"] = "::1"
test_d = self._make_get_request(b"matrix://[::1]/foo/bar")
# Nothing happened yet
self.assertNoResult(test_d)
# 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')
self.assertEqual(port, 8448)
# make a test server, and wire up the client
http_server = self._make_connection(
client_factory,
expected_sni=None,
)
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'[::1]'],
)
# finish the request
request.finish()
self.reactor.pump((0.1,))
self.successResultOf(test_d)
def test_get_ipv6_address_with_port(self):
"""
Test the behaviour when the server name contains an explicit IPv6 address
(with explicit port)
"""
# there will be a getaddrinfo on the IP
self.reactor.lookups["::1"] = "::1"
test_d = self._make_get_request(b"matrix://[::1]:80/foo/bar")
# Nothing happened yet
self.assertNoResult(test_d)
# 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')
self.assertEqual(port, 80)
# make a test server, and wire up the client
http_server = self._make_connection(
client_factory,
expected_sni=None,
)
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'[::1]:80'],
)
# finish the request # finish the request
request.finish() request.finish()
@ -235,6 +317,10 @@ class MatrixFederationAgentTests(TestCase):
request = http_server.requests[0] request = http_server.requests[0]
self.assertEqual(request.method, b'GET') self.assertEqual(request.method, b'GET')
self.assertEqual(request.path, b'/foo/bar') self.assertEqual(request.path, b'/foo/bar')
self.assertEqual(
request.requestHeaders.getRawHeaders(b'host'),
[b'testserv'],
)
# finish the request # finish the request
request.finish() request.finish()
@ -246,7 +332,7 @@ class MatrixFederationAgentTests(TestCase):
Test the behaviour when there is a single SRV record Test the behaviour when there is a single SRV record
""" """
self.mock_resolver.resolve_service.side_effect = lambda _: [ self.mock_resolver.resolve_service.side_effect = lambda _: [
Server(host="srvtarget", port=8443) Server(host=b"srvtarget", port=8443)
] ]
self.reactor.lookups["srvtarget"] = "1.2.3.4" self.reactor.lookups["srvtarget"] = "1.2.3.4"
@ -276,6 +362,100 @@ class MatrixFederationAgentTests(TestCase):
request = http_server.requests[0] request = http_server.requests[0]
self.assertEqual(request.method, b'GET') self.assertEqual(request.method, b'GET')
self.assertEqual(request.path, b'/foo/bar') 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_idna_servername(self):
"""test the behaviour when the server name has idna chars in"""
self.mock_resolver.resolve_service.side_effect = lambda _: []
# hostnameendpoint does the lookup on the unicode value (getaddrinfo encodes
# it back to idna)
self.reactor.lookups[u"bücher.com"] = "1.2.3.4"
# this is idna for bücher.com
test_d = self._make_get_request(b"matrix://xn--bcher-kva.com/foo/bar")
# Nothing happened yet
self.assertNoResult(test_d)
self.mock_resolver.resolve_service.assert_called_once_with(
b"_matrix._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, 8448)
# 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(self):
"""test the behaviour when the target of a SRV record has idna chars"""
self.mock_resolver.resolve_service.side_effect = lambda _: [
Server(host=b"xn--trget-3qa.com", port=8443) # târget.com
]
self.reactor.lookups[u"târget.com"] = "1.2.3.4"
test_d = self._make_get_request(b"matrix://xn--bcher-kva.com/foo/bar")
# Nothing happened yet
self.assertNoResult(test_d)
self.mock_resolver.resolve_service.assert_called_once_with(
b"_matrix._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 # finish the request
request.finish() request.finish()

View file

@ -49,7 +49,6 @@ class FederationClientTests(HomeserverTestCase):
return hs return hs
def prepare(self, reactor, clock, homeserver): def prepare(self, reactor, clock, homeserver):
self.cl = MatrixFederationHttpClient(self.hs) self.cl = MatrixFederationHttpClient(self.hs)
self.reactor.lookups["testserv"] = "1.2.3.4" self.reactor.lookups["testserv"] = "1.2.3.4"
@ -95,6 +94,7 @@ class FederationClientTests(HomeserverTestCase):
# that should have made it send the request to the transport # that should have made it send the request to the transport
self.assertRegex(transport.value(), b"^GET /foo/bar") self.assertRegex(transport.value(), b"^GET /foo/bar")
self.assertRegex(transport.value(), b"Host: testserv:8008")
# Deferred is still without a result # Deferred is still without a result
self.assertNoResult(test_d) self.assertNoResult(test_d)

View file

@ -18,7 +18,7 @@ from mock import Mock
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership from synapse.api.constants import EventTypes, Membership, RoomVersions
from synapse.types import RoomID, UserID from synapse.types import RoomID, UserID
from tests import unittest from tests import unittest
@ -52,6 +52,7 @@ class RedactionTestCase(unittest.TestCase):
content = {"membership": membership} content = {"membership": membership}
content.update(extra_content) content.update(extra_content)
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": EventTypes.Member, "type": EventTypes.Member,
"sender": user.to_string(), "sender": user.to_string(),
@ -74,6 +75,7 @@ class RedactionTestCase(unittest.TestCase):
self.depth += 1 self.depth += 1
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": EventTypes.Message, "type": EventTypes.Message,
"sender": user.to_string(), "sender": user.to_string(),
@ -94,6 +96,7 @@ class RedactionTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def inject_redaction(self, room, event_id, user, reason): def inject_redaction(self, room, event_id, user, reason):
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": EventTypes.Redaction, "type": EventTypes.Redaction,
"sender": user.to_string(), "sender": user.to_string(),

View file

@ -18,7 +18,7 @@ from mock import Mock
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership from synapse.api.constants import EventTypes, Membership, RoomVersions
from synapse.types import RoomID, UserID from synapse.types import RoomID, UserID
from tests import unittest from tests import unittest
@ -50,6 +50,7 @@ class RoomMemberStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def inject_room_member(self, room, user, membership, replaces_state=None): def inject_room_member(self, room, user, membership, replaces_state=None):
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": EventTypes.Member, "type": EventTypes.Member,
"sender": user.to_string(), "sender": user.to_string(),

View file

@ -17,7 +17,7 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import EventTypes, Membership from synapse.api.constants import EventTypes, Membership, RoomVersions
from synapse.storage.state import StateFilter from synapse.storage.state import StateFilter
from synapse.types import RoomID, UserID from synapse.types import RoomID, UserID
@ -52,6 +52,7 @@ class StateStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def inject_state_event(self, room, sender, typ, state_key, content): def inject_state_event(self, room, sender, typ, state_key, content):
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": typ, "type": typ,
"sender": sender.to_string(), "sender": sender.to_string(),

View file

@ -17,6 +17,7 @@ import logging
from twisted.internet import defer from twisted.internet import defer
from twisted.internet.defer import succeed from twisted.internet.defer import succeed
from synapse.api.constants import RoomVersions
from synapse.events import FrozenEvent from synapse.events import FrozenEvent
from synapse.visibility import filter_events_for_server from synapse.visibility import filter_events_for_server
@ -124,6 +125,7 @@ class FilterEventsForServerTestCase(tests.unittest.TestCase):
def inject_visibility(self, user_id, visibility): def inject_visibility(self, user_id, visibility):
content = {"history_visibility": visibility} content = {"history_visibility": visibility}
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": "m.room.history_visibility", "type": "m.room.history_visibility",
"sender": user_id, "sender": user_id,
@ -144,6 +146,7 @@ class FilterEventsForServerTestCase(tests.unittest.TestCase):
content = {"membership": membership} content = {"membership": membership}
content.update(extra_content) content.update(extra_content)
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": "m.room.member", "type": "m.room.member",
"sender": user_id, "sender": user_id,
@ -165,6 +168,7 @@ class FilterEventsForServerTestCase(tests.unittest.TestCase):
if content is None: if content is None:
content = {"body": "testytest"} content = {"body": "testytest"}
builder = self.event_builder_factory.new( builder = self.event_builder_factory.new(
RoomVersions.V1,
{ {
"type": "m.room.message", "type": "m.room.message",
"sender": user_id, "sender": user_id,

View file

@ -26,7 +26,7 @@ from six.moves.urllib import parse as urlparse
from twisted.internet import defer, reactor from twisted.internet import defer, reactor
from synapse.api.constants import EventTypes from synapse.api.constants import EventTypes, RoomVersions
from synapse.api.errors import CodeMessageException, cs_error from synapse.api.errors import CodeMessageException, cs_error
from synapse.config.server import ServerConfig from synapse.config.server import ServerConfig
from synapse.federation.transport import server from synapse.federation.transport import server
@ -624,6 +624,7 @@ def create_room(hs, room_id, creator_id):
event_creation_handler = hs.get_event_creation_handler() event_creation_handler = hs.get_event_creation_handler()
builder = event_builder_factory.new( builder = event_builder_factory.new(
RoomVersions.V1,
{ {
"type": EventTypes.Create, "type": EventTypes.Create,
"state_key": "", "state_key": "",