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
@@ -749,32 +748,6 @@ class RoomMemberHandler(BaseHandler):
)
@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):
# TODO this should be a different type of message, not m.text
|