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();
}
예제 #2
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);
    }
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
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();
}
예제 #6
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;
}
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;
}