async def handle_connection(self):
     logger.log_pdebug('Connected to the master server.')
     await self.send_server_info()
     ping_timeout = False
     lastping = time.time() - 20
     while True:
         self.reader.feed_data(b'END')
         full_data = await self.reader.readuntil(b'END')
         full_data = full_data[:-3]
         if len(full_data) > 0:
             data_list = list(full_data.split(b'#%'))[:-1]
             for data in data_list:
                 raw_msg = data.decode()
                 cmd, *args = raw_msg.split('#')
                 if cmd not in ('CHECK', 'PONG'):
                     logger.log_debug(
                         '[MASTERSERVER][INC][RAW]{}'.format(raw_msg))
                 elif cmd == 'CHECK':
                     await self.send_raw_message('PING#%')
                 elif cmd == 'PONG':
                     ping_timeout = False
                 elif cmd == 'NOSERV':
                     await self.send_server_info()
         if time.time() - lastping > 10:
             if ping_timeout:
                 self.writer.close()
                 return
             lastping = time.time()
             ping_timeout = True
             await self.send_raw_message('PING#%')
         await asyncio.sleep(1)
Ejemplo n.º 2
0
    def load_ids(self):
        self.ipid_list = {}
        self.hdid_list = {}

        #load ipids
        try:
            with Constants.fopen('storage/ip_ids.json', 'r',
                                 encoding='utf-8') as whole_list:
                self.ipid_list = json.loads(whole_list.read())
        except Exception as ex:
            message = 'WARNING: Error loading storage/ip_ids.json. Will assume empty values.\n'
            message += '{}: {}'.format(type(ex).__name__, ex)

            logger.log_pdebug(message)

        #load hdids
        try:
            with Constants.fopen('storage/hd_ids.json', 'r',
                                 encoding='utf-8') as whole_list:
                self.hdid_list = json.loads(whole_list.read())
        except Exception as ex:
            message = 'WARNING: Error loading storage/hd_ids.json. Will assume empty values.\n'
            message += '{}: {}'.format(type(ex).__name__, ex)

            logger.log_pdebug(message)
Ejemplo n.º 3
0
    def load_gimp(self):
        try:
            gimp_list = ValidateGimp().validate('config/gimp.yaml')
        except ServerError.FileNotFoundError:
            gimp_list = [
                'ERP IS BAN',
                'HELP ME',
                '(((((case????)))))',
                'Anyone else a fan of MLP?',
                'does this server have sans from undertale?',
                'what does call mod do',
                'Join my discord server please',
                'can I have mod pls?',
                'why is everyone a missingo?',
                'how 2 change areas?',
                '19 years of perfection, i don\'t play games to f*****g lose',
                ('nah... your taunts are f*****g useless... only defeat angers me... by trying '
                 'to taunt just earns you my pitty'),
                'When do we remove dangits',
                'MODS STOP GIMPING ME',
                'PLAY NORMIES PLS',
                'share if you not afraid of herobrine',
                'New Killer Choosen! Hold On!!',
                'The cake killed Nether.',
                'How you win Class Trials is simple, call your opposition cucks.',
            ]
            with Constants.fopen('config/gimp.yaml', 'w') as gimp:
                Constants.yaml_dump(gimp_list, gimp)
            message = 'WARNING: File not found: config/gimp.yaml. Creating a new one...'
            logger.log_pdebug(message)

        self.gimp_list = gimp_list
        return gimp_list.copy()
Ejemplo n.º 4
0
    def load_iniswaps(self):
        try:
            with Constants.fopen('config/iniswaps.yaml', 'r', encoding='utf-8') as iniswaps:
                self.allowed_iniswaps = Constants.yaml_load(iniswaps)
        except Exception as ex:
            message = 'WARNING: Error loading config/iniswaps.yaml. Will assume empty values.\n'
            message += '{}: {}'.format(type(ex).__name__, ex)

            logger.log_pdebug(message)
Ejemplo n.º 5
0
    def start(self):
        self.loop = asyncio.get_event_loop()

        bound_ip = '0.0.0.0'
        if self.config['local']:
            bound_ip = '127.0.0.1'
            logger.log_print(
                'Starting a local server. Ignore outbound connection attempts.'
            )

        ao_server_crt = self.loop.create_server(lambda: AOProtocol(self),
                                                bound_ip, self.config['port'])
        ao_server = self.loop.run_until_complete(ao_server_crt)

        logger.log_pdebug('Server started successfully!\n')

        if self.config['use_district']:
            self.district_client = DistrictClient(self)
            self.global_connection = asyncio.ensure_future(
                self.district_client.connect(), loop=self.loop)
            logger.log_print(
                'Attempting to connect to district at {}:{}.'.format(
                    self.config['district_ip'], self.config['district_port']))

        if self.config['use_masterserver']:
            self.ms_client = MasterServerClient(self)
            self.global_connection = asyncio.ensure_future(
                self.ms_client.connect(), loop=self.loop)
            logger.log_print(
                'Attempting to connect to the master server at {}:{} with the following details:'
                .format(self.config['masterserver_ip'],
                        self.config['masterserver_port']))
            logger.log_print('*Server name: {}'.format(
                self.config['masterserver_name']))
            logger.log_print('*Server description: {}'.format(
                self.config['masterserver_description']))

        try:
            self.loop.run_forever()
        except KeyboardInterrupt:
            pass

        print('')  # Lame
        logger.log_pdebug('You have initiated a server shut down.')
        self.shutdown()

        ao_server.close()
        self.loop.run_until_complete(ao_server.wait_closed())
        self.loop.close()
        logger.log_print('Server has successfully shut down.')
Ejemplo n.º 6
0
 def load_banlist(self):
     try:
         with Constants.fopen('storage/banlist.json', 'r') as banlist_file:
             self.bans = json.load(banlist_file)
     except ServerError as ex:
         if ex.code == 'FileNotFound':
             message = 'WARNING: File not found: storage/banlist.json. Creating a new one...'
             logger.log_pdebug(message)
             self.write_banlist()
         else:
             raise ex
     except Exception as ex:
         message = 'WARNING: Error loading storage/banlist.json. Will assume empty values.\n'
         message += '{}: {}'.format(type(ex).__name__, ex)
         logger.log_pdebug(message)
Ejemplo n.º 7
0
 async def connect(self):
     loop = asyncio.get_event_loop()
     while True:
         try:
             self.reader, self.writer = await asyncio.open_connection(
                 self.server.config['masterserver_ip'],
                 self.server.config['masterserver_port'])
             await self.handle_connection()
         except (ConnectionRefusedError, TimeoutError, socket.gaierror):
             pass
         except (ConnectionResetError, asyncio.IncompleteReadError):
             self.writer = None
             self.reader = None
         finally:
             if not self.server.shutting_down:
                 logger.log_pdebug(
                     "Unable to connect to the master server, retrying in 20 seconds."
                 )
                 await asyncio.sleep(20)
Ejemplo n.º 8
0
def main():
    server = None

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    try:
        _pre_launch_checks()
        server = TsuserverDR()

        def _handle_exception(loop, context):
            # The function signature MUST be of the above form
            # https://docs.python.org/3/library/asyncio-eventloop.html
            exception = context.get('exception')
            server.error_queue.put_nowait(exception)
            server.error_queue.put_nowait(exception)
            # An exception is put twice, because it is pulled twice: once by the server object itself
            # (so that it leaves its main loop) and once by this main() function (so that it can
            # print traceback)

        loop.set_exception_handler(_handle_exception)
        loop.run_until_complete(server.start())
        # If we are done with this coroutine, that means an error was raised
        raise server.error_queue.get_nowait()
    except KeyboardInterrupt:
        print('')  # Lame
        logger.log_pdebug('You have initiated a server shut down.')
        loop.run_until_complete(_normal_shutdown(server=server))
        logger.log_pdebug('Server has successfully shut down.')
    except Exception as exception:
        loop.run_until_complete(_abnormal_shutdown(exception, server=server))
    finally:
        try:
            input("Press Enter to exit. ")
        except (Exception, KeyboardInterrupt):
            # Only errors that could realistically happen are just a bunch of Ctrl+C/Z leaking
            # in the input message and those being sent. We don't really care what happens now,
            # everything has shut down by this point.
            pass
Ejemplo n.º 9
0
    def load_ids(self):
        self.ipid_list = dict()
        self.hdid_list = dict()

        # load ipids
        try:
            with Constants.fopen('storage/ip_ids.json', 'r', encoding='utf-8') as whole_list:
                self.ipid_list = json.load(whole_list)
        except ServerError as exc:
            if exc.code != 'FileNotFound':
                raise exc
            with Constants.fopen('storage/ip_ids.json', 'w', encoding='utf-8') as whole_list:
                json.dump(dict(), whole_list)
            message = 'WARNING: File not found: storage/ip_ids.json. Creating a new one...'
            logger.log_pdebug(message)
        except Exception as ex:
            message = 'WARNING: Error loading storage/ip_ids.json. Will assume empty values.\n'
            message += '{}: {}'.format(type(ex).__name__, ex)

            logger.log_pdebug(message)

        # If the IPID list is not a dict, fix the file
        # Why on earth is it called an IPID list if it is a Python dict is beyond me.
        if not isinstance(self.ipid_list, dict):
            message = (f'WARNING: File storage/ip_ids.json had a structure of the wrong type: '
                       f'{self.ipid_list}. Replacing it with a proper type.')
            logger.log_pdebug(message)
            self.ipid_list = dict()
            self.dump_ipids()

        # load hdids
        try:
            with Constants.fopen('storage/hd_ids.json', 'r', encoding='utf-8') as whole_list:
                self.hdid_list = json.load(whole_list)
        except ServerError as exc:
            if exc.code != 'FileNotFound':
                raise exc
            with Constants.fopen('storage/hd_ids.json', 'w', encoding='utf-8') as whole_list:
                json.dump(dict(), whole_list)
            message = 'WARNING: File not found: storage/hd_ids.json. Creating a new one...'
            logger.log_pdebug(message)
        except Exception as ex:
            message = 'WARNING: Error loading storage/hd_ids.json. Will assume empty values.\n'
            message += '{}: {}'.format(type(ex).__name__, ex)

            logger.log_pdebug(message)

        # If the HDID list is not a dict, fix the file
        # Why on earth is it called an HDID list if it is a Python dict is beyond me.
        if not isinstance(self.hdid_list, dict):
            message = (f'WARNING: File storage/hd_ids.json had a structure of the wrong type: '
                       f'{self.hdid_list}. Replacing it with a proper type.')
            logger.log_pdebug(message)
            self.hdid_list = dict()
            self.dump_hdids()
Ejemplo n.º 10
0
    def start(self):
        try:
            self.loop = asyncio.get_event_loop()
        except RuntimeError:
            self.loop = asyncio.new_event_loop()

        self.tasker = Tasker(self, self.loop)
        bound_ip = '0.0.0.0'
        if self.config['local']:
            bound_ip = '127.0.0.1'
            server_name = 'localhost'
            logger.log_print('Starting a local server...')
        else:
            server_name = self.config['masterserver_name']
            logger.log_print('Starting a nonlocal server...')

        ao_server_crt = self.loop.create_server(lambda: self.protocol(self), bound_ip,
                                                self.config['port'])
        ao_server = self.loop.run_until_complete(ao_server_crt)

        logger.log_pserver('Server started successfully!')

        if self.config['local']:
            host_ip = '127.0.0.1'
        else:
            try:
                host_ip = (urllib.request.urlopen('https://api.ipify.org',
                                                  context=ssl.SSLContext())
                           .read().decode('utf8'))
            except urllib.error.URLError as ex:
                host_ip = None
                logger.log_pdebug('Unable to obtain personal IP from https://api.ipify.org\n'
                                  '{}: {}\n'
                                  'Players may be unable to join.'
                                  .format(type(ex).__name__, ex.reason))
        if host_ip is not None:
            logger.log_pdebug('Server should be now accessible from {}:{}:{}'
                              .format(host_ip, self.config['port'], server_name))
        if not self.config['local']:
            logger.log_pdebug('If you want to join your server from this device, you may need to '
                              'join with this IP instead: 127.0.0.1:{}:localhost'
                              .format(self.config['port']))

        if self.config['local']:
            self.local_connection = asyncio.ensure_future(self.tasker.do_nothing(), loop=self.loop)

        if self.config['use_district']:
            self.district_client = DistrictClient(self)
            self.district_connection = asyncio.ensure_future(self.district_client.connect(),
                                                             loop=self.loop)
            print(' ')
            logger.log_print('Attempting to connect to district at {}:{}.'
                             .format(self.config['district_ip'], self.config['district_port']))

        if self.config['use_masterserver']:
            self.ms_client = MasterServerClient(self)
            self.masterserver_connection = asyncio.ensure_future(self.ms_client.connect(),
                                                                 loop=self.loop)
            print(' ')
            logger.log_print('Attempting to connect to the master server at {}:{} with the '
                             'following details:'.format(self.config['masterserver_ip'],
                                                         self.config['masterserver_port']))
            logger.log_print('*Server name: {}'.format(self.config['masterserver_name']))
            logger.log_print('*Server description: {}'
                             .format(self.config['masterserver_description']))

        try:
            self.loop.run_forever()
        except KeyboardInterrupt:
            pass

        print('') # Lame
        logger.log_pdebug('You have initiated a server shut down.')
        self.shutdown()

        ao_server.close()
        self.loop.run_until_complete(ao_server.wait_closed())
        self.loop.close()
        logger.log_pserver('Server has successfully shut down.')
Ejemplo n.º 11
0
    async def start(self):
        self.loop = asyncio.get_event_loop()
        self.error_queue = asyncio.Queue()

        self.tasker = Tasker(self)
        bound_ip = '0.0.0.0'
        if self.config['local']:
            bound_ip = '127.0.0.1'
            server_name = 'localhost'
            logger.log_print('Starting a local server...')
        else:
            server_name = self.config['masterserver_name']
            logger.log_print('Starting a nonlocal server...')

        # Check if port is available
        port = self.config['port']
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind((bound_ip, port))
            except socket.error as exc:
                if exc.errno == errno.EADDRINUSE:
                    msg = (
                        f'Port {port} is in use by another application. Make sure to close any '
                        f'conflicting applications (even another instance of this server) and '
                        f'try again.')
                    raise ServerError(msg)
                raise exc
            except OverflowError as exc:
                msg = str(exc).replace('bind(): ', '').capitalize()
                msg += ' Make sure to set your port number to an appropriate value and try again.'
                raise ServerError(msg)

        # Yes there is a race condition here (between checking if port is available, and actually
        # using it). The only side effect of a race condition is a slightly less nice error
        # message, so it's not that big of a deal.
        self._server = await self.loop.create_server(
            lambda: self.protocol(self), bound_ip, port, start_serving=False)
        asyncio.create_task(self._server.serve_forever())
        logger.log_pserver('Server started successfully!')

        if self.config['local']:
            host_ip = '127.0.0.1'
        else:
            try:
                host_ip = (urllib.request.urlopen(
                    'https://api.ipify.org',
                    context=ssl.SSLContext()).read().decode('utf8'))
            except urllib.error.URLError as ex:
                host_ip = None
                logger.log_pdebug(
                    'Unable to obtain personal IP from https://api.ipify.org\n'
                    '{}: {}\n'
                    'Players may be unable to join.'.format(
                        type(ex).__name__, ex.reason))
        if host_ip is not None:
            logger.log_pdebug(
                'Server should be now accessible from {}:{}:{}'.format(
                    host_ip, self.config['port'], server_name))
        if not self.config['local']:
            logger.log_pdebug(
                'If you want to join your server from this device, you may need to '
                'join with this IP instead: 127.0.0.1:{}:localhost'.format(
                    self.config['port']))

        if self.config['local']:
            self.local_connection = asyncio.create_task(
                self.tasker.do_nothing())

        if self.config['use_district']:
            self.district_client = DistrictClient(self)
            self.district_connection = asyncio.create_task(
                self.district_client.connect())
            print(' ')
            logger.log_print(
                'Attempting to connect to district at {}:{}.'.format(
                    self.config['district_ip'], self.config['district_port']))

        if self.config['use_masterserver']:
            self.ms_client = MasterServerClient(self)
            self.masterserver_connection = asyncio.create_task(
                self.ms_client.connect())
            print(' ')
            logger.log_print(
                'Attempting to connect to the master server at {}:{} with the '
                'following details:'.format(self.config['masterserver_ip'],
                                            self.config['masterserver_port']))
            logger.log_print('*Server name: {}'.format(
                self.config['masterserver_name']))
            logger.log_print('*Server description: {}'.format(
                self.config['masterserver_description']))

        raise await self.error_queue.get()