diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py
index 6a2631ee18..01aa285130 100644
--- a/synapse/federation/federation_server.py
+++ b/synapse/federation/federation_server.py
@@ -568,7 +568,7 @@ class FederationServer(FederationBase):
return {}
async def on_make_knock_request(
- self, origin: str, room_id: str, user_id: str,
+ self, origin: str, room_id: str, user_id: str, supported_versions: List[str]
) -> Dict[str, Union[EventBase, str]]:
"""We've received a /make_knock/ request, so we create a partial knock
event for the room and hand that back, along with the room version, to the knocking
@@ -579,16 +579,22 @@ class FederationServer(FederationBase):
origin: The (verified) server name of the requesting server.
room_id: The room to create the knock event in.
user_id: The user to create the knock for.
+ supported_versions: The room versions supported by the requesting server.
Returns:
The partial knock event.
"""
origin_host, _ = parse_server_name(origin)
await self.check_server_matches_acl(origin_host, room_id)
- pdu = await self.handler.on_make_knock_request(origin, room_id, user_id)
room_version = await self.store.get_room_version_id(room_id)
+ if room_version not in supported_versions:
+ logger.warning(
+ "Room version %s not in %s", room_version, supported_versions
+ )
+ raise IncompatibleRoomVersionError(room_version=room_version)
+ pdu = await self.handler.on_make_knock_request(origin, room_id, user_id)
time_now = self._clock.time_msec()
return {"event": pdu.get_pdu_json(time_now), "room_version": room_version}
diff --git a/synapse/federation/transport/server.py b/synapse/federation/transport/server.py
index 40d6af45cd..961d16ac5a 100644
--- a/synapse/federation/transport/server.py
+++ b/synapse/federation/transport/server.py
@@ -15,7 +15,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
import functools
import logging
import re
@@ -36,6 +35,7 @@ from synapse.http.servlet import (
parse_boolean_from_args,
parse_integer_from_args,
parse_json_object_from_request,
+ parse_list_from_args,
parse_string_from_args,
)
from synapse.logging.context import run_in_background
@@ -550,7 +550,15 @@ class FederationMakeKnockServlet(BaseFederationServlet):
PREFIX = FEDERATION_UNSTABLE_PREFIX + "/xyz.amorgan.knock"
async def on_GET(self, origin, content, query, room_id, user_id):
- content = await self.handler.on_make_knock_request(origin, room_id, user_id)
+ try:
+ # Retrieve the room versions the remote homeserver claims to support
+ supported_versions = parse_list_from_args(query, "ver", encoding="utf-8")
+ except KeyError:
+ raise SynapseError(400, "Missing required query parameter 'ver'")
+
+ content = await self.handler.on_make_knock_request(
+ origin, room_id, user_id, supported_versions=supported_versions
+ )
return 200, content
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index a9ac4bd85e..87c8da0196 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -1470,10 +1470,14 @@ class FederationHandler(BaseHandler):
"""
logger.debug("Knocking on room %s on behalf of user %s", room_id, knockee)
+ # Inform the remote server of the room versions we support
+ supported_room_versions = list(KNOWN_ROOM_VERSIONS.keys())
+
# Ask the remote server to create a valid knock event for us. Once received,
# we sign the event
+ params = {"ver": supported_room_versions} # type: Dict[str, Iterable[str]]
origin, event, event_format_version = await self._make_and_verify_event(
- target_hosts, room_id, knockee, Membership.KNOCK, content,
+ target_hosts, room_id, knockee, Membership.KNOCK, content, params=params
)
# Record the room ID and its version so that we have a record of the room
@@ -1875,6 +1879,7 @@ class FederationHandler(BaseHandler):
raise SynapseError(403, "User not from origin", Codes.FORBIDDEN)
room_version = await self.store.get_room_version_id(room_id)
+
builder = self.event_builder_factory.new(
room_version,
{
diff --git a/tests/federation/transport/test_knocking.py b/tests/federation/transport/test_knocking.py
index 9e30037ea3..f60fdd7983 100644
--- a/tests/federation/transport/test_knocking.py
+++ b/tests/federation/transport/test_knocking.py
@@ -229,8 +229,15 @@ class FederationKnockingTestCase(
_, channel = self.make_request(
"GET",
- "/_matrix/federation/unstable/%s/make_knock/%s/%s"
- % (KNOCK_UNSTABLE_IDENTIFIER, room_id, fake_knocking_user_id),
+ "/_matrix/federation/unstable/%s/make_knock/%s/%s?ver=%s"
+ % (
+ KNOCK_UNSTABLE_IDENTIFIER,
+ room_id,
+ fake_knocking_user_id,
+ # Inform the remote that we support the room version of the room we're
+ # knocking on
+ RoomVersions.MSC2403_DEV.identifier,
+ ),
)
self.assertEquals(200, channel.code, channel.result)
|