'Creates a new room.
Args:
requester (Requester): The user who requested the room creation.
config (dict) : A dict of configuration options.
Returns:
The new room ID.
Raises:
SynapseError if the room ID couldn\'t be stored, or something went
horribly wrong.'

@defer.inlineCallbacks
def create_room(self, requester, config, ratelimit=True):

    user_id = requester.user.to_string()
    if ratelimit:
        (yield self.ratelimit(requester))
    if ('room_alias_name' in config):
        for wchar in string.whitespace:
            if (wchar in config['room_alias_name']):
                raise SynapseError(400, 'Invalid    characters    in    room    alias')
        room_alias = RoomAlias.create(config['room_alias_name'], self.hs.hostname)
        mapping = (yield self.store.get_association_from_room_alias(room_alias))
        if mapping:
            raise SynapseError(400, 'Room    alias    already    taken')
    else:
        room_alias = None
    invite_list = config.get('invite', [])
    for i in invite_list:
        try:
            UserID.from_string(i)
        except:
            raise SynapseError(400, ('Invalid    user_id:    %s' % (i,)))
    invite_3pid_list = config.get('invite_3pid', [])
    visibility = config.get('visibility', None)
    is_public = (visibility == 'public')
    attempts = 0
    room_id = None
    while (attempts < 5):
        try:
            random_string = stringutils.random_string(18)
            gen_room_id = RoomID.create(random_string, self.hs.hostname)
            (yield self.store.store_room(room_id=gen_room_id.to_string(), room_creator_user_id=user_id, is_public=is_public))
            room_id = gen_room_id.to_string()
            break
        except StoreError:
            attempts += 1
    if (not room_id):
        raise StoreError(500, "Couldn't    generate    a    room    ID.")
    if room_alias:
        directory_handler = self.hs.get_handlers().directory_handler
        (yield directory_handler.create_association(user_id=user_id, room_id=room_id, room_alias=room_alias, servers=[self.hs.hostname]))
    preset_config = config.get('preset', (RoomCreationPreset.PRIVATE_CHAT if (visibility == 'private') else RoomCreationPreset.PUBLIC_CHAT))
    raw_initial_state = config.get('initial_state', [])
    initial_state = OrderedDict()
    for val in raw_initial_state:
        initial_state[(val['type'], val.get('state_key', ''))] = val['content']
    creation_content = config.get('creation_content', {})
    msg_handler = self.hs.get_handlers().message_handler
    room_member_handler = self.hs.get_handlers().room_member_handler
    (yield self._send_events_for_new_room(requester, room_id, msg_handler, room_member_handler, preset_config=preset_config, invite_list=invite_list, initial_state=initial_state, creation_content=creation_content, room_alias=room_alias, power_level_content_override=config.get('power_level_content_override', {})))
    if ('name' in config):
        name = config['name']
        (yield msg_handler.create_and_send_nonmember_event(requester, {'type': EventTypes.Name, 'room_id': room_id, 'sender': user_id, 'state_key': '', 'content': {'name': name}}, ratelimit=False))
    if ('topic' in config):
        topic = config['topic']
        (yield msg_handler.create_and_send_nonmember_event(requester, {'type': EventTypes.Topic, 'room_id': room_id, 'sender': user_id, 'state_key': '', 'content': {'topic': topic}}, ratelimit=False))
    content = {}
    is_direct = config.get('is_direct', None)
    if is_direct:
        content['is_direct'] = is_direct
    for invitee in invite_list:
        (yield room_member_handler.update_membership(requester, UserID.from_string(invitee), room_id, 'invite', ratelimit=False, content=content))
    for invite_3pid in invite_3pid_list:
        id_server = invite_3pid['id_server']
        address = invite_3pid['address']
        medium = invite_3pid['medium']
        (yield self.hs.get_handlers().room_member_handler.do_3pid_invite(room_id, requester.user, medium, address, id_server, requester, txn_id=None))
    result = {'room_id': room_id}
    if room_alias:
        result['room_alias'] = room_alias.to_string()
        (yield directory_handler.send_room_alias_update_event(requester, user_id, room_id))
    defer.returnValue(result)
