コード例 #1
0
ファイル: caching.py プロジェクト: Dermogod/ForcAD
def cache_last_stolen(team_id: int, round: int, pipeline):
    """Put stolen flags for attacker team from last "flag_lifetime" rounds to cache

        :param team_id: attacker team id
        :param round: current round
        :param pipeline: redis connection to add command to
    Just adds commands to pipeline stack, don't forget to execute afterwards
    """
    game_config = config.get_game_config()
    conn = storage.get_db_pool().getconn()
    curs = conn.cursor()

    curs.execute(_SELECT_LAST_STOLEN_TEAM_FLAGS_QUERY,
                 (round - game_config['flag_lifetime'], team_id))

    flags = curs.fetchall()
    curs.close()
    storage.get_db_pool().putconn(conn)

    pipeline.delete(f'team:{team_id}:cached:stolen',
                    f'team:{team_id}:stolen_flags')
    if flags:
        pipeline.sadd(f'team:{team_id}:stolen_flags',
                      *[flag_id for flag_id, in flags])
    pipeline.set(f'team:{team_id}:cached:stolen', 1)
コード例 #2
0
ファイル: caching.py プロジェクト: Dermogod/ForcAD
def cache_last_flags(round: int, pipeline):
    """Put all generated flags from last "flag_lifetime" rounds to cache

        :param round: current round
        :param pipeline: redis connection to add command to

    Just adds commands to pipeline stack, don't forget to execute afterwards
    """
    game_config = config.get_game_config()
    conn = storage.get_db_pool().getconn()
    curs = conn.cursor(cursor_factory=extras.DictCursor)

    curs.execute(_SELECT_ALL_LAST_FLAGS_QUERY,
                 (round - game_config['flag_lifetime'], ))

    flags = curs.fetchall()
    curs.close()
    storage.get_db_pool().putconn(conn)

    pipeline.delete('flags:cached')
    flag_models = []
    for flag_dict in flags:
        flag = helplib.models.Flag.from_dict(flag_dict)
        flag_models.append(flag)

    if flag_models:
        pipeline.delete(*[
            f'team:{flag.team_id}:task:{flag.task_id}:round_flags:{flag.round}'
            for flag in flag_models
        ])

    for flag in flag_models:
        pipeline.set(f'flag:id:{flag.id}', flag.to_json())
        pipeline.set(f'flag:str:{flag.flag}', flag.to_json())
        pipeline.sadd(
            f'team:{flag.team_id}:task:{flag.task_id}:round_flags:{flag.round}',
            flag.id)

    pipeline.set('flags:cached', 1)
コード例 #3
0
def startup(**_kwargs):
    """Task to run on start of celery, schedules game start"""
    game_config = config.get_game_config()

    logger.info(f'Received game config: {game_config}')

    start_game.apply_async(eta=game_config['start_time'], )

    round = storage.game.get_real_round()
    if not round or round == -1:
        storage.caching.cache_teamtasks(round=0)

        game_state = storage.game.get_game_state(round=0)
        if not game_state:
            logger.warning('Initial game_state missing')
        else:
            with storage.get_redis_storage().pipeline(
                    transaction=True) as pipeline:
                logger.info(
                    f"Initializing game_state with {game_state.to_dict()}")
                pipeline.set('game_state', game_state.to_json())
                pipeline.publish('scoreboard', game_state.to_json())
                pipeline.execute()
コード例 #4
0
def get_action(put_ok, team_json, task_json, round):
    """Run "get" checker action

        :param put_ok: boolean passed by "put" action in chain to indicate successful check and put
        :param team_json: json-dumped team
        :param task_json: json-dumped task
        :param round: current round

        If "check" or "put" actions fail, get is not run.

        It runs `task.gets` times, each time a flag is chosen randomly from last "flag_lifetime" rounds
    """
    if not put_ok:
        return False

    team = models.Team.from_json(team_json)
    task = models.Task.from_json(task_json)

    flag_lifetime = config.get_game_config()['flag_lifetime']

    rounds_to_check = list(
        set(max(1, round - x) for x in range(0, flag_lifetime)))
    random.shuffle(rounds_to_check)
    rounds_to_check = rounds_to_check[:task.gets]

    logger.info(
        f'Running GET on rounds {rounds_to_check} for team {team.id} task {task.id}'
    )

    checker_verdict = models.CheckerVerdict(
        status=TaskStatus.UP,
        public_message='',
        private_message='',
        command=[],
    )

    for get_round in rounds_to_check:
        flag = storage.flags.get_random_round_flag(
            team_id=team.id,
            task_id=task.id,
            round=get_round,
            current_round=round,
        )

        if not flag:
            checker_verdict.status = TaskStatus.CORRUPT
            checker_verdict.private_message = f'No flags from round {get_round}'
            checker_verdict.public_message = f'Could not get flag'
        else:
            checker_verdict = checkers.run_get_command(
                checker_path=task.checker,
                env_path=task.env_path,
                host=team.ip,
                flag=flag,
                team_name=team.name,
                timeout=task.checker_timeout,
                logger=logger,
            )

        if checker_verdict.status != TaskStatus.UP:
            break

    storage.tasks.update_task_status(
        task_id=task.id,
        team_id=team.id,
        checker_verdict=checker_verdict,
        round=round,
    )

    return checker_verdict.status == TaskStatus.UP
コード例 #5
0
ファイル: init_db.py プロジェクト: Dermogod/ForcAD
def run():
    conn = storage.get_db_pool().getconn()
    curs = conn.cursor()

    create_query_path = os.path.join(SCRIPTS_DIR, 'create_query.sql')
    create_query = open(create_query_path).read()
    curs.execute(create_query)

    curs.execute(_CONFIG_INITIALIZATION_QUERY, (0, 0))

    teams_config = config.get_teams_config()
    teams = []

    for team_conf in teams_config:
        team_token = secrets.token_hex(8)
        team = models.Team(id=None, **team_conf, token=team_token)
        curs.execute(_TEAM_INSERT_QUERY, (team.name, team.ip, team_token))
        team.id, = curs.fetchone()
        teams.append(team)

    tasks_config = config.get_tasks_config()
    tasks = []

    game_config = config.get_game_config()
    global_env_path = game_config['env_path']
    checkers_path = game_config['checkers_path']
    global_default_score = game_config['default_score']

    for task_conf in tasks_config:
        if 'env_path' not in task_conf:
            task_conf['env_path'] = global_env_path

        if 'default_score' not in task_conf:
            task_conf['default_score'] = global_default_score

        task_conf['checker'] = os.path.join(checkers_path,
                                            task_conf['checker'])

        task = models.Task(id=None, **task_conf)
        curs.execute(_TASK_INSERT_QUERY, (
            task.name,
            task.checker,
            task.gets,
            task.puts,
            task.places,
            task.checker_timeout,
            task.env_path,
            int(task.checker_returns_flag_id),
        ))
        task.id, = curs.fetchone()
        tasks.append(task)

    for team in teams:
        for task in tasks:
            curs.execute(_TEAMTASK_INSERT_QUERY,
                         (task.id, team.id, 0, task.default_score, -1))

    conn.commit()
    curs.close()
    storage.get_db_pool().putconn(conn)

    storage.caching.cache_teamtasks(round=0)
    game_state = storage.game.get_game_state(round=0)
    with storage.get_redis_storage().pipeline(transaction=True) as pipeline:
        pipeline.set('game_state', game_state.to_json())
        pipeline.publish('scoreboard', game_state.to_json())
        pipeline.execute()
コード例 #6
0
ファイル: celery.py プロジェクト: Dermogod/ForcAD
from celery import Celery

import config

celery_config = config.get_celery_config()

app = Celery(
    __name__,
    include=[
        'celery_tasks.tasks',
    ],
)

game_config = config.get_game_config()

app.conf.beat_schedule = {
    'process_round': {
        'task': 'celery_tasks.tasks.process_round',
        'schedule': game_config['round_time'],
    },
}

app.conf.update(celery_config)