mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-15 01:53:58 +01:00
Merge pull request #6349 from matrix-org/babolivier/msc1802
Implement v2 APIs for send_join and send_leave
This commit is contained in:
commit
54ae52ba96
5 changed files with 141 additions and 28 deletions
1
changelog.d/6349.feature
Normal file
1
changelog.d/6349.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Implement v2 APIs for the `send_join` and `send_leave` federation endpoints (as described in [MSC1802](https://github.com/matrix-org/matrix-doc/pull/1802)).
|
|
@ -526,13 +526,7 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def send_request(destination):
|
def send_request(destination):
|
||||||
time_now = self._clock.time_msec()
|
content = yield self._do_send_join(destination, pdu)
|
||||||
_, content = yield self.transport_layer.send_join(
|
|
||||||
destination=destination,
|
|
||||||
room_id=pdu.room_id,
|
|
||||||
event_id=pdu.event_id,
|
|
||||||
content=pdu.get_pdu_json(time_now),
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug("Got content: %s", content)
|
logger.debug("Got content: %s", content)
|
||||||
|
|
||||||
|
@ -599,6 +593,44 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
return self._try_destination_list("send_join", destinations, send_request)
|
return self._try_destination_list("send_join", destinations, send_request)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def _do_send_join(self, destination, pdu):
|
||||||
|
time_now = self._clock.time_msec()
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = yield self.transport_layer.send_join_v2(
|
||||||
|
destination=destination,
|
||||||
|
room_id=pdu.room_id,
|
||||||
|
event_id=pdu.event_id,
|
||||||
|
content=pdu.get_pdu_json(time_now),
|
||||||
|
)
|
||||||
|
|
||||||
|
return content
|
||||||
|
except HttpResponseException as e:
|
||||||
|
if e.code in [400, 404]:
|
||||||
|
err = e.to_synapse_error()
|
||||||
|
|
||||||
|
# If we receive an error response that isn't a generic error, or an
|
||||||
|
# unrecognised endpoint error, we assume that the remote understands
|
||||||
|
# the v2 invite API and this is a legitimate error.
|
||||||
|
if err.errcode not in [Codes.UNKNOWN, Codes.UNRECOGNIZED]:
|
||||||
|
raise err
|
||||||
|
else:
|
||||||
|
raise e.to_synapse_error()
|
||||||
|
|
||||||
|
logger.debug("Couldn't send_join with the v2 API, falling back to the v1 API")
|
||||||
|
|
||||||
|
resp = yield self.transport_layer.send_join_v1(
|
||||||
|
destination=destination,
|
||||||
|
room_id=pdu.room_id,
|
||||||
|
event_id=pdu.event_id,
|
||||||
|
content=pdu.get_pdu_json(time_now),
|
||||||
|
)
|
||||||
|
|
||||||
|
# We expect the v1 API to respond with [200, content], so we only return the
|
||||||
|
# content.
|
||||||
|
return resp[1]
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def send_invite(self, destination, room_id, event_id, pdu):
|
def send_invite(self, destination, room_id, event_id, pdu):
|
||||||
room_version = yield self.store.get_room_version(room_id)
|
room_version = yield self.store.get_room_version(room_id)
|
||||||
|
@ -708,18 +740,50 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def send_request(destination):
|
def send_request(destination):
|
||||||
|
content = yield self._do_send_leave(destination, pdu)
|
||||||
|
|
||||||
|
logger.debug("Got content: %s", content)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._try_destination_list("send_leave", destinations, send_request)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def _do_send_leave(self, destination, pdu):
|
||||||
time_now = self._clock.time_msec()
|
time_now = self._clock.time_msec()
|
||||||
_, content = yield self.transport_layer.send_leave(
|
|
||||||
|
try:
|
||||||
|
content = yield self.transport_layer.send_leave_v2(
|
||||||
destination=destination,
|
destination=destination,
|
||||||
room_id=pdu.room_id,
|
room_id=pdu.room_id,
|
||||||
event_id=pdu.event_id,
|
event_id=pdu.event_id,
|
||||||
content=pdu.get_pdu_json(time_now),
|
content=pdu.get_pdu_json(time_now),
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug("Got content: %s", content)
|
return content
|
||||||
return None
|
except HttpResponseException as e:
|
||||||
|
if e.code in [400, 404]:
|
||||||
|
err = e.to_synapse_error()
|
||||||
|
|
||||||
return self._try_destination_list("send_leave", destinations, send_request)
|
# If we receive an error response that isn't a generic error, or an
|
||||||
|
# unrecognised endpoint error, we assume that the remote understands
|
||||||
|
# the v2 invite API and this is a legitimate error.
|
||||||
|
if err.errcode not in [Codes.UNKNOWN, Codes.UNRECOGNIZED]:
|
||||||
|
raise err
|
||||||
|
else:
|
||||||
|
raise e.to_synapse_error()
|
||||||
|
|
||||||
|
logger.debug("Couldn't send_leave with the v2 API, falling back to the v1 API")
|
||||||
|
|
||||||
|
resp = yield self.transport_layer.send_leave_v1(
|
||||||
|
destination=destination,
|
||||||
|
room_id=pdu.room_id,
|
||||||
|
event_id=pdu.event_id,
|
||||||
|
content=pdu.get_pdu_json(time_now),
|
||||||
|
)
|
||||||
|
|
||||||
|
# We expect the v1 API to respond with [200, content], so we only return the
|
||||||
|
# content.
|
||||||
|
return resp[1]
|
||||||
|
|
||||||
def get_public_rooms(
|
def get_public_rooms(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -384,15 +384,10 @@ class FederationServer(FederationBase):
|
||||||
|
|
||||||
res_pdus = await self.handler.on_send_join_request(origin, pdu)
|
res_pdus = await self.handler.on_send_join_request(origin, pdu)
|
||||||
time_now = self._clock.time_msec()
|
time_now = self._clock.time_msec()
|
||||||
return (
|
return {
|
||||||
200,
|
|
||||||
{
|
|
||||||
"state": [p.get_pdu_json(time_now) for p in res_pdus["state"]],
|
"state": [p.get_pdu_json(time_now) for p in res_pdus["state"]],
|
||||||
"auth_chain": [
|
"auth_chain": [p.get_pdu_json(time_now) for p in res_pdus["auth_chain"]],
|
||||||
p.get_pdu_json(time_now) for p in res_pdus["auth_chain"]
|
}
|
||||||
],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
async def on_make_leave_request(self, origin, room_id, user_id):
|
async def on_make_leave_request(self, origin, room_id, user_id):
|
||||||
origin_host, _ = parse_server_name(origin)
|
origin_host, _ = parse_server_name(origin)
|
||||||
|
@ -419,7 +414,7 @@ class FederationServer(FederationBase):
|
||||||
pdu = await self._check_sigs_and_hash(room_version, pdu)
|
pdu = await self._check_sigs_and_hash(room_version, pdu)
|
||||||
|
|
||||||
await self.handler.on_send_leave_request(origin, pdu)
|
await self.handler.on_send_leave_request(origin, pdu)
|
||||||
return 200, {}
|
return {}
|
||||||
|
|
||||||
async def on_event_auth(self, origin, room_id, event_id):
|
async def on_event_auth(self, origin, room_id, event_id):
|
||||||
with (await self._server_linearizer.queue((origin, room_id))):
|
with (await self._server_linearizer.queue((origin, room_id))):
|
||||||
|
|
|
@ -243,7 +243,7 @@ class TransportLayerClient(object):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def send_join(self, destination, room_id, event_id, content):
|
def send_join_v1(self, destination, room_id, event_id, content):
|
||||||
path = _create_v1_path("/send_join/%s/%s", room_id, event_id)
|
path = _create_v1_path("/send_join/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
response = yield self.client.put_json(
|
response = yield self.client.put_json(
|
||||||
|
@ -254,7 +254,18 @@ class TransportLayerClient(object):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def send_leave(self, destination, room_id, event_id, content):
|
def send_join_v2(self, destination, room_id, event_id, content):
|
||||||
|
path = _create_v2_path("/send_join/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
|
response = yield self.client.put_json(
|
||||||
|
destination=destination, path=path, data=content
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
@log_function
|
||||||
|
def send_leave_v1(self, destination, room_id, event_id, content):
|
||||||
path = _create_v1_path("/send_leave/%s/%s", room_id, event_id)
|
path = _create_v1_path("/send_leave/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
response = yield self.client.put_json(
|
response = yield self.client.put_json(
|
||||||
|
@ -270,6 +281,24 @@ class TransportLayerClient(object):
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
@log_function
|
||||||
|
def send_leave_v2(self, destination, room_id, event_id, content):
|
||||||
|
path = _create_v2_path("/send_leave/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
|
response = yield self.client.put_json(
|
||||||
|
destination=destination,
|
||||||
|
path=path,
|
||||||
|
data=content,
|
||||||
|
# we want to do our best to send this through. The problem is
|
||||||
|
# that if it fails, we won't retry it later, so if the remote
|
||||||
|
# server was just having a momentary blip, the room will be out of
|
||||||
|
# sync.
|
||||||
|
ignore_backoff=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def send_invite_v1(self, destination, room_id, event_id, content):
|
def send_invite_v1(self, destination, room_id, event_id, content):
|
||||||
|
|
|
@ -506,9 +506,19 @@ class FederationMakeLeaveServlet(BaseFederationServlet):
|
||||||
return 200, content
|
return 200, content
|
||||||
|
|
||||||
|
|
||||||
class FederationSendLeaveServlet(BaseFederationServlet):
|
class FederationV1SendLeaveServlet(BaseFederationServlet):
|
||||||
PATH = "/send_leave/(?P<room_id>[^/]*)/(?P<event_id>[^/]*)"
|
PATH = "/send_leave/(?P<room_id>[^/]*)/(?P<event_id>[^/]*)"
|
||||||
|
|
||||||
|
async def on_PUT(self, origin, content, query, room_id, event_id):
|
||||||
|
content = await self.handler.on_send_leave_request(origin, content, room_id)
|
||||||
|
return 200, (200, content)
|
||||||
|
|
||||||
|
|
||||||
|
class FederationV2SendLeaveServlet(BaseFederationServlet):
|
||||||
|
PATH = "/send_leave/(?P<room_id>[^/]*)/(?P<event_id>[^/]*)"
|
||||||
|
|
||||||
|
PREFIX = FEDERATION_V2_PREFIX
|
||||||
|
|
||||||
async def on_PUT(self, origin, content, query, room_id, event_id):
|
async def on_PUT(self, origin, content, query, room_id, event_id):
|
||||||
content = await self.handler.on_send_leave_request(origin, content, room_id)
|
content = await self.handler.on_send_leave_request(origin, content, room_id)
|
||||||
return 200, content
|
return 200, content
|
||||||
|
@ -521,9 +531,21 @@ class FederationEventAuthServlet(BaseFederationServlet):
|
||||||
return await self.handler.on_event_auth(origin, context, event_id)
|
return await self.handler.on_event_auth(origin, context, event_id)
|
||||||
|
|
||||||
|
|
||||||
class FederationSendJoinServlet(BaseFederationServlet):
|
class FederationV1SendJoinServlet(BaseFederationServlet):
|
||||||
PATH = "/send_join/(?P<context>[^/]*)/(?P<event_id>[^/]*)"
|
PATH = "/send_join/(?P<context>[^/]*)/(?P<event_id>[^/]*)"
|
||||||
|
|
||||||
|
async def on_PUT(self, origin, content, query, context, event_id):
|
||||||
|
# TODO(paul): assert that context/event_id parsed from path actually
|
||||||
|
# match those given in content
|
||||||
|
content = await self.handler.on_send_join_request(origin, content, context)
|
||||||
|
return 200, (200, content)
|
||||||
|
|
||||||
|
|
||||||
|
class FederationV2SendJoinServlet(BaseFederationServlet):
|
||||||
|
PATH = "/send_join/(?P<context>[^/]*)/(?P<event_id>[^/]*)"
|
||||||
|
|
||||||
|
PREFIX = FEDERATION_V2_PREFIX
|
||||||
|
|
||||||
async def on_PUT(self, origin, content, query, context, event_id):
|
async 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
|
||||||
|
@ -1367,8 +1389,10 @@ FEDERATION_SERVLET_CLASSES = (
|
||||||
FederationMakeJoinServlet,
|
FederationMakeJoinServlet,
|
||||||
FederationMakeLeaveServlet,
|
FederationMakeLeaveServlet,
|
||||||
FederationEventServlet,
|
FederationEventServlet,
|
||||||
FederationSendJoinServlet,
|
FederationV1SendJoinServlet,
|
||||||
FederationSendLeaveServlet,
|
FederationV2SendJoinServlet,
|
||||||
|
FederationV1SendLeaveServlet,
|
||||||
|
FederationV2SendLeaveServlet,
|
||||||
FederationV1InviteServlet,
|
FederationV1InviteServlet,
|
||||||
FederationV2InviteServlet,
|
FederationV2InviteServlet,
|
||||||
FederationQueryAuthServlet,
|
FederationQueryAuthServlet,
|
||||||
|
|
Loading…
Reference in a new issue