Implement fallback for V2 invite API
If the room version is either 1 or 2 then a server should retry failed `/v2/invite` requests with the v1 API
This commit is contained in:
parent
57a3e96e8e
commit
d414f30019
|
@ -751,18 +751,9 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def send_invite(self, destination, room_id, event_id, pdu):
|
def send_invite(self, destination, room_id, event_id, pdu):
|
||||||
time_now = self._clock.time_msec()
|
room_version = yield self.store.get_room_version(room_id)
|
||||||
try:
|
|
||||||
code, content = yield self.transport_layer.send_invite(
|
content = yield self._do_send_invite(destination, pdu, room_version)
|
||||||
destination=destination,
|
|
||||||
room_id=room_id,
|
|
||||||
event_id=event_id,
|
|
||||||
content=pdu.get_pdu_json(time_now),
|
|
||||||
)
|
|
||||||
except HttpResponseException as e:
|
|
||||||
if e.code == 403:
|
|
||||||
raise e.to_synapse_error()
|
|
||||||
raise
|
|
||||||
|
|
||||||
pdu_dict = content["event"]
|
pdu_dict = content["event"]
|
||||||
|
|
||||||
|
@ -780,6 +771,55 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
defer.returnValue(pdu)
|
defer.returnValue(pdu)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def _do_send_invite(self, destination, pdu, room_version):
|
||||||
|
"""Actually sends the invite, first trying v2 API and falling back to
|
||||||
|
v1 API if necessary.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
destination (str): Target server
|
||||||
|
pdu (FrozenEvent)
|
||||||
|
room_version (str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: The event as a dict as returned by the remote server
|
||||||
|
"""
|
||||||
|
time_now = self._clock.time_msec()
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = yield self.transport_layer.send_invite_v2(
|
||||||
|
destination=destination,
|
||||||
|
room_id=pdu.room_id,
|
||||||
|
event_id=pdu.event_id,
|
||||||
|
content={
|
||||||
|
"event": pdu.get_pdu_json(time_now),
|
||||||
|
"room_version": room_version,
|
||||||
|
"invite_room_state": pdu.unsigned.get("invite_room_state", []),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
defer.returnValue(content)
|
||||||
|
except HttpResponseException as e:
|
||||||
|
if e.code in [400, 404]:
|
||||||
|
if room_version in (RoomVersions.V1, RoomVersions.V2):
|
||||||
|
pass # We'll fall through
|
||||||
|
else:
|
||||||
|
raise Exception("Remote server is too old")
|
||||||
|
elif e.code == 403:
|
||||||
|
raise e.to_synapse_error()
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Didn't work, try v1 API.
|
||||||
|
# Note the v1 API returns a tuple of `(200, content)`
|
||||||
|
|
||||||
|
_, content = yield self.transport_layer.send_invite_v1(
|
||||||
|
destination=destination,
|
||||||
|
room_id=pdu.room_id,
|
||||||
|
event_id=pdu.event_id,
|
||||||
|
content=pdu.get_pdu_json(time_now),
|
||||||
|
)
|
||||||
|
defer.returnValue(content)
|
||||||
|
|
||||||
def send_leave(self, destinations, pdu):
|
def send_leave(self, destinations, pdu):
|
||||||
"""Sends a leave event to one of a list of homeservers.
|
"""Sends a leave event to one of a list of homeservers.
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ from six.moves import urllib
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
from synapse.api.constants import Membership
|
from synapse.api.constants import Membership
|
||||||
from synapse.api.urls import FEDERATION_V1_PREFIX
|
from synapse.api.urls import FEDERATION_V1_PREFIX, FEDERATION_V2_PREFIX
|
||||||
from synapse.util.logutils import log_function
|
from synapse.util.logutils import log_function
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -289,7 +289,7 @@ class TransportLayerClient(object):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def send_invite(self, destination, room_id, event_id, content):
|
def send_invite_v1(self, destination, room_id, event_id, content):
|
||||||
path = _create_v1_path("/invite/%s/%s", room_id, event_id)
|
path = _create_v1_path("/invite/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
response = yield self.client.put_json(
|
response = yield self.client.put_json(
|
||||||
|
@ -301,6 +301,20 @@ class TransportLayerClient(object):
|
||||||
|
|
||||||
defer.returnValue(response)
|
defer.returnValue(response)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
@log_function
|
||||||
|
def send_invite_v2(self, destination, room_id, event_id, content):
|
||||||
|
path = _create_v2_path("/invite/%s/%s", room_id, event_id)
|
||||||
|
|
||||||
|
response = yield self.client.put_json(
|
||||||
|
destination=destination,
|
||||||
|
path=path,
|
||||||
|
data=content,
|
||||||
|
ignore_backoff=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
defer.returnValue(response)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def get_public_rooms(self, remote_server, limit, since_token,
|
def get_public_rooms(self, remote_server, limit, since_token,
|
||||||
|
@ -958,3 +972,24 @@ def _create_v1_path(path, *args):
|
||||||
FEDERATION_V1_PREFIX
|
FEDERATION_V1_PREFIX
|
||||||
+ path % tuple(urllib.parse.quote(arg, "") for arg in args)
|
+ path % tuple(urllib.parse.quote(arg, "") for arg in args)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_v2_path(path, *args):
|
||||||
|
"""Creates a path against V2 federation API from the path template and
|
||||||
|
args. Ensures that all args are url encoded.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
_create_v2_path("/event/%s/", event_id)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): String template for the path
|
||||||
|
args: ([str]): Args to insert into path. Each arg will be url encoded
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
FEDERATION_V2_PREFIX
|
||||||
|
+ path % tuple(urllib.parse.quote(arg, "") for arg in args)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue