Exemple #1
0
    async def EquipItem(self, instance_id: int32):
        item_inst = self.Items.get(instance_id, None)

        if item_inst is None:            return \
WARN_MSG(f"There is no item instance with id={instance_id}")

        item_info = ItemsCatalog.get_by("Name", item_inst['Name'])

        if item_info is None:            return \
WARN_MSG(f"There is no item named {item_inst['Name']}")

        slot_id = item_info['CompatibleSlot']

        with Sync(self.Equipment):
            self.Equipment[slot_id] = instance_id
Exemple #2
0
    def terminate(self):
        INFO_MSG(f"Service {self.get_class_name()} going to be stopped")

        def on_terminate(proc):
            process_info = self.processes.get(proc.pid)
            status = proc.status()
            WARN_MSG(
                "Process did't terminated after timeout. pid: %s, status: %s, info: %s",
                proc.pid, status, process_info)

        processes = []
        for pid, info in self.processes.items():
            process = psutil.Process(pid)
            processes.append(process)
            process.terminate()
            INFO_MSG(
                f"Service {self.get_class_name()}. Send terminate to {info['name']}, status: {process.status()}, pid_exists: {psutil.pid_exists(pid)}"
            )

        if processes:
            try:
                from time import sleep
                # sleep(5)
                # for i in processes:
                #     INFO_MSG(f"1 Service {self.get_class_name()}. -- {i.pid} --, status: {i.status()}, pid_exists: {psutil.pid_exists(i.pid)}")
                gone, alive = psutil.wait_procs([
                    i for i in processes if i.status() != psutil.STATUS_ZOMBIE
                ],
                                                timeout=60,
                                                callback=on_terminate)
                # todo: Some strange sings here
            except Exception as e:
                WARN_MSG(f"Service {self.get_class_name()} exception {e}")
        INFO_MSG(f"Service {self.get_class_name()} is stopped")
        sys.exit(0)
Exemple #3
0
    def __run__(cls, *args, **kwargs):
        Globals.access_token = Access().register_access(
            "SUPER INTERNAL ACCESS", AccessLevel.Internal)
        Globals.service_name = cls.__name__ + CommandLine.get_arguments(
        ).postfix
        service_instance = cls(*args, **kwargs)
        Globals.this_service = service_instance

        signal.signal(signal.SIGTERM, service_instance.sigterm_handler)
        # signal.signal(signal.SIGBREAK, service_instance.sigterm_handler)
        signal.signal(signal.SIGINT, service_instance.sigterm_handler)

        try:
            asyncio.get_event_loop().run_until_complete(
                service_instance)  # this calls __await__
            asyncio.get_event_loop().run_until_complete(
                service_instance.done())
            asyncio.get_event_loop().run_forever()
        except KeyboardInterrupt:
            INFO_MSG("Preparing to shut down service...")
        except Exception as exc:
            from traceback import print_exc
            ERROR_MSG("Exception raised:", exc)
            print_exc()
            INFO_MSG("Press enter to continue")
            input()
            print("What's your name?\n> ", end="")
            name = input()
            print(f"{name}, how did you come to this?\n> ", end="")
            reason = input()
            WARN_MSG(
                f'The program has been stopped, the {name} provoked an error, and says: "{reason}". Dismiss him'
            )
Exemple #4
0
    def on_service_connection_lost(self, process: subprocess.Popen,
                                   connection):
        try:
            process.wait(1.0)
        except subprocess.TimeoutExpired:
            WARN_MSG(
                f"Something went wrong with process {process.pid}. Timeout expired"
            )
            return

        if process.returncode:
            WARN_MSG(
                f"Process {process.pid} has been disconnected with return code {process.returncode} ({get_retcode_descr(process.returncode)}) "
            )
        else:
            WARN_MSG(f"Process {process.pid} just disconnected")
Exemple #5
0
    async def enqueue_player(self, session):
        """ Добавить в очередь игрока
            Запускает матч, если список игроков заполнен
            @param session: сессия игрока
            @param character_id: ИД персонажа
        """
        INFO_MSG(f"Enqueueing player {session}")
        request_result = EReqGameResponse.Wait
        if self.fulfilled:
            WARN_MSG(f"Can't enqueue {session}. Game is fulfilled")
            return EReqGameResponse.Denied
        self.players[session] = GamePlayerInfo(session=session)
        session.ue4client.add_lost_callback(
            partial(self.on_client_dropped, session))
        # Начать выполнение матча. Можно только если команда заполнена и матч на данный момент не выполняется
        if self.fulfilled and not self.performing:
            asyncio.Task(self.perform())

        # Допустить игрока (дополнительного игрока, для восполнения) в матч (можно только если уже начат)
        if self.started:
            await self.accept_player_to_started_game(session,
                                                     self.players[session])
            request_result = EReqGameResponse.Success

        return request_result
Exemple #6
0
    def send_method_call(self, method_index, future_id, *args, **kwargs):
        if not self:
            WARN_MSG("Call to invalid mailbox %s" % self, depth=1)
            return

        method_info = self.entity_info.get_method(self.context_name,
                                                  method_index)
        params, _ = method_info.signature
        name = method_info.name

        serialized_params = BinarySerialization()

        for param_index, (param_name, param_type) in enumerate(params):
            param = param_type.instantiate(args[param_index])
            serialized_params << param.serialize()

        serialized_call = BinarySerialization()
        serialized_call << self.remote_id
        serialized_call << Globals.generator_signature
        serialized_call << method_index
        serialized_call << future_id
        serialized_call << Globals.access_token
        serialized_call << serialized_params

        message = BinarySerialization()
        message << ConnectionMessageTypes.rmi_call
        message << serialized_call

        self.send_data(message.get_archive())
Exemple #7
0
    async def FindUserForLogin(self, username: FString, password: FString) -> (ELoginResult, int32, uint8, int32, FDateTime):
        """
        Поиск пользователя для логина
        @param username: имя
        @param password: хэш пароля
        @return: успех, ИД, доступ, ДБИД
        """
        res = await self.driver.exec_raw(""" SELECT * 
                                             FROM public.users 
                                             WHERE LOWER(unique_name)=LOWER(%s); 
                                         """, username)

        for row in res:
            id, _, __, mail, pass_hash, salt, access, dbid, reg_time, confirmed = get_rows(row, 10)

            # final_hash = bcrypt.hashpw(password.encode(), salt.encode()).decode()
            # if pass_hash == final_hash:
            #     if not confirmed:
            #         WARN_MSG(f"User {username} is unconfirmed")
            #         return ELoginResult.Unconfirmed, 0, 0, 0, FDateTime(0, 0, 0)
            #
            #     res.close()
            return ELoginResult.Success, id, access, dbid, reg_time

        WARN_MSG(f"User {username} not found or wrong password")

        return ELoginResult.NotExists, 0, 0, 0, FDateTime.invalid()
Exemple #8
0
    async def async_method_caller(self, method_index, *args, **kwargs):
        if not self:            return \
   WARN_MSG("Awaiting call to invalid mailbox %s" % self, depth=1)

        future_data = FuturesManager().new(self, method_index)
        self.send_method_call(method_index, future_data['future_id'], *args)
        return await future_data['future']
Exemple #9
0
 def rollback(self, reason):
     WARN_MSG("rolling back, reason", reason)
     for property_name, (
             context,
             serialized_value) in self.serialized_variables.items():
         T = context.properties[property_name].prop_type
         ds = T.deserialize(serialized_value)
         setattr(context, property_name, ds)
         getattr(context, property_name).replicate()
Exemple #10
0
 def return_back_player(self, session):
     if session in self.players:
         asyncio.Task(
             self.accept_player_to_started_game(session,
                                                self.players[session],
                                                player_returned=True))
         return True
     WARN_MSG("Failed to return back player")
     return False
Exemple #11
0
 def has_future(self, future_id, remote_entity_id, method_index):
     future_dict = self.futures.get(future_id, None)
     if future_dict is not None:
         if future_dict['method_id'] == method_index and future_dict[
                 'mailbox'].remote_id == remote_entity_id:
             return True
     WARN_MSG(
         "Unable to get future with id %i, entity id %i and method index %i"
         % (future_id, remote_entity_id, method_index))
     return False
Exemple #12
0
def ensure_locked(*vars):
    """ Checks the all variables are locked (by transaction) and returns true. 
        False otherwise and shows warning about unlocked variables
    """
    result = all([var.locked for var in vars])
    if not result:
        WARN_MSG("This variables not locked: [%s]" %
                 ", ".join(var.property_name
                           for var in vars if not var.locked),
                 depth=1)
    return result
Exemple #13
0
def reduce_classes_list(lst, context_name):
    from Core.Entity import Entity
    for i, item in enumerate(lst):
        if issubclass(item, Entity):
            lst[i] = make_mailbox_proxy(context_name, item.__name__)

        if item in pythonic_types_mapping:
            WARN_MSG("Used python type '%s' instead '%s' (replaced)" %
                     (item.__name__, pythonic_types_mapping[item].__name__),
                     depth=2,
                     warning_id="TYPE_NEGLECT")
            lst[i] = pythonic_types_mapping[item]
Exemple #14
0
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        do_not_raise_exc = True

        if exc_type is None:
            new_variables = TArray[FPropertyInfo]()
            for context, varname in self.vars:
                var = getattr(context, varname)
                info = FPropertyInfo(EntityDBID=context.dbid,
                                     EntityClass=context.__class__.__name__,
                                     PropertyName=var.property_name,
                                     PropertyTypeName=var.get_type_name(),
                                     SerializedValue=var.serialize())
                new_variables.append(info)
            success = await Globals.this_service.db.UpdateVariablesTransactionally(
                self.old_variables, new_variables)
            if success:
                self.unlock_all()
                INFO_MSG("%s done" % self, depth=1)
                Replication.__exit__(self, exc_type, exc_val, exc_tb)
            else:
                self.rollback("DB error")
                self.unlock_all()
                ERROR_MSG(
                    "%s failed, because values in database not actual. Variables rolled back"
                    % self,
                    depth=1)
                raise TransactionError("Variables changed outside transaction")
        elif exc_type == TransactionExitException:
            self.rollback("Interrupted")
            self.unlock_all()
            do_not_raise_exc = True
            WARN_MSG(
                "Transaction %s interrupted from code. Variables rolled back" %
                self,
                depth=1)
        else:
            self.rollback("Code error")
            self.unlock_all()
            do_not_raise_exc = False
            ERROR_MSG(
                "%s failed, because errors in code. Variables rolled back" %
                self,
                depth=1)

        # for context, varname in self.vars:
        #     var = getattr(context, varname)
        #     if var.locked:
        #         var.unlock()

        return do_not_raise_exc
Exemple #15
0
    async def Synchronize(self):
        """ Синхронизировать ( типы ) """
        for T in TypeBase.all_types['types'].values():
            if issubclass(T, StructBase) and T is not StructBase:
                d = dict()
                for column_name, column_type in T.fields:
                    d[column_name] = column_type.__name__
                await self.driver.exec_raw("""  INSERT INTO public.types (type_name, type_data) VALUES ('{0}', '{1}')
                                                ON CONFLICT (type_name) DO
                                                UPDATE SET type_data = '{1}'::jsonb;""".format(T.__name__, json.dumps(d)))
        self.types = await self.get_types()

        classes = dict()
        result = await self.driver.exec_raw("""  SELECT * FROM classes; """)
        for r in result:
            class_name, data = r[0], r[1]
            classes[class_name] = data

        reconstructed_classes_info = dict()
        result = await self.driver.exec_raw("""  SELECT * FROM entities; """)

        for r in result:
            dbid, class_name = r[0], r[1]
            res = await self.driver.exec_raw("""  SELECT * FROM "class_{class_name}" WHERE db_id = {dbid} 
                                             """.format(class_name=class_name, dbid=dbid))
            class_data = classes[class_name]
            dictionary = dict()
            for r in res:
                for field_name, field_type in class_data.items():
                    for key, value in r.items():
                        T = TypeBase.find_type(field_type)
                        if T is not None:
                            if field_name == key:
                                dictionary[field_name] = reconstruct(T, value)
            reconstructed_classes_info[(dbid, class_name)] = dictionary

        for (dbid, class_name), class_info in reconstructed_classes_info.items():
            lst = list()
            for key, value in class_info.items():
                lst.append('"%s" = %s' % (key, pg_str(value)))
            update_str = ", ".join(lst)
            if lst:
                await self.driver.exec_raw("""  UPDATE "class_{class_name}" SET {update_str} WHERE db_id = {db_id};
                                           """.format(class_name=class_name, db_id=dbid, update_str=update_str))
            else:
                WARN_MSG(f"There are no '{class_name}' entry with dbid {dbid}")
                if ConfigGlobals.ClearMissingEntitiesDBIDs:
                    await self.driver.exec_raw(""" DELETE FROM entities WHERE db_id = {db_id};
                                               """.format(db_id=dbid))
Exemple #16
0
    def destroy_game(self, game_to_destroy):
        INFO_MSG(f"{game_to_destroy}")
        for games in self.games.values():
            for game in games:
                if game.is_subgame(game_to_destroy):
                    game.reset()
                    for player_session in game_to_destroy.players:
                        self.free_player(player_session)
                    return

            if game_to_destroy in games:
                games.remove(game_to_destroy)
                for player_session in game_to_destroy.players:
                    self.free_player(player_session)
                return
        WARN_MSG(f"Cannot destroy game {game_to_destroy}, not found")
Exemple #17
0
def get_citizens_with_ability_names_by_ids_and_ability_type(
        city, citizens_ids, ability_type_name,
        building_name) -> Dict[str, List[FCitizen]]:
    result = dict()

    for cid in citizens_ids:
        if cid not in city.Citizens:
            WARN_MSG(f"Failed to get citizen with id {cid}")
            continue
        citizen = city.Citizens[cid]
        for ability_name, ability_experience in citizen.Abilities.items():
            ability_info = CitizenAbilities.get_by("Name", ability_name)
            if ability_info[
                    'AbilityType'] == ability_type_name and building_name in ability_info[
                        'BuildingTypes']:
                if ability_name not in result:
                    result[ability_name] = list()
                result[ability_name].append(citizen)
    return result
Exemple #18
0
    async def FindUserForLoginWithoutPassword(self, username: FString) -> (ELoginResult, int32, uint8, int32, FDateTime):
        """
        Поиск пользователя для логина
        @param username: имя
        @param password: хэш пароля
        @return: успех, ИД, доступ, ДБИД
        """
        res = await self.driver.exec_raw(""" SELECT id, auth, account_dbid, register_date, confirmed 
                                             FROM public.users 
                                             WHERE LOWER(unique_name)=LOWER(%s); 
                                         """, username)

        for row in res:
            id, access, dbid, reg_time, confirmed = get_rows(row, 5)

            return ELoginResult.Success, id, access, dbid, reg_time

        WARN_MSG(f"User {username} not found or wrong password")

        return ELoginResult.NotExists, 0, 0, 0, FDateTime.invalid()
Exemple #19
0
    async def ConfirmUser(self, digest: FString) -> (Bool, FString):
        unconfirmeds = await self.driver.exec_raw(""" SELECT * FROM public.users_uncofirmed WHERE digest=%s; """, digest)

        for unconfirmed_user in unconfirmeds:
            id, digest = get_rows(unconfirmed_user, 2)

            users = await self.driver.exec_raw(""" SELECT unique_name FROM public.users WHERE id=%s; """, id)

            for user in users:
                await self.driver.exec_raw(""" UPDATE public.users 
                                               SET confirmed = TRUE 
                                               WHERE id=%s; 
                                               
                                               DELETE FROM users_uncofirmed WHERE id=%s; 
                                           """, id, id)
                username = user[0]
                INFO_MSG(f"User {username} confirmed")
                return True, username
            else:
                WARN_MSG(f"No user with id={id} and digest={digest}")
        return False, ""
Exemple #20
0
 def cmd(self, cmd):
     if self.dedicated_server:
         self.dedicated_server.RunConsoleCommand(cmd)
     else:
         WARN_MSG("Can't execute command while server loading")
Exemple #21
0
    async def CreateClassTable(self, class_name: FString, fields: TMap[FString, FString]):
        """
        Создать таблицу класса
        @param class_name: имя класса
        @param fields: поля {имя: тип}
        """
        INFO_MSG(f"Create class table {class_name}, {fields}")
        # await self.driver.exec_raw(""" DROP TABLE IF EXISTS public.Class_{0}; """.format(class_name))

        fields_substitute = str()
        for field_name, field_typedata in fields.items():
            T = self.find_type(field_typedata)
            pg_spec = T.pg_spec if T else 'INTEGER'
            default = ConfigurationGenerator().generated_entities_info.get_by_name(class_name).get_property('base', field_name).default

            fields_substitute += ', "%s" %s DEFAULT %s' % (field_name, pg_spec, pg_str(default))

        self.username = None

        current_data = await self.driver.exec_raw("""  SELECT class_data 
                                                       FROM public.classes 
                                                       WHERE class_name='{0}';
                                                  """.format(class_name))
        for c in current_data:
            r = c['class_data']
            deleted_columns = list()
            new_columns = list()
            changed_columns = list()
            alter_strings = list()
            for column_name, column_type in fields.items():
                T = self.find_type(column_type)
                pg_spec = T.pg_spec if T else 'INTEGER'
                default = ConfigurationGenerator().generated_entities_info.get_by_name(class_name).get_property('base', column_name).default
                default = pg_str(default)

                if column_name not in r:
                    new_columns.append((column_name, column_type))
                    alter_strings.append("ADD COLUMN {0} {1} DEFAULT {2}".format(column_name, pg_spec, default))
                elif column_name in r and r[column_name] != column_type:
                    changed_columns.append((column_name, r[column_name], column_type))
                    alter_strings.append("ALTER COLUMN {0} TYPE {1}, ALTER COLUMN {0} SET DEFAULT {2}".format(column_name, pg_spec, default))

            for column_name, column_type in r.items():
                if column_name not in fields:
                    alter_strings.append("DROP COLUMN {0}".format(column_name))
                    deleted_columns.append(column_name)

            if deleted_columns or changed_columns or new_columns:
                try:
                    await self.driver.exec_raw("""  ALTER TABLE IF EXISTS "class_{0}" {1};
                                               """.format(class_name,
                                                          ", ".join(alter_strings)))
                except Exception as e:
                    ERROR_MSG("An exception occurred, returning...", e)
                    return

                if deleted_columns:
                    WARN_MSG("Deleted columns in %s %i: [%s]" % (class_name, len(deleted_columns), ", ".join(deleted_columns)))

                if changed_columns:
                    WARN_MSG("Changed columns in %s %i: [%s]" % (class_name, len(changed_columns), ", ".join(["%s from %s to %s" % c for c in changed_columns])))

                if new_columns:
                    INFO_MSG("New columns in %s %i: [%s]" % (class_name, len(new_columns), ", ".join("%s %s" % c for c in new_columns)))
        INFO_MSG(class_name, fields, fields_substitute)
        await self.driver.exec_raw("""  INSERT INTO public.classes (class_name, class_data) VALUES ('{0}', '{1}')
                                        ON CONFLICT (class_name) DO
                                        UPDATE SET class_data = '{1}';
                                   """.format(class_name, json.dumps(fields)))

        await self.driver.exec_raw("""  CREATE TABLE IF NOT EXISTS "class_{0}"
                                        (
                                            rec_id SERIAL PRIMARY KEY NOT NULL,
                                            db_id SERIAL {1}
                                        );
                                        CREATE UNIQUE INDEX IF NOT EXISTS "class_{0}_rec_id_uindex" ON "class_{0}" (rec_id);
                                   """.format(class_name, fields_substitute))

        INFO_MSG(fields)
Exemple #22
0
 async def refresh_database(self):
     """ Обновляет основную структуру если она нарушена """
     try:
         await self.driver.exec_raw("""  CREATE TABLE IF NOT EXISTS public.users  --- список пользователей
                                         (
                                             id SERIAL PRIMARY KEY NOT NULL,    -- ID пользователя
                                             unique_name VARCHAR(255) NOT NULL,    -- имя пользователя
                                             nickname VARCHAR(255),
                                             mail VARCHAR(255) NOT NULL,
                                             hash VARCHAR(255),                -- пароль
                                             salt VARCHAR(255),
                                             auth INT2,                         -- аутентификация
                                             account_dbid SERIAL,               -- DB-идентификатор сущности-аккаунта 
                                             register_date TIMESTAMP,
                                             confirmed BOOLEAN DEFAULT FALSE
                                         );
                                         CREATE UNIQUE INDEX IF NOT EXISTS users_id_uindex ON public.users (id);
                                         
                                         CREATE INDEX IF NOT EXISTS idx_users_name ON public.users (unique_name);
                                         
                                         CREATE TABLE IF NOT EXISTS public.users_uncofirmed
                                         (
                                           id SERIAL PRIMARY KEY NOT NULL,
                                           digest VARCHAR(255)
                                         );
 
                                         CREATE TABLE IF NOT EXISTS public.entities  --- список сущностей (DB-идентификатор - имя класса)
                                         (
                                             db_id SERIAL PRIMARY KEY NOT NULL,    -- DB-идентификатор сущности
                                             class_name VARCHAR(255)               -- имя класс
                                         );
                                         CREATE UNIQUE INDEX IF NOT EXISTS entities_db_id_uindex ON public.entities (db_id);
 
                                         CREATE TABLE IF NOT EXISTS public.classes  --- имформация о классах в базе данных
                                         (
                                             class_name VARCHAR(255) PRIMARY KEY NOT NULL,  -- имя класса
                                             class_data JSONB                               -- данные класса
                                         );
                                         CREATE UNIQUE INDEX IF NOT EXISTS classes_class_name_uindex ON public.classes (class_name);
                                         
                                         CREATE TABLE IF NOT EXISTS public.types  --- имформация о типах
                                         (
                                             type_name VARCHAR(255) PRIMARY KEY NOT NULL,  -- имя типа
                                             type_data JSONB                               -- данные типа
                                         );
                                         CREATE UNIQUE INDEX IF NOT EXISTS types_type_name_uindex ON public.types (type_name);                 
                                         CREATE TABLE IF NOT EXISTS ccu
                                         (
                                             app_name VARCHAR(255),
                                             dump_time TIMESTAMP,
                                             online_count INTEGER,
                                             in_game_count INTEGER
                                         );                     
                                         --- CREATE TABLE IF NOT EXISTS public.storages  --- имформация о хранилищах в базе данных
                                         --- (
                                         ---     storage_name VARCHAR(255) PRIMARY KEY NOT NULL,  -- имя хранилища
                                         ---     storage_data JSONB                               -- данные хранилища
                                         --- );
                                         --- CREATE UNIQUE INDEX IF NOT EXISTS storages_class_name_uindex ON public.storages (storage_name);
                                         CREATE TABLE IF NOT EXISTS public.statistics
                                         (
                                             id SERIAL PRIMARY KEY NOT NULL,
                                             user_id INTEGER,    -- ID пользователя
                                             username VARCHAR(255),
                                             score INTEGER DEFAULT 0,
                                             game_mode INTEGER,
                                             deaths INTEGER DEFAULT 0,
                                             wins INTEGER DEFAULT 0,
                                             CONSTRAINT unique_entry UNIQUE (username, game_mode)
                                         );               
                                         
                                    """)
     except psycopg2.ProgrammingError as e:
         WARN_MSG(f"Unable to refresh database due to errors: {e}")
Exemple #23
0
 def __init__(self, name):
     from Core import WARN_MSG
     self.name = name
     WARN_MSG(f"Access to invalid configuration '{self.name}'")
Exemple #24
0
 def on_terminate(proc):
     process_info = self.processes.get(proc.pid)
     status = proc.status()
     WARN_MSG(
         "Process did't terminated after timeout. pid: %s, status: %s, info: %s",
         proc.pid, status, process_info)
    async def handle_message(self, data):
        """ Обработка входящего сообщения """

        try:
            message_proxy = BinarySerialization(data).proxy()
        except Exception as e:
            ERROR_MSG("Unable to make proxy for data %s: %s" % (data, e))
            return
        try:
            message_type = message_proxy >> int
            message_data = message_proxy >> bytes
        except:
            print(message_proxy)


        if message_type == ConnectionMessageTypes.rmi_call:
            proxy = BinarySerialization(message_data).proxy()
            entity_id    = proxy >> int
            gen_sig      = proxy >> str
            method_index = proxy >> int
            future_id    = proxy >> int
            access_token = proxy >> str
            params       = proxy >> bytes
            if gen_sig == Globals.generator_signature:
                await EntitiesDispatcher().execute_rmi(self.client_connection, entity_id, method_index, future_id, access_token, params)
            else:
                EntitiesDispatcher().remote_response_error(self.client_connection, entity_id, future_id, "Generator signature mismatch")

        elif message_type == ConnectionMessageTypes.rmi_future:
            proxy = BinarySerialization(message_data).proxy()
            entity_id    = proxy >> int
            method_index = proxy >> int
            future_id    = proxy >> int
            returns      = proxy >> bytes
            if future_id != -1:
                EntitiesDispatcher().yield_rmi_result(future_id, entity_id, method_index, returns)

        elif message_type == ConnectionMessageTypes.rmi_error:
            proxy = BinarySerialization(message_data).proxy()
            error_source  = proxy >> str
            error_message = proxy >> str
            future_id     = proxy >> int

            WARN_MSG("Error from %s: %s" % (error_source, error_message))

            if future_id != -1:
                EntitiesDispatcher().yield_rmi_error(future_id)

        elif message_type == ConnectionMessageTypes.rmi_exception:
            proxy = BinarySerialization(message_data).proxy()
            exception_source  = proxy >> str
            exception_class   = proxy >> str
            exception_args    = proxy >> str
            future_id         = proxy >> int

            WARN_MSG("Exception from %s: %s" % (exception_source, exception_class))

            if future_id != -1:
                EntitiesDispatcher().yield_rmi_exception(future_id, exception_class, exception_args)

        await asyncio.sleep(0.1)
Exemple #26
0
    async def GenericLogin(self, login_type, unique_id, password=None, digest=None, nickname=None):
        INFO_MSG(f"Logging in the user {unique_id}: {password} (via {login_type})")
        if digest != LOGIN_DIGEST:
            return None, ELoginResult.InternalError, ""

        if password is not None:
            login_result_status, id, access, dbid, reg_date = await self.db.FindUserForLogin(unique_id, password)
        else:
            login_result_status, id, access, dbid, reg_date = await self.db.FindUserForLoginWithoutPassword(unique_id)

        # TODO: Temporary
        if login_result_status == ELoginResult.NotExists:
            WARN_MSG("Login failed, register it and try again")
            if password is not None:
                await self.RegisterUser(unique_id, "", password, False)
            else:
                if nickname is None:
                    raise NotImplementedError("Login without password is not supported without nickname")
                await self.RegisterUserWithoutPassword(unique_id, nickname)
            return await self.GenericLogin(login_type, unique_id, password=password, digest=digest, nickname=nickname)

        if login_result_status != ELoginResult.Success:
            return None, login_result_status, ""

        success = False
        access_token = ""

        if id not in self.loggedin_users:
            region = self.config.get_region()
            base: 'BaseApp' = await self.supervisor.RequestBaseAppForLogin(region)
            if base:
                access_token = Access().generate(access)

                if nickname is None:  # todo: temp
                    nickname = unique_id

                success = await base.PrepareForJoin(nickname, access_token, id, dbid, self)

                if success:
                    self.loggedin_users[id] = {
                        'base': base,
                        'access_token': access_token,
                    }
                else:
                    WARN_MSG(f"BaseApp does not want to take user {unique_id}")
                    login_result_status = ELoginResult.Rejected
            else:
                login_result_status = ELoginResult.InternalError
                WARN_MSG(f"Failed to login user, there are no active BaseApps")

        else:
            base = self.loggedin_users[id]['base']
            access_token = self.loggedin_users[id]['access_token']
            success = True

        if not success:
            WARN_MSG(f"Failed to login user {unique_id} ({login_result_status})")
            base = None
            access_token = ""

        return base.as_exposed(), login_result_status, access_token