'Attempts to join the `joinee` to the room `room_id` via the
server `target_host`.
This first triggers a /make_join/ request that returns a partial
event that we can fill out and sign. This is then sent to the
remote server via /send_join/ which responds with the state at that
event and the auth_chains.
We suspend processing of any received events from this room until we
have finished processing the join.'

@log_function
@defer.inlineCallbacks
def do_invite_join(self, target_hosts, room_id, joinee, content):

    logger.debug('Joining    %s    to    %s', joinee, room_id)
    (origin, event) = (yield self._make_and_verify_event(target_hosts, room_id, joinee, 'join', content))
    assert (room_id not in self.room_queues)
    self.room_queues[room_id] = []
    (yield self.store.clean_room_for_join(room_id))
    handled_events = set()
    try:
        event = self._sign_event(event)
        try:
            target_hosts.remove(origin)
            target_hosts.insert(0, origin)
        except ValueError:
            pass
        ret = (yield self.replication_layer.send_join(target_hosts, event))
        origin = ret['origin']
        state = ret['state']
        auth_chain = ret['auth_chain']
        auth_chain.sort(key=(lambda e: e.depth))
        handled_events.update([s.event_id for s in state])
        handled_events.update([a.event_id for a in auth_chain])
        handled_events.add(event.event_id)
        logger.debug('do_invite_join    auth_chain:    %s', auth_chain)
        logger.debug('do_invite_join    state:    %s', state)
        logger.debug('do_invite_join    event:    %s', event)
        try:
            (yield self.store.store_room(room_id=room_id, room_creator_user_id='', is_public=False))
        except:
            pass
        (event_stream_id, max_stream_id) = (yield self._persist_auth_tree(origin, auth_chain, state, event))
        self.notifier.on_new_room_event(event, event_stream_id, max_stream_id, extra_users=[joinee])
        logger.debug('Finished    joining    %s    to    %s', joinee, room_id)
    finally:
        room_queue = self.room_queues[room_id]
        del self.room_queues[room_id]
        synapse.util.logcontext.preserve_fn(self._handle_queued_pdus)(room_queue)
    defer.returnValue(True)
