Esempio n. 1
0
void Server::externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId)
{
    // This function is always called from the main thread via signal/slot.

    try {
        QReadLocker roomsLocker(&roomsLock);
        QReadLocker clientsLocker(&clientsLock);

        Server_Room *room = rooms.value(roomId);
        if (!room) {
            qDebug() << "externalJoinGameCommandReceived: room id=" << roomId << "not found";
            throw Response::RespNotInRoom;
        }
        Server_AbstractUserInterface *userInterface = externalUsersBySessionId.value(sessionId);
        if (!userInterface) {
            qDebug() << "externalJoinGameCommandReceived: session id=" << sessionId << "not found";
            throw Response::RespNotInRoom;
        }

        ResponseContainer responseContainer(cmdId);
        Response::ResponseCode responseCode = room->processJoinGameCommand(cmd, responseContainer, userInterface);
        userInterface->sendResponseContainer(responseContainer, responseCode);
    } catch (Response::ResponseCode code) {
        Response response;
        response.set_cmd_id(cmdId);
        response.set_response_code(code);

        sendIsl_Response(response, serverId, sessionId);
    }
}
Esempio n. 2
0
IslInterface::~IslInterface()
{
	logger->logMessage("[ISL] session ended", this);
	
	flushOutputBuffer();
	
	// As these signals are connected with Qt::QueuedConnection implicitly,
	// we don't need to worry about them modifying the lists while we're iterating.
	
	server->roomsLock.lockForRead();
	QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
	while (roomIterator.hasNext()) {
		Server_Room *room = roomIterator.next().value();
		room->usersLock.lockForRead();
		QMapIterator<QString, ServerInfo_User_Container> roomUsers(room->getExternalUsers());
		while (roomUsers.hasNext()) {
			roomUsers.next();
			if (roomUsers.value().getUserInfo()->server_id() == serverId)
				emit externalRoomUserLeft(room->getId(), roomUsers.key());
		}
		room->usersLock.unlock();
	}
	server->roomsLock.unlock();
	
	server->clientsLock.lockForRead();
	QMapIterator<QString, Server_AbstractUserInterface *> extUsers(server->getExternalUsers());
	while (extUsers.hasNext()) {
		extUsers.next();
		if (extUsers.value()->getUserInfo()->server_id() == serverId)
			emit externalUserLeft(extUsers.key());
	}
	server->clientsLock.unlock();
}
Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc)
{
	if (authState == NotLoggedIn)
		return Response::RespLoginNeeded;
	
	// We don't need to check whether the user is logged in; persistent games should also work.
	// The client needs to deal with an empty result list.
	
	Response_GetGamesOfUser *re = new Response_GetGamesOfUser;
	server->roomsLock.lockForRead();
	QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
	while (roomIterator.hasNext()) {
		Server_Room *room = roomIterator.next().value();
		room->gamesLock.lockForRead();
		room->getInfo(*re->add_room_list(), false, true);
		QListIterator<ServerInfo_Game> gameIterator(room->getGamesOfUser(QString::fromStdString(cmd.user_name())));
		while (gameIterator.hasNext())
			re->add_game_list()->CopyFrom(gameIterator.next());
		room->gamesLock.unlock();
	}
	server->roomsLock.unlock();
	
	rc.setResponseExtension(re);
	return Response::RespOk;
}
void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
{
    QList<PlayerReference> gamesToJoin = server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
    
    server->roomsLock.lockForRead();
    for (int i = 0; i < gamesToJoin.size(); ++i) {
        const PlayerReference &pr = gamesToJoin.at(i);
        
        Server_Room *room = server->getRooms().value(pr.getRoomId());
        if (!room)
            continue;
        QReadLocker roomGamesLocker(&room->gamesLock);
        
        Server_Game *game = room->getGames().value(pr.getGameId());
        if (!game)
            continue;
        QMutexLocker gameLocker(&game->gameMutex);
        
        Server_Player *player = game->getPlayers().value(pr.getPlayerId());
        
        player->setUserInterface(this);
        playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
        
        game->createGameJoinedEvent(player, rc, true);
    }
    server->roomsLock.unlock();
}
Esempio n. 5
0
void Server::externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId)
{
    // This function is always called from the main thread via signal/slot.

    try {
        ResponseContainer responseContainer(cont.cmd_id());
        Response::ResponseCode finalResponseCode = Response::RespOk;

        QReadLocker roomsLocker(&roomsLock);
        Server_Room *room = rooms.value(cont.room_id());
        if (!room) {
            qDebug() << "externalGameCommandContainerReceived: room id=" << cont.room_id() << "not found";
            throw Response::RespNotInRoom;
        }

        QReadLocker roomGamesLocker(&room->gamesLock);
        Server_Game *game = room->getGames().value(cont.game_id());
        if (!game) {
            qDebug() << "externalGameCommandContainerReceived: game id=" << cont.game_id() << "not found";
            throw Response::RespNotInRoom;
        }

        QMutexLocker gameLocker(&game->gameMutex);
        Server_Player *player = game->getPlayers().value(playerId);
        if (!player) {
            qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found";
            throw Response::RespNotInRoom;
        }

        GameEventStorage ges;
        for (int i = cont.game_command_size() - 1; i >= 0; --i) {
            const GameCommand &sc = cont.game_command(i);
            qDebug() << "[ISL]" << QString::fromStdString(sc.ShortDebugString());

            Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges);

            if (resp != Response::RespOk)
                finalResponseCode = resp;
        }
        ges.sendToGame(game);

        if (finalResponseCode != Response::RespNothing) {
            player->playerMutex.lock();
            player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode);
            player->playerMutex.unlock();
        }
    } catch (Response::ResponseCode code) {
        Response response;
        response.set_cmd_id(cont.cmd_id());
        response.set_response_code(code);

        sendIsl_Response(response, serverId, sessionId);
    }
}
Esempio n. 6
0
int Server::getGamesCount() const
{
    int result = 0;
    QReadLocker locker(&roomsLock);
    QMapIterator<int, Server_Room *> roomIterator(rooms);
    while (roomIterator.hasNext()) {
        Server_Room *room = roomIterator.next().value();
        QReadLocker roomLocker(&room->gamesLock);
        result += room->getGames().size();
    }
    return result;
}
Esempio n. 7
0
void Server::externalRoomSay(int roomId, const QString &userName, const QString &message)
{
    // This function is always called from the main thread via signal/slot.
    QReadLocker locker(&roomsLock);
    
    Server_Room *room = rooms.value(roomId);
    if (!room) {
        qDebug() << "externalRoomSay: room id=" << roomId << "not found";
        return;
    }
    room->say(userName, message, false);
}
Esempio n. 8
0
void Server::externalRoomUserLeft(int roomId, const QString &userName)
{
    // This function is always called from the main thread via signal/slot.
    QReadLocker locker(&roomsLock);

    Server_Room *room = rooms.value(roomId);
    if (!room) {
        qDebug() << "externalRoomUserLeft: room id=" << roomId << "not found";
        return;
    }
    room->removeExternalUser(userName);
}
Esempio n. 9
0
void Server::externalRoomUserJoined(int roomId, const ServerInfo_User &userInfo)
{
    // This function is always called from the main thread via signal/slot.
    QReadLocker locker(&roomsLock);

    Server_Room *room = rooms.value(roomId);
    if (!room) {
        qDebug() << "externalRoomUserJoined: room id=" << roomId << "not found";
        return;
    }
    room->addExternalUser(userInfo);
}
Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc)
{
    if (authState == NotLoggedIn)
        return Response::RespLoginNeeded;

    if (rooms.contains(cmd.room_id()))
        return Response::RespContextError;

    QReadLocker serverLocker(&server->roomsLock);
    Server_Room *r = server->getRooms().value(cmd.room_id(), 0);
    if (!r)
        return Response::RespNameNotFound;

    QString roomPermission = r->getRoomPermission().toLower();
    if (roomPermission != "none"){
        if (roomPermission == "registered") {
            if (!(userInfo->user_level() & ServerInfo_User::IsRegistered))
                return Response::RespUserLevelTooLow;
        }

        if (roomPermission == "moderator"){
            if (!(userInfo->user_level() & ServerInfo_User::IsModerator))
                return Response::RespUserLevelTooLow;
        }

        if (roomPermission == "administrator"){
            if (!(userInfo->user_level() & ServerInfo_User::IsAdmin))
                return Response::RespUserLevelTooLow;
        }
    }

    r->addClient(this);
    rooms.insert(r->getId(), r);

    Event_RoomSay joinMessageEvent;
    joinMessageEvent.set_message(r->getJoinMessage().toStdString());
    joinMessageEvent.set_message_type(Event_RoomSay::Welcome);
    rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));

    QReadLocker chatHistoryLocker(&r->historyLock);
    QList<ServerInfo_ChatMessage> chatHistory = r->getChatHistory();
    ServerInfo_ChatMessage chatMessage;
    for (int i = 0; i < chatHistory.size(); ++i) {
        chatMessage = chatHistory.at(i);
        qDebug() << QString::fromStdString(chatMessage.message()).simplified();
        Event_RoomSay roomChatHistory;
        roomChatHistory.set_message(chatMessage.sender_name() + ": " + chatMessage.message());
        roomChatHistory.set_message_type(Event_RoomSay::ChatHistory);
        roomChatHistory.set_time_of(QDateTime::fromString(QString::fromStdString(chatMessage.time())).toMSecsSinceEpoch());
        rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(roomChatHistory));
    }

    Response_JoinRoom *re = new Response_JoinRoom;
    r->getInfo(*re->mutable_room_info(), true);

    rc.setResponseExtension(re);
    return Response::RespOk;
}
Esempio n. 11
0
void Server::externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo)
{
    // This function is always called from the main thread via signal/slot.
    QReadLocker locker(&roomsLock);

    Server_Room *room = rooms.value(roomId);
    if (!room) {
        qDebug() << "externalRoomGameListChanged: room id=" << roomId << "not found";
        return;
    }
    room->updateExternalGameList(gameInfo);
}
Esempio n. 12
0
void Server::externalRoomSay(int roomId, const QString &userName, const QString &message)
{
    // This function is always called from the main thread via signal/slot.
    QReadLocker locker(&roomsLock);

    Server_Room *room = rooms.value(roomId);
    if (!room) {
        qDebug() << "externalRoomSay: room id=" << roomId << "not found";
        return;
    }
    room->say(userName, message, false);

    getDatabaseInterface()->logMessage(0, userName, "ISL", message, Server_DatabaseInterface::MessageTargetIslRoom, room->getId(), room->getName());
}
Esempio n. 13
0
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
	if (authState == NotLoggedIn)
		return Response::RespLoginNeeded;
	
	QMap<int, QPair<int, int> > gameMap = getGames();
	if (!gameMap.contains(cont.game_id()))
		return Response::RespNotInRoom;
	const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());
	
	QReadLocker roomsLocker(&server->roomsLock);
	Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
	if (!room)
		return Response::RespNotInRoom;
	
	QReadLocker roomGamesLocker(&room->gamesLock);
	Server_Game *game = room->getGames().value(cont.game_id());
	if (!game) {
		if (room->getExternalGames().contains(cont.game_id())) {
			server->sendIsl_GameCommand(cont,
			                            room->getExternalGames().value(cont.game_id()).server_id(),
			                            userInfo->session_id(),
			                            roomIdAndPlayerId.first,
			                            roomIdAndPlayerId.second
			                            );
			return Response::RespNothing;
		}
		return Response::RespNotInRoom;
	}
	
	QMutexLocker gameLocker(&game->gameMutex);
	Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
	if (!player)
		return Response::RespNotInRoom;
	
	GameEventStorage ges;
	Response::ResponseCode finalResponseCode = Response::RespOk;
	for (int i = cont.game_command_size() - 1; i >= 0; --i) {
		const GameCommand &sc = cont.game_command(i);
		logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));
		
		Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);

		if (resp != Response::RespOk)
			finalResponseCode = resp;
	}
	ges.sendToGame(game);
	
	return finalResponseCode;
}
Esempio n. 14
0
void Server::externalUserLeft(const QString &userName)
{
    // This function is always called from the main thread via signal/slot.

    clientsLock.lockForWrite();
    Server_AbstractUserInterface *user = externalUsers.take(userName);
    externalUsersBySessionId.remove(user->getUserInfo()->session_id());
    clientsLock.unlock();

    QMap<int, QPair<int, int> > userGames(user->getGames());
    QMapIterator<int, QPair<int, int> > userGamesIterator(userGames);
    roomsLock.lockForRead();
    while (userGamesIterator.hasNext()) {
        userGamesIterator.next();
        Server_Room *room = rooms.value(userGamesIterator.value().first);
        if (!room)
            continue;

        QReadLocker roomGamesLocker(&room->gamesLock);
        Server_Game *game = room->getGames().value(userGamesIterator.key());
        if (!game)
            continue;

        QMutexLocker gameLocker(&game->gameMutex);
        Server_Player *player = game->getPlayers().value(userGamesIterator.value().second);
        if (!player)
            continue;

        player->disconnectClient();
    }
    roomsLock.unlock();

    delete user;

    Event_UserLeft event;
    event.set_name(userName.toStdString());

    SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
    clientsLock.lockForRead();
    for (int i = 0; i < clients.size(); ++i)
        if (clients[i]->getAcceptsUserListChanges())
            clients[i]->sendProtocolItem(*se);
    clientsLock.unlock();
    delete se;
}
Esempio n. 15
0
// This function must only be called from the thread this object lives in.
// The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock).
void Server_ProtocolHandler::prepareDestroy()
{
	if (deleted)
		return;
	deleted = true;
	
	QMapIterator<int, Server_Room *> roomIterator(rooms);
	while (roomIterator.hasNext())
		roomIterator.next().value()->removeClient(this);
	
	QMap<int, QPair<int, int> > tempGames(getGames());
	
	server->roomsLock.lockForRead();
	QMapIterator<int, QPair<int, int> > gameIterator(tempGames);
	while (gameIterator.hasNext()) {
		gameIterator.next();
		
		Server_Room *r = server->getRooms().value(gameIterator.value().first);
		if (!r)
			continue;
		r->gamesLock.lockForRead();
		Server_Game *g = r->getGames().value(gameIterator.key());
		if (!g) {
			r->gamesLock.unlock();
			continue;
		}
		g->gameMutex.lock();
		Server_Player *p = g->getPlayers().value(gameIterator.value().second);
		if (!p) {
			g->gameMutex.unlock();
			r->gamesLock.unlock();
			continue;
		}
		
		p->disconnectClient();
		
		g->gameMutex.unlock();
		r->gamesLock.unlock();
	}
	server->roomsLock.unlock();
	
	server->removeClient(this);
	
	deleteLater();
}
Esempio n. 16
0
Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc)
{
	if (authState == NotLoggedIn)
		return Response::RespLoginNeeded;
	
	if (rooms.contains(cmd.room_id()))
		return Response::RespContextError;
	
	QReadLocker serverLocker(&server->roomsLock);
	Server_Room *r = server->getRooms().value(cmd.room_id(), 0);
	if (!r)
		return Response::RespNameNotFound;
	
	r->addClient(this);
	rooms.insert(r->getId(), r);
	
	Event_RoomSay joinMessageEvent;
	joinMessageEvent.set_message(r->getJoinMessage().toStdString());
	rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));
	
	Response_JoinRoom *re = new Response_JoinRoom;
	r->getInfo(*re->mutable_room_info(), true);
	
	rc.setResponseExtension(re);
	return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoom &cmd, ResponseContainer &rc)
{
    if (authState == NotLoggedIn)
        return Response::RespLoginNeeded;

    if (rooms.contains(cmd.room_id()))
        return Response::RespContextError;

    QReadLocker serverLocker(&server->roomsLock);
    Server_Room *r = server->getRooms().value(cmd.room_id(), 0);
    if (!r)
        return Response::RespNameNotFound;

    QString roomPermission = r->getRoomPermission().toLower();
    if (roomPermission != "none"){
        if (roomPermission == "registered") {
            if (!(userInfo->user_level() & ServerInfo_User::IsRegistered))
                return Response::RespUserLevelTooLow;
        }

        if (roomPermission == "moderator"){
            if (!(userInfo->user_level() & ServerInfo_User::IsModerator))
                return Response::RespUserLevelTooLow;
        }

        if (roomPermission == "administrator"){
            if (!(userInfo->user_level() & ServerInfo_User::IsAdmin))
                return Response::RespUserLevelTooLow;
        }
    }

    r->addClient(this);
    rooms.insert(r->getId(), r);

    Event_RoomSay joinMessageEvent;
    joinMessageEvent.set_message(r->getJoinMessage().toStdString());
    rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));

    Response_JoinRoom *re = new Response_JoinRoom;
    r->getInfo(*re->mutable_room_info(), true);

    rc.setResponseExtension(re);
    return Response::RespOk;
}
ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandContainer *cont)
{
	if (authState == PasswordWrong)
		return RespLoginNeeded;
	
	if (rooms.contains(cmd->getRoomId()))
		return RespContextError;
	
	Server_Room *r = server->getRooms().value(cmd->getRoomId(), 0);
	if (!r)
		return RespNameNotFound;

	r->addClient(this);
	rooms.insert(r->getId(), r);
	
	enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage()));
	
	cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true)));
	return RespNothing;
}
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
    static QList<GameCommand::GameCommandType> antifloodCommandsWhiteList = QList<GameCommand::GameCommandType>()
        // draw/undo card draw (example: drawing 10 cards one by one from the deck)
        << GameCommand::DRAW_CARDS
        << GameCommand::UNDO_DRAW
        // create, delete arrows (example: targeting with 10 cards during an attack)
        << GameCommand::CREATE_ARROW
        << GameCommand::DELETE_ARROW
        // set card attributes (example: tapping 10 cards at once)
        << GameCommand::SET_CARD_ATTR
        // increment / decrement counter (example: -10 life points one by one)
        << GameCommand::INC_COUNTER
        // mulling lots of hands in a row
        << GameCommand::MULLIGAN
        // allows a user to sideboard without receiving flooding message
        << GameCommand::MOVE_CARD;

    if (authState == NotLoggedIn)
        return Response::RespLoginNeeded;

    QMap<int, QPair<int, int> > gameMap = getGames();
    if (!gameMap.contains(cont.game_id()))
        return Response::RespNotInRoom;
    const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());

    QReadLocker roomsLocker(&server->roomsLock);
    Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first);
    if (!room)
        return Response::RespNotInRoom;

    QReadLocker roomGamesLocker(&room->gamesLock);
    Server_Game *game = room->getGames().value(cont.game_id());
    if (!game) {
        if (room->getExternalGames().contains(cont.game_id())) {
            server->sendIsl_GameCommand(cont,
                                        room->getExternalGames().value(cont.game_id()).server_id(),
                                        userInfo->session_id(),
                                        roomIdAndPlayerId.first,
                                        roomIdAndPlayerId.second
                                        );
            return Response::RespNothing;
        }
        return Response::RespNotInRoom;
    }

    QMutexLocker gameLocker(&game->gameMutex);
    Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second);
    if (!player)
        return Response::RespNotInRoom;

    int commandCountingInterval = server->getCommandCountingInterval();
    int maxCommandCountPerInterval = server->getMaxCommandCountPerInterval();
    GameEventStorage ges;
    Response::ResponseCode finalResponseCode = Response::RespOk;
    for (int i = cont.game_command_size() - 1; i >= 0; --i) {
        const GameCommand &sc = cont.game_command(i);
        logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));

        if (commandCountingInterval > 0) {
            int totalCount = 0;
            if (commandCountOverTime.isEmpty())
                commandCountOverTime.prepend(0);

            if(!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType) getPbExtension(sc)))
                ++commandCountOverTime[0];

            for (int i = 0; i < commandCountOverTime.size(); ++i)
                totalCount += commandCountOverTime[i];

            if (totalCount > maxCommandCountPerInterval)
                return Response::RespChatFlood;
        }

        Response::ResponseCode resp = player->processGameCommand(sc, rc, ges);

        if (resp != Response::RespOk)
            finalResponseCode = resp;
    }
    ges.sendToGame(game);

    return finalResponseCode;
}
Esempio n. 20
0
void IslInterface::initServer()
{
	socket->setSocketDescriptor(socketDescriptor);
	
	logger->logMessage(QString("[ISL] incoming connection: %1").arg(socket->peerAddress().toString()));
	
	QList<ServerProperties> serverList = server->getServerList();
	int listIndex = -1;
	for (int i = 0; i < serverList.size(); ++i)
		if (serverList[i].address == socket->peerAddress()) {
			listIndex = i;
			break;
		}
	if (listIndex == -1) {
		logger->logMessage(QString("[ISL] address %1 unknown, terminating connection").arg(socket->peerAddress().toString()));
		deleteLater();
		return;
	}
	
	socket->startServerEncryption();
	if (!socket->waitForEncrypted(5000)) {
		QList<QSslError> sslErrors(socket->sslErrors());
		if (sslErrors.isEmpty())
			qDebug() << "[ISL] SSL handshake timeout, terminating connection";
		else
			qDebug() << "[ISL] SSL errors:" << sslErrors;
		deleteLater();
		return;
	}
	
	if (serverList[listIndex].cert == socket->peerCertificate())
		logger->logMessage(QString("[ISL] Peer authenticated as " + serverList[listIndex].hostname));
	else {
		logger->logMessage(QString("[ISL] Authentication failed, terminating connection"));
		deleteLater();
		return;
	}
	serverId = serverList[listIndex].id;
	
	Event_ServerCompleteList event;
	event.set_server_id(server->getServerId());
	
	server->clientsLock.lockForRead();
	QMapIterator<QString, Server_ProtocolHandler *> userIterator(server->getUsers());
	while (userIterator.hasNext())
		event.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(true, true));
	server->clientsLock.unlock();
	
	server->roomsLock.lockForRead();
	QMapIterator<int, Server_Room *> roomIterator(server->getRooms());
	while (roomIterator.hasNext()) {
		Server_Room *room = roomIterator.next().value();
		room->usersLock.lockForRead();
		room->gamesLock.lockForRead();
		room->getInfo(*event.add_room_list(), true, true, false, false);
	}
	
	IslMessage message;
	message.set_message_type(IslMessage::SESSION_EVENT);
	SessionEvent *sessionEvent = message.mutable_session_event();
	sessionEvent->GetReflection()->MutableMessage(sessionEvent, event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(event);
	
	server->islLock.lockForWrite();
	if (server->islConnectionExists(serverId)) {
		qDebug() << "[ISL] Duplicate connection to #" << serverId << "terminating connection";
		deleteLater();
	} else {
		transmitMessage(message);
		server->addIslInterface(serverId, this);
	}
	server->islLock.unlock();
	
	roomIterator.toFront();
	while (roomIterator.hasNext()) {
		roomIterator.next();
		roomIterator.value()->gamesLock.unlock();
		roomIterator.value()->usersLock.unlock();
	}
	server->roomsLock.unlock();
}