From 5ef0948eaa48d44822345efe04ec1612a96a4d37 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 20 Aug 2014 14:42:36 +0100 Subject: Better handle the edge cases of trying to remote join rooms --- synapse/handlers/federation.py | 78 ++++++++++++++++++++++++++++++++++++++++++ synapse/handlers/room.py | 47 ++++++------------------- 2 files changed, 88 insertions(+), 37 deletions(-) diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 0430a8307e..aa3bf273f7 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -72,6 +72,34 @@ class FederationHandler(BaseHandler): with (yield self.room_lock.lock(event.room_id)): store_id = yield self.store.persist_event(event, backfilled) + room = yield self.store.get_room(event.room_id) + + if not room: + # Huh, let's try and get the current state + try: + federation = self.hs.get_federation() + yield federation.get_state_for_room( + event.origin, event.room_id + ) + + hosts = yield self.store.get_joined_hosts_for_room( + event.room_id + ) + if self.hs.hostname in hosts: + try: + yield self.store.store_room( + event.room_id, + "", + is_public=False + ) + except: + pass + except: + logger.exception( + "Failed to get current state for room %s", + event.room_id + ) + if not backfilled: yield self.notifier.on_new_room_event(event, store_id) @@ -88,3 +116,53 @@ class FederationHandler(BaseHandler): logger.exception("Failed to persist event: %s", event) defer.returnValue(events) + + @log_function + @defer.inlineCallbacks + def do_invite_join(self, target_host, room_id, joinee, content): + federation = self.hs.get_federation() + + hosts = yield self.store.get_joined_hosts_for_room(room_id) + if self.hs.hostname in hosts: + # We are already in the room. + logger.debug("We're already in the room apparently") + defer.returnValue(False) + + # First get current state to see if we are already joined. + try: + yield federation.get_state_for_room(target_host, room_id) + + hosts = yield self.store.get_joined_hosts_for_room(room_id) + if self.hs.hostname in hosts: + # Oh, we were actually in the room already. + logger.debug("We're already in the room apparently") + defer.returnValue(False) + except Exception: + logger.exception("Failed to get current state") + + new_event = self.event_factory.create_event( + etype=InviteJoinEvent.TYPE, + target_host=target_host, + room_id=room_id, + user_id=joinee, + content=content + ) + + new_event.destinations = [target_host] + + yield federation.handle_new_event(new_event) + + store_id = yield self.store.persist_event(new_event) + self.notifier.on_new_room_event(new_event, store_id) + + try: + yield self.store.store_room( + event.room_id, + "", + is_public=False + ) + except: + pass + + + defer.returnValue(True) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 7ab881847d..6ecb6dd0e4 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -599,9 +599,9 @@ class RoomMemberHandler(BaseHandler): # that we are allowed to join when we decide whether or not we # need to do the invite/join dance. - room = yield self.store.get_room(room_id) + hosts = yield self.store.get_joined_hosts_for_room(room_id) - if room: + if self.hs.hostname in hosts: should_do_dance = False elif room_host: should_do_dance = True @@ -621,8 +621,15 @@ class RoomMemberHandler(BaseHandler): else: should_do_dance = False + have_joined = False + if should_do_dance: + handler = self.hs.get_handlers().federation_handler + have_joined = yield handler.do_invite_join( + room_host, room_id, event.user_id, event.content + ) + # We want to do the _do_update inside the room lock. - if not should_do_dance: + if not have_joined: logger.debug("Doing normal join") if do_auth: @@ -635,14 +642,6 @@ class RoomMemberHandler(BaseHandler): broadcast_msg=broadcast_msg, ) - if should_do_dance: - yield self._do_invite_join_dance( - room_id=room_id, - joinee=event.user_id, - target_host=room_host, - content=event.content, - ) - user = self.hs.parse_userid(event.user_id) self.distributor.fire( "user_joined_room", user=user, room_id=room_id @@ -748,32 +747,6 @@ class RoomMemberHandler(BaseHandler): membership=event.content["membership"] ) - @defer.inlineCallbacks - def _do_invite_join_dance(self, room_id, joinee, target_host, content): - logger.debug("Doing remote join dance") - - # do invite join dance - federation = self.hs.get_federation() - new_event = self.event_factory.create_event( - etype=InviteJoinEvent.TYPE, - target_host=target_host, - room_id=room_id, - user_id=joinee, - content=content - ) - - new_event.destinations = [target_host] - - yield self.store.store_room( - room_id, "", is_public=False - ) - - # yield self.state_handler.handle_new_event(event) - yield federation.handle_new_event(new_event) - yield federation.get_state_for_room( - target_host, room_id - ) - @defer.inlineCallbacks def _inject_membership_msg(self, room_id=None, source=None, target=None, membership=None): -- cgit 1.4.1