Exemple #1
0
    def __init__(self, name='', devices=(), backdoor=None):
        self.name = name
        self._log = logging.getLogger('{0}.{1}'.format(_log.name, name))
        self._log.info('Bootstraping server')
        if backdoor:
            from gevent.backdoor import BackdoorServer
            banner = 'Welcome to Bliss emulator server console.\n' \
                     'My name is {0!r}. You can access me through the ' \
                     '\'server()\' function. Have fun!'.format(name)
            self.backdoor = BackdoorServer(
                backdoor, banner=banner, locals=dict(server=weakref.ref(self)))
            self.backdoor.start()
            self._log.info('Backdoor opened at %r', backdoor)

        else:
            self._log.info('no backdoor declared')

        self.devices = {}
        for device in devices:
            try:
                self.create_device(device)
            except Exception as error:
                dname = device.get('name', device.get('class', 'unknown'))
                self._log.error(
                    'error creating device %s (will not be available): %s',
                    dname, error)
                self._log.debug('details: %s', error, exc_info=1)
Exemple #2
0
 def __init__(self, addr, *args, **kwargs):
     if self.__class__.__instance is not None:
         raise RuntimeError(
             'only one backdoor server allowed to be running')
     self.addr = addr
     self.server = BackdoorServer(addr)
     Greenlet.__init__(self, *args, **kwargs)
Exemple #3
0
    def start_backdoor(self):
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals={'dispatcher': self.dispatcher})

        gevent.spawn(self.backdoor_server.serve_forever)
Exemple #4
0
class ServeBackdoor(Greenlet):
    __instance = None

    def __init__(self, addr, *args, **kwargs):
        if self.__class__.__instance is not None:
            raise RuntimeError(
                'only one backdoor server allowed to be running')
        self.addr = addr
        self.server = BackdoorServer(addr)
        Greenlet.__init__(self, *args, **kwargs)

    @classmethod
    def get_instance(cls):
        return cls.__instance

    # pylint: disable=E0202
    def _run(self):
        cls = self.__class__
        try:
            cls.__instance = self
            logger.info("starting backdoor server on %r...", self.addr)
            self.server.serve_forever()
        finally:
            logger.info('backdoor server on %r stopped', self.addr)
            cls.__instance = None
Exemple #5
0
    def start_backdoor(self, backlog=50):
        """Start a backdoor server on a local UNIX domain socket.

        """
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise
        else:
            logger.warning("A backdoor socket has been found and deleted.")
        mkdir(os.path.dirname(backdoor_path))
        backdoor_sock = gevent.socket.socket(socket.AF_UNIX,
                                             socket.SOCK_STREAM)
        backdoor_sock.setblocking(0)
        backdoor_sock.bind(backdoor_path)
        user = pwd.getpwnam(config.cmsuser)
        # We would like to also set the user to "cmsuser" but only root
        # can do that. Therefore we limit ourselves to the group.
        os.chown(backdoor_path, os.getuid(), user.pw_gid)
        os.chmod(backdoor_path, 0o770)
        backdoor_sock.listen(backlog)
        self.backdoor = BackdoorServer(backdoor_sock, locals={'service': self})
        self.backdoor.start()
Exemple #6
0
def main():
    global context
    global app

    parser = argparse.ArgumentParser()
    parser.add_argument("-p",
                        "--pid-file",
                        help="location to write process ID",
                        required=False)
    args = parser.parse_args()

    if args.pid_file is not None:
        with open(args.pid_file, "w") as pid_file:
            pid_file.write(str(os.getpid()) + "\n")

    app = create_app()

    #from . import emergency # we do this late so app is available for import

    with app.app_context():
        try:
            backdoor = BackdoorServer(
                ('127.0.0.1', app.config["BACKEND_BACKDOOR_SERVER_PORT"]),
                locals=locals())
            backdoor.start()

            server()
        except KeyboardInterrupt as e:
            l.debug("shutting down")
Exemple #7
0
    def __init__(self, devices=(), backdoor=None):
        self._log = _log
        self._log.info("Bootstraping server")
        if backdoor:
            from gevent.backdoor import BackdoorServer

            banner = ("Welcome to Simulator server console.\n"
                      "You can access me through the "
                      "'server()' function. Have fun!")
            self.backdoor = BackdoorServer(
                backdoor, banner=banner, locals=dict(server=weakref.ref(self)))
            self.backdoor.start()
            self._log.info("Backdoor opened at %r", backdoor)
        else:
            self._log.info("no backdoor declared")

        self.devices = {}
        for device in devices:
            try:
                self.create_device(device)
            except Exception as error:
                dname = device.get("name", device.get("class", "unknown"))
                self._log.error(
                    "error creating device %s (will not be available): %s",
                    dname, error)
                self._log.debug("details: %s", error, exc_info=1)
Exemple #8
0
class Warpgate(object):

    def init(self):
        import options
        from UnityEngine import Debug

        L = lambda s: Debug.Log("PyWrap: " + s)
        L("init")

        self.events = []

        # should set them
        options.no_update
        options.show_hidden_mode

        options.freeplay = False

        if options.no_update:
            import autoupdate
            autoupdate.Autoupdate = autoupdate.DummyAutoupdate

        L("before gevent")
        from gevent import monkey
        monkey.patch_socket()
        monkey.patch_os()
        monkey.patch_select()
        L("after gevent")

        from game import autoenv
        autoenv.init('Client')

        import thb.ui.ui_meta  # noqa, init ui_meta

        from client.core.executive import Executive
        self.executive = ExecutiveWrapper(Executive, self)

    def get_events(self):
        l = self.events
        self.events = []
        return l

    def start_backdoor(self):
        from gevent.backdoor import BackdoorServer
        import gevent
        self.bds = BackdoorServer(('127.0.0.1', 12345))
        self.gr_bds = gevent.spawn(self.bds.serve_forever)

    def stop_backdoor(self):
        self.gr_bds.kill()
        self.bds.close()

    def shutdown(self):
        from client.core.executive import Executive
        if Executive.state == 'connected':
            Executive.disconnect()

    def queue_system_event(self, evt_name, arg=None):
        self.events.append(('system_event', evt_name, arg))
def startbackdoor(host=None, port=8998):
    if get_config('DONT_USE_GEVENT'):
        raise('Backdoor is not available')
    if host is None:
        host=HOST
    from gevent.backdoor import BackdoorServer
    print('Backdoor is on %s:%s' % (host, port))
    bs = BackdoorServer((host, port), locals())
    bs.start()
Exemple #10
0
class Warpgate(object):
    def init(self):
        import options
        from UnityEngine import Debug

        L = lambda s: Debug.Log("PyWrap: " + s)
        L("init")

        self.events = []

        # should set them
        options.no_update
        options.show_hidden_mode

        options.freeplay = False

        if options.no_update:
            import autoupdate
            autoupdate.Autoupdate = autoupdate.DummyAutoupdate

        L("before gevent")
        from gevent import monkey
        monkey.patch_socket()
        monkey.patch_os()
        monkey.patch_select()
        L("after gevent")

        from game import autoenv
        autoenv.init('Client')

        import thb.ui.ui_meta  # noqa, init ui_meta

        from client.core.executive import Executive
        self.executive = ExecutiveWrapper(Executive, self)

    def get_events(self):
        l = self.events
        self.events = []
        return l

    def start_backdoor(self):
        from gevent.backdoor import BackdoorServer
        import gevent
        self.bds = BackdoorServer(('127.0.0.1', 12345))
        self.gr_bds = gevent.spawn(self.bds.serve_forever)

    def stop_backdoor(self):
        self.gr_bds.kill()
        self.bds.close()

    def shutdown(self):
        from client.core.executive import Executive
        if Executive.state == 'connected':
            Executive.disconnect()

    def queue_system_event(self, evt_name, arg=None):
        self.events.append(('system_event', evt_name, arg))
Exemple #11
0
def startbackdoor(host=None, port=8998):
    if get_config('DONT_USE_GEVENT'):
        raise('Backdoor is not available')
    if host is None:
        host=HOST
    from gevent.backdoor import BackdoorServer
    print('Backdoor is on %s:%s' % (host, port))
    bs = BackdoorServer((host, port), locals())
    bs.start()
Exemple #12
0
 def start_server(self, host='localhost', port=None):
     "Start a server on HOST and PORT."
     assert port is not None
     if self.where is not None:
         self.stop_server()
     self.where = host, port
     log.info("Installing backdoor on %s, port %d.", host, port)
     from gevent.backdoor import BackdoorServer
     server = BackdoorServer(self.where)
     server.start()
Exemple #13
0
    def start_backdoor(self):
        if not self.gevent:
            raise RpcException(errno.ENOTSUP, 'Not supported')

        from gevent import spawn
        from gevent.backdoor import BackdoorServer
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals=self.backdoor_locals)

        spawn(self.backdoor_server.serve_forever())
Exemple #14
0
    def backdoor(self):
        self.logger.debug('Spawning Backdoor Greenlet')
        self.logger.warning(
            "The backdoor server should be used for dev purposes only!")

        if self.config.backdoor_host == "0.0.0.0":
            self.logger.warning(
                "Backdoor server should never bind to 0.0.0.0! This is extremely dangerous!"
            )

        server = BackdoorServer(
            (self.config.backdoor_host, self.config.backdoor_port),
            locals={'bot': self})
        server.serve_forever()
Exemple #15
0
class BackdoorPlugin(BotPlugin):
	name = 'backdoor'
	defaults = {
		'port': 1234,
	}

	def init(self):
		self.server = BackdoorServer(('localhost', self.config.port), locals={
			'clients': clients,
		})
		self.server.start()

	def cleanup(self):
		super(BackdoorPlugin, self).cleanup()
		self.server.stop()
Exemple #16
0
    def run(self, auto_join=False):
        """
            Runs Dissonance, loading all the modules, starting the web service, and starting the adapter.

            If auto_join=True, this function will not return, and will run until dissonance stops if starting dissonance from
            outside of a greenlet.

        """
        if self.running:
            raise RuntimeError("Dissonance is already running!")

        logger.info("Starting Dissonance v%s", self.version)

        logger.info("Starting storage %s", self._storage)
        self._storage.start()

        logger.info("Loading modules")
        self.modules.load_all()

        if getattr(self.config, 'web', False) or str(
                self._opts.get('web', False)).upper() == 'TRUE':
            self._web = Web(
                self,
                EnvFallbackDict('web', getattr(self.config, 'web_opts', {})))
            self._web.start()

        if getattr(self.config, 'manhole', False):
            from gevent.backdoor import BackdoorServer
            manhole_opts = EnvFallbackDict(
                'manhole', getattr(self.config, 'manhole_opts', {}))
            self._manhole = BackdoorServer(
                (manhole_opts.get('listen_host', '127.0.0.1'),
                 int(manhole_opts.get('listen_port', 9001))),
                locals={'client': self.client})

            self._manhole.start()

        logger.info("Attempting to log in as %s" % self._opts['email'])
        self.client.login(self._opts['email'], self._opts['password'])
        logger.info("Starting connection to Discord")
        self.client.start()
        self._storage_sync_periodic.start(right_away=False)
        self._stop_event.clear()

        # If we are the main greenlet, chances are we probably want to never return,
        # so the main greenlet won't exit, and tear down everything with it.
        if auto_join and gevent.get_hub().parent == gevent.getcurrent():
            self.join()
Exemple #17
0
    def __init__(self, name='', devices=(), backdoor=None):
        self.name = name
        self._log = logging.getLogger('{0}.{1}'.format(_log.name, name))
        self._log.info('Bootstraping server')
        if backdoor:
            from gevent.backdoor import BackdoorServer
            banner = 'Welcome to Bliss emulator server console.\n' \
                     'My name is {0!r}. You can access me through the ' \
                     '\'server()\' function. Have fun!'.format(name)
            self.backdoor = BackdoorServer(backdoor, banner=banner,
                                           locals=dict(server=weakref.ref(self)))
            self.backdoor.start()
            self._log.info('Backdoor opened at %r', backdoor)

        else:
            self._log.info('no backdoor declared')

        self.devices = {}
        for device in devices:
            try:
                self.create_device(device)
            except Exception as error:
                dname = device.get('name', device.get('class', 'unknown'))
                self._log.error('error creating device %s (will not be available): %s',
                                dname, error)
                self._log.debug('details: %s', error, exc_info=1)
Exemple #18
0
 def run(self):
     from gevent.server import StreamServer
     from gevent.pywsgi import WSGIServer
     from gevent.backdoor import BackdoorServer
     import gm.app  # NOQA
     from gm.init_app import application
     import settings as st
     # wait for proxy
     self.ping_proxy()
     threads = []
     logger.info('listening 0.0.0.0:%d', st.WORLD['port'])
     self.mainServer = StreamServer(('0.0.0.0', st.WORLD['port']),
                                    self.handle_client)
     threads.append(Greenlet.spawn(self.mainServer.serve_forever))
     logger.info('listening %s:%d', st.WORLD['managehost'],
                 st.WORLD['manageport'])
     threads.append(
         Greenlet.spawn(
             WSGIServer((st.WORLD['managehost'], st.WORLD['manageport']),
                        application,
                        spawn=pool.Pool(10)).serve_forever))
     if os.environ.get("DOCKER_MANAGEHOST"):
         backdoorhost = "0.0.0.0"
     else:
         backdoorhost = "127.0.0.1"
     logger.info('listening %s:%d', backdoorhost, st.WORLD['backdoorport'])
     threads.append(
         Greenlet.spawn(
             BackdoorServer(
                 (backdoorhost, st.WORLD['backdoorport'])).serve_forever))
     # start cron thread
     import cron_settings  # NOQA
     threads.append(Greenlet.spawn(self.heart_beat))
     joinall(threads)
Exemple #19
0
def main():
    parser = argparse.ArgumentParser('aya')
    parser.add_argument('--dbc-username')
    parser.add_argument('--dbc-password')
    parser.add_argument('--bearybot')
    parser.add_argument('--upyun-bucket')
    parser.add_argument('--upyun-username')
    parser.add_argument('--upyun-password')
    parser.add_argument('--redis-url', default='redis://*****:*****@sentry.thbattle.net/4'
    )
    State.options = options = parser.parse_args()

    utils.logging.init_server(logging.DEBUG,
                              options.sentry,
                              'aya-1.0',
                              'aya.log',
                              with_gr_name=False)
    db.session.init(options.db)
    gevent.spawn(BackdoorServer(('127.0.0.1', 11111)).serve_forever)

    def loop():
        State.aya = Aya()
        # State.aya.wait_ready()
        State.interconnect = AyaInterconnect.spawn('aya', options.redis_url)
        State.dao = AyaDAO(options.redis_url)
        State.aya.join()

    gevent.spawn(loop).join()
    gevent.sleep(10)  # for sentry
Exemple #20
0
    def run(self):
        container = create_container(self.config)
        install_plugins(container, self.config.get('plugins', {}))
        install_interfaces(container, self.config.get('interfaces', {}))

        for cls_name in self.args.get('--interface', ()):
            cls = import_object(cls_name)
            container.install(cls)

        if self.args.get('--debug'):
            from gevent.backdoor import BackdoorServer
            backdoor = BackdoorServer(('127.0.0.1', 5005), locals={'container': container})
            gevent.spawn(backdoor.serve_forever)

        def handle_signal():
            logger.info('caught SIGINT/SIGTERM, pid=%s', os.getpid())
            container.stop()
            container.join()
            sys.exit(0)
        gevent.signal(signal.SIGINT, handle_signal)
        gevent.signal(signal.SIGTERM, handle_signal)

        setproctitle('lymph-instance (identity: %s, endpoint: %s, config: %s)' % (
            container.identity,
            container.endpoint,
            self.config.source,
        ))

        container.start(register=not self.args.get('--isolated', False))

        if self.args.get('--reload'):
            set_source_change_callback(container.stop)

        container.join()
Exemple #21
0
def main():
    global interconnect, aya
    logging.basicConfig(level=logging.DEBUG)

    gevent.spawn(BackdoorServer(('127.0.0.1', 11111)).serve_forever)

    aya = Aya()
    # aya.wait_ready()
    interconnect = AyaInterconnect.spawn('aya', options.redis_url)
    aya.join()
Exemple #22
0
    def start_backdoor(self):
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals={
                'dispatcher': self.dispatcher
            }
        )

        gevent.spawn(self.backdoor_server.serve_forever)
Exemple #23
0
def handle_run(args):
    store = Storage(args.root)
    transport = Transport(args.listen)
    node = LogicNode(transport.endpoint(), store)
    if args.backdoor:
        from gevent.backdoor import BackdoorServer
        BackdoorServer(('127.0.0.1', args.backdoor),
                       banner="Hello from gevent backdoor!",
                       locals={
                           'node': node
                       }).start()
    gevent.wait()
Exemple #24
0
def start_server():

    def _exit_handler(*a, **k):
        gevent.kill(MAIN, SystemExit)
    sig(signal.SIGTERM, _exit_handler)

    from game import autoenv

    import argparse

    parser = argparse.ArgumentParser(prog=sys.argv[0])
    parser.add_argument('node', type=str)
    parser.add_argument('--host', default='0.0.0.0', type=str)
    parser.add_argument('--port', default=9999, type=int)
    parser.add_argument('--backdoor-host', default='127.0.0.1', type=str)
    parser.add_argument('--backdoor-port', default=19999, type=int)
    parser.add_argument('--no-backdoor', action='store_true')
    parser.add_argument('--freeplay', action='store_true')
    parser.add_argument('--log', default='INFO')
    parser.add_argument('--logfile', default='')
    parser.add_argument('--gidfile', default='')
    parser.add_argument('--credit-multiplier', type=float, default=1)
    parser.add_argument('--no-counting-flee', action='store_true')
    parser.add_argument('--archive-path', default='')
    parser.add_argument('--interconnect', action='store_true', default=False)
    parser.add_argument('--redis-url', default='redis://localhost:6379')
    parser.add_argument('--discuz-authkey', default='Proton rocks')
    parser.add_argument('--db', default='sqlite:////dev/shm/thb.sqlite3')
    options = parser.parse_args()

    import options as opmodule
    opmodule.options = options

    import db.session
    db.session.init(options.db)

    autoenv.init('Server')

    import settings

    utils.logging.init_server(getattr(logging, options.log.upper()), settings.SENTRY_DSN, settings.VERSION, options.logfile)

    if not options.no_backdoor:
        from gevent.backdoor import BackdoorServer
        gevent.spawn(BackdoorServer((options.backdoor_host, options.backdoor_port)).serve_forever)

    from server.core import Client

    root = logging.getLogger()
    root.info('=' * 20 + settings.VERSION + '=' * 20)
    server = StreamServer((options.host, options.port), Client.serve, None)
    server.serve_forever()
Exemple #25
0
 def init_device(self):
     Device.init_device(self)
     self.debug_stream("In init_device() of controller")
     self.group_dict = {}
     if self.BackdoorPort:
         print "Starting Backdoor server on port", self.BackdoorPort
         server = BackdoorServer(('127.0.0.1', self.BackdoorPort),
                                 banner="BlissAxisManager back door",
                                 locals={'axis_manager': self})
         gevent.spawn(server.serve_forever)
         self.__backdoor_server = server
     else:
         print " no backdoor"
Exemple #26
0
    def start_backdoor(self):
        if not self.gevent:
            raise RpcException(errno.ENOTSUP, 'Not supported')

        from gevent import spawn
        from gevent.backdoor import BackdoorServer
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals=self.backdoor_locals
        )

        spawn(self.backdoor_server.serve_forever())
Exemple #27
0
    def run(self, auto_join=False):
        """
            Runs Dissonance, loading all the modules, starting the web service, and starting the adapter.

            If auto_join=True, this function will not return, and will run until dissonance stops if starting dissonance from
            outside of a greenlet.

        """
        if self.running:
            raise RuntimeError("Dissonance is already running!")

        logger.info("Starting Dissonance v%s", self.version)

        logger.info("Starting storage %s", self._storage)
        self._storage.start()

        logger.info("Loading modules")
        self.modules.load_all()

        if getattr(self.config, 'web', False) or str(self._opts.get('web', False)).upper() == 'TRUE':
            self._web = Web(self, EnvFallbackDict('web', getattr(self.config, 'web_opts', {})))
            self._web.start()

        if getattr(self.config, 'manhole', False):
            from gevent.backdoor import BackdoorServer
            manhole_opts = EnvFallbackDict('manhole', getattr(self.config, 'manhole_opts', {}))
            self._manhole = BackdoorServer((
                manhole_opts.get('listen_host', '127.0.0.1'),
                int(manhole_opts.get('listen_port', 9001))
            ), locals={
                'client': self.client
            })

            self._manhole.start()

        logger.info("Attempting to log in as %s" % self._opts['email'])
        self.client.login(self._opts['email'], self._opts['password'])
        logger.info("Starting connection to Discord")
        self.client.start()
        self._storage_sync_periodic.start(right_away=False)
        self._stop_event.clear()

        # If we are the main greenlet, chances are we probably want to never return,
        # so the main greenlet won't exit, and tear down everything with it.
        if auto_join and gevent.get_hub().parent == gevent.getcurrent():
            self.join()
Exemple #28
0
    def _start_backdoor_terminal(self):
        # XXX(Mouad): Imported here since this is still broken in Python3.x
        from gevent.backdoor import BackdoorServer

        try:
            ip = self.config.get_raw('debug.backdoor_ip')
        except KeyError:
            ip = '127.0.0.1'
        port = get_unused_port()
        endpoint = '%s:%s' % (ip, port)

        banner = "Welcome to backdoor Terminal of %s" % self.container.service_name

        backdoor = BackdoorServer(
            endpoint,
            locals={'container': self.container, 'dump_stacks': dump_stacks},
            banner=banner)
        gevent.spawn(backdoor.serve_forever)

        self.container.backdoor_endpoint = endpoint
Exemple #29
0
 def get_backdoor_server(self, listen_addr, **context):
     """Add a backdoor (debug) server."""
     from django.conf import settings
     local_vars = {
         'launcher': self,
         'servers': self.servers,
         'pgworker': self.pgworker,
         'stop': self.stop,
         'api': self.api,
         'resource': self.resource,
         'settings': settings,
         'wsgi_app': self.wsgi_app,
         'wsgi_name': self.wsgi_name,
     }
     local_vars.update(context)
     return BackdoorServer(
         listen_addr,
         banner='Django DDP',
         locals=local_vars,
     )
Exemple #30
0
    def start_backdoor(self, backlog=50):
        """Start a backdoor server on a local UNIX domain socket.

        """
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise
        else:
            logger.warning("A backdoor socket has been found and deleted.")
        mkdir(os.path.dirname(backdoor_path))
        backdoor_sock = _socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        backdoor_sock.setblocking(0)
        backdoor_sock.bind(backdoor_path)
        user = pwd.getpwnam("cmsuser")
        # We would like to also set the user to "cmsuser" but only root
        # can do that. Therefore we limit ourselves to the group.
        os.chown(backdoor_path, os.getuid(), user.pw_gid)
        os.chmod(backdoor_path, 0o770)
        backdoor_sock.listen(backlog)
        self.backdoor = BackdoorServer(backdoor_sock, locals={'service': self})
        self.backdoor.start()
Exemple #31
0
class DebugService(RpcService):
    def __init__(self, gevent=False, builtins=None):
        self.gevent = gevent
        self.backdoor_locals = builtins or {}
        self.backdoor_server = None

    @private
    def attach(self, host, port):
        import pydevd
        pydevd.settrace(host, port=port, stdoutToServer=True, stderrToServer=True)

    @private
    def detach(self):
        import pydevd
        pydevd.stoptrace()

    @private
    def dump_stacks(self):
        if self.gevent:
            from greenlet import greenlet

            # If greenlet is present, let's dump each greenlet stack
            dump = []
            for ob in gc.get_objects():
                if not isinstance(ob, greenlet):
                    continue
                if not ob:
                    continue   # not running anymore or not started

                dump.append(''.join(traceback.format_stack(ob.gr_frame)))

            return dump
        else:
            dump = []
            for frame in list(sys._current_frames().values()):
                dump.append(''.join(traceback.format_stack(frame)))

            return dump

    @private
    def start_backdoor(self):
        if not self.gevent:
            raise RpcException(errno.ENOTSUP, 'Not supported')

        from gevent import spawn
        from gevent.backdoor import BackdoorServer
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals=self.backdoor_locals
        )

        spawn(self.backdoor_server.serve_forever())

    @private
    def stop_backdoor(self):
        if not self.gevent:
            raise RpcException(errno.ENOTSUP, 'Not supported')

        if self.backdoor_server:
            self.backdoor_server.close()
            self.backdoor_server = None
Exemple #32
0
                (rec.msg, rec.args)),
        )


fmter = ServerLogFormatter()

root = logging.getLogger()

root.setLevel(getattr(logging, options.log.upper()))
std = logging.StreamHandler(stream=sys.stdout)
std.setFormatter(fmter)
root.handlers = []
root.addHandler(std)

if options.logfile:
    from logging.handlers import WatchedFileHandler
    filehdlr = WatchedFileHandler(options.logfile)
    filehdlr.setFormatter(fmter)
    root.addHandler(filehdlr)

if not options.no_backdoor:
    from gevent.backdoor import BackdoorServer
    gevent.spawn(
        BackdoorServer(('127.0.0.1', options.backdoor_port)).serve_forever)

from server.core import Client

root.info('=' * 20 + settings.VERSION + '=' * 20)
server = StreamServer(('0.0.0.0', options.port), Client.spawn, None)
server.serve_forever()
Exemple #33
0
                self.msg(user.nick,
                         "Yahoo answers cannot answer %r" % match.group(1))
                self.msg(user.nick, "Try: \"Does napping make you smarter?\"")
        else:
            self.msg(user.nick,
                     "Can't understand your command: \"%s\"" % message)


if __name__ == '__main__':
    from girclib.helpers import setup_logging
    setup_logging(level=5)
    client = YahooAnswerBot('irc.freenode.net', 6667, 'girclib', 'gIRClib')

    # Just for the fun, start telnet backdoor on port 2000
    from gevent.backdoor import BackdoorServer
    server = BackdoorServer(('127.0.0.1', 2000), locals=locals())
    server.start()

    @signals.on_signed_on.connect
    def _on_motd(emitter):
        log.info("Signed on. Let's join #ufs")
        client.join("#ufs")

    @signals.on_disconnected.connect
    def disconnected(emitter):
        log.info("Exited!?")
        try:
            gevent.shutdown()
        except AssertionError:
            # Shutting down is only possible from MAIN greenlet
            pass
Exemple #34
0
import gevent.monkey
from gevent.wsgi import WSGIServer
from gevent.backdoor import BackdoorServer
from webservice import app
from ircservice import irc

gevent.monkey.patch_all()

backdoor = BackdoorServer(('127.0.0.1',18080))
backdoor.start()

irc.init()

http_server = WSGIServer(('', 8000), app)
http_server.serve_forever()
Exemple #35
0
class DebugService(RpcService):
    def __init__(self):
        super(DebugService, self).__init__()
        self.dispatcher = None
        self.backdoor_server = None

    def initialize(self, context):
        self.dispatcher = context.dispatcher

    @private
    def dump_stacks(self):
        from greenlet import greenlet

        # If greenlet is present, let's dump each greenlet stack
        dump = []
        for ob in gc.get_objects():
            if not isinstance(ob, greenlet):
                continue
            if not ob:
                continue   # not running anymore or not started

            dump.append(''.join(traceback.format_stack(ob.gr_frame)))

        return dump

    @private
    def attach(self, host, port):
        sys.path.append('/usr/local/lib/dispatcher/pydev')

        import pydevd
        pydevd.settrace(host, port=port, stdoutToServer=True, stderrToServer=True)

    @private
    def detach(self):
        import pydevd
        pydevd.stoptrace()

    @private
    def set_tasks_debug(self, host, port, tasks=None):
        self.dispatcher.balancer.debugger = (host, port)
        self.dispatcher.balancer.debugged_tasks = tasks or ['*']

    @private
    def cancel_tasks_debug(self):
        self.dispatcher.balancer.debugger = None
        self.dispatcher.balancer.debugged_tasks = None

    @private
    def start_backdoor(self):
        self.backdoor_server = BackdoorServer(
            ('127.0.0.1', 9999),
            banner='DebugService backdoor server',
            locals={
                'dispatcher': self.dispatcher
            }
        )

        gevent.spawn(self.backdoor_server.serve_forever)

    @private
    def stop_backdoor(self):
        if self.backdoor_server:
            self.backdoor_server.close()
            self.backdoor_server = None

    @private
    def start_tracemalloc(self):
        tracemalloc.start()

    @private
    def stop_tracemalloc(self):
        tracemalloc.stop()

    @private
    def snapshot_tracemalloc(self):
        snap = tracemalloc.take_snapshot()
        return [str(i) for i in snap.statistics('lineno')[:100]]
Exemple #36
0
	def init(self):
		self.server = BackdoorServer(('localhost', self.config.port), locals={
			'clients': clients,
		})
		self.server.start()
Exemple #37
0
def main(stdscr, *args, **kwargs):
	global answer, feedback, candidates

	gevent.signal(signal.SIGUSR1, lambda *args: game_close.set()) # For standard/graceful restart
#	gevent.signal(signal.SIGINT, lambda *args: None) # Disable SIGINT
#	signal.signal(signal.SIGQUIT, signal.SIG_IGN) # Disable SIGQUIT
#	signal.signal(signal.SIGTSTP, signal.SIG_IGN) # Disable SIGTSTP

	logging.info("Window bounds: %s", stdscr.getmaxyx())

	backdoor = BackdoorServer(('0.0.0.0', 4200))
	backdoor.start()
	logging.info("Backdoor started")

	curses.curs_set(0) # Cursor invisible
	stdscr.nodelay(1) # Nonblocking input
	MAXY, MAXX = stdscr.getmaxyx()

	curses.init_pair(PAIR_MAIN, *DEFAULT_COLORS)
	curses.init_pair(PAIR_AI, curses.COLOR_RED, curses.COLOR_BLACK)
	curses.init_pair(PAIR_FEEDBACK, curses.COLOR_WHITE, curses.COLOR_BLACK)
	curses.init_pair(PAIR_TAGGED, curses.COLOR_YELLOW, curses.COLOR_BLACK)

	rightscr = stdscr.subwin(0, SPLIT)
	leftscr = stdscr.subwin(VERTSPLIT, SPLIT, 0, 0)

	logging.info("Right screen from %s, size %s", rightscr.getbegyx(), rightscr.getmaxyx())
	logging.info("Left screen from %s, size %s", leftscr.getbegyx(), leftscr.getmaxyx())

	feedback = SlowtypeWindow((VERTSPLIT, 1), (MAXY - VERTSPLIT - 1, SPLIT - 1))

	answer = random.choice(get_words(WORDS_PATH))
	candidates = get_closest(answer, WORDS_PATH, NUM_CANDIDATES - 1) + [answer]

	shuffle_main(leftscr, candidates)

	g_key_handler = spawn(key_handler, stdscr, leftscr)
	first_key.wait()
	g_chatter = spawn(timed_chat, rightscr, MAXY - 2)

	won = game_win_state.get()

	do_ai_fast.set()
	ai_done.wait()

	g_key_handler.kill()
	g_chatter.kill()
	feedback.wait()

	if not won:
		end(stdscr, "LOSS")

	attr = curses.color_pair(PAIR_MAIN)
	leftscr.move(0,0)
	leftscr.clear()
	leftscr.addstr("""WARNING
Experiment 203 (Synthetic Reasoning, Combat)
 has breached containment.
Please select a course of action.
 (1) Isolate system and scrub disks (This will
      destroy all research on Experiment 203)
 (2) Release remaining locks, allow experiment
      full access to base (MAY BE DANGEROUS)
 (3) Activate Emergency Base Procedure XK-682

""", attr)
	leftscr.refresh()

	first = True
	while 1:
		c = gevent_getch(sys.stdin, stdscr)
		if c == ord('1'):
			end(stdscr, "DESTROY")
		elif c == ord('2'):
			end(stdscr, "RELEASE")
		elif c == ord('3') and first:
			first = False
			logging.info("User attempted to arm the nukes")
			n = 3
			leftscr.addstr("Arming nuclear warheads.\nActivation in ", attr)
			y,x = leftscr.getyx()
			for i in range(n, -1, -1):
				leftscr.move(y,x)
				leftscr.addstr("%d seconds..." % i, attr)
				leftscr.refresh()
				gevent.sleep(1)
			leftscr.addstr("\nERROR\nYou do not have security permissions\n to perform this action.", attr)
			leftscr.refresh()
Exemple #38
0
class Service(object):

    def __init__(self, shard=0):
        signal.signal(signal.SIGINT, lambda unused_x, unused_y: self.exit())

        self.name = self.__class__.__name__
        self.shard = shard
        self._my_coord = ServiceCoord(self.name, self.shard)

        # Dictionaries of (to be) connected RemoteServiceClients.
        self.remote_services = {}

        self.initialize_logging()

        # We setup the listening address for services which want to
        # connect with us.
        try:
            address = get_service_address(self._my_coord)
        except KeyError:
            raise ConfigError("Unable to find address for service %r. "
                              "Is it specified in core_services in cms.conf?" %
                              (self._my_coord,))

        self.rpc_server = StreamServer(address, self._connection_handler)
        self.backdoor = None

    def initialize_logging(self):
        """Set up additional logging handlers.

        What we do, in detail, is to add a logger to file (whose
        filename depends on the coords) and a remote logger to a
        LogService. We also attach the service coords to all log
        messages.

        """
        filter_ = ServiceFilter(self.name, self.shard)

        # Update shell handler to attach service coords.
        shell_handler.addFilter(filter_)

        # Determine location of log file, and make directories.
        log_dir = os.path.join(config.log_dir,
                               "%s-%d" % (self.name, self.shard))
        mkdir(config.log_dir)
        mkdir(log_dir)
        log_filename = "%d.log" % int(time.time())

        # Install a file handler.
        file_handler = FileHandler(os.path.join(log_dir, log_filename),
                                   mode='w', encoding='utf-8')
        if config.file_log_debug:
            file_log_level = logging.DEBUG
        else:
            file_log_level = logging.INFO
        file_handler.setLevel(file_log_level)
        file_handler.setFormatter(CustomFormatter(False))
        file_handler.addFilter(filter_)
        root_logger.addHandler(file_handler)

        # Provide a symlink to the latest log file.
        try:
            os.remove(os.path.join(log_dir, "last.log"))
        except OSError:
            pass
        os.symlink(log_filename, os.path.join(log_dir, "last.log"))

        # Setup a remote LogService handler (except when we already are
        # LogService, to avoid circular logging).
        if self.name != "LogService":
            log_service = self.connect_to(ServiceCoord("LogService", 0))
            remote_handler = LogServiceHandler(log_service)
            remote_handler.setLevel(logging.INFO)
            remote_handler.addFilter(filter_)
            root_logger.addHandler(remote_handler)

    def _connection_handler(self, sock, address):
        """Receive and act upon an incoming connection.

        A new RemoteServiceServer is spawned to take care of the new
        connection.

        """
        try:
            ipaddr, port = address
            ipaddr = gevent.socket.gethostbyname(ipaddr)
            address = Address(ipaddr, port)
        except socket.error:
            logger.warning("Unexpected error.", exc_info=True)
            return
        remote_service = RemoteServiceServer(self, address)
        remote_service.handle(sock)

    def connect_to(self, coord, on_connect=None, on_disconnect=None,
                   must_be_present=True):
        """Return a proxy to a remote service.

        Obtain a communication channel to the remote service at the
        given coord (reusing an existing one, if possible), attach the
        on_connect and on_disconnect handlers and return it.

        coord (ServiceCoord): the coord of the service to connect to.
        on_connect (function|None): to be called when the service
            connects.
        on_disconnect (function|None): to be called when it
            disconnects.
        must_be_present (bool): if True, the coord must be present in
            the configuration; otherwise, it can be missing and in
            that case the return value is a fake client (that is, a
            client that never connects and ignores all calls).

        return (RemoteServiceClient): a proxy to that service.

        """
        if coord not in self.remote_services:
            try:
                service = RemoteServiceClient(coord, auto_retry=0.5)
            except KeyError:
                # The coordinates are invalid: raise a ConfigError if
                # the service was needed, or return a dummy client if
                # the service was optional.
                if must_be_present:
                    raise ConfigError("Missing address and port for %s "
                                      "in cms.conf." % (coord, ))
                else:
                    service = FakeRemoteServiceClient(coord, None)
            service.connect()
            self.remote_services[coord] = service
        else:
            service = self.remote_services[coord]

        if on_connect is not None:
            service.add_on_connect_handler(on_connect)

        return service

    def add_timeout(self, func, plus, seconds, immediately=False):
        """Register a function to be called repeatedly.

        func (function): the function to call.
        plus (object): additional data to pass to the function.
        seconds (float): the minimum interval between successive calls
            (may be larger if a call doesn't return on time).
        immediately (bool): whether to call right off or wait also
            before the first call.

        """
        if plus is None:
            plus = {}
        func = functools.partial(func, **plus)
        if immediately:
            gevent.spawn(repeater, func, seconds)
        else:
            gevent.spawn_later(seconds, repeater, func, seconds)

    def exit(self):
        """Terminate the service at the next step.

        """
        logger.warning("%r received request to shut down.", self._my_coord)
        self.rpc_server.stop()

    def get_backdoor_path(self):
        """Return the path for a UNIX domain socket to use as backdoor.

        """
        return os.path.join(config.run_dir, "%s_%d" % (self.name, self.shard))

    @rpc_method
    def start_backdoor(self, backlog=50):
        """Start a backdoor server on a local UNIX domain socket.

        """
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise
        else:
            logger.warning("A backdoor socket has been found and deleted.")
        mkdir(os.path.dirname(backdoor_path))
        backdoor_sock = _socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        backdoor_sock.setblocking(0)
        backdoor_sock.bind(backdoor_path)
        user = pwd.getpwnam("cmsuser")
        # We would like to also set the user to "cmsuser" but only root
        # can do that. Therefore we limit ourselves to the group.
        os.chown(backdoor_path, os.getuid(), user.pw_gid)
        os.chmod(backdoor_path, 0o770)
        backdoor_sock.listen(backlog)
        self.backdoor = BackdoorServer(backdoor_sock, locals={'service': self})
        self.backdoor.start()

    @rpc_method
    def stop_backdoor(self):
        """Stop a backdoor server started by start_backdoor.

        """
        if self.backdoor is not None:
            self.backdoor.stop()
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise

    def run(self):
        """Starts the main loop of the service.

        return (bool): True if successful.

        """
        try:
            self.rpc_server.start()

        # This must come before socket.error, because socket.gaierror
        # extends socket.error
        except socket.gaierror:
            logger.critical("Service %s could not listen on "
                            "specified address, because it cannot "
                            "be resolved.", self.name)
            return False

        except socket.error as error:
            if error.errno == errno.EADDRINUSE:
                logger.critical("Listening port %s for service %s is "
                                "already in use, quitting.",
                                self.rpc_server.address.port, self.name)
                return False
            elif error.errno == errno.EADDRNOTAVAIL:
                logger.critical("Service %s could not listen on "
                                "specified address, because it is not "
                                "available.", self.name)
                return False
            else:
                raise

        if config.backdoor:
            self.start_backdoor()

        logger.info("%s %d up and running!", *self._my_coord)

        # This call will block until self.rpc_server.stop() is called.
        self.rpc_server.serve_forever()

        logger.info("%s %d is shutting down", *self._my_coord)

        if config.backdoor:
            self.stop_backdoor()

        self._disconnect_all()
        return True

    def _disconnect_all(self):
        """Disconnect all remote services.

        """
        for service in self.remote_services.itervalues():
            if service.connected:
                service.disconnect()

    @rpc_method
    def echo(self, string):
        """Simple RPC method.

        string (string): the string to be echoed.
        return (string): string, again.

        """
        return string

    @rpc_method
    def quit(self, reason=""):
        """Shut down the service

        reason (string): why, oh why, you want me down?

        """
        logger.info("Trying to exit as asked by another service (%s).", reason)
        self.exit()
Exemple #39
0
                self.msg(user.nick, "Yahoo answers cannot answer %r" %
                         match.group(1))
                self.msg(user.nick, "Try: \"Does napping make you smarter?\"")
        else:
            self.msg(user.nick, "Can't understand your command: \"%s\"" %
                     message)


if __name__ == '__main__':
    from girclib.helpers import setup_logging
    setup_logging(level=5)
    client = YahooAnswerBot('irc.freenode.net', 6667, 'girclib', 'gIRClib')

    # Just for the fun, start telnet backdoor on port 2000
    from gevent.backdoor import BackdoorServer
    server = BackdoorServer(('127.0.0.1', 2000), locals=locals())
    server.start()

    @signals.on_signed_on.connect
    def _on_motd(emitter):
        log.info("Signed on. Let's join #ufs")
        client.join("#ufs")

    @signals.on_disconnected.connect
    def disconnected(emitter):
        log.info("Exited!?")
        try:
            gevent.shutdown()
        except AssertionError:
            # Shutting down is only possible from MAIN greenlet
            pass
Exemple #40
0
 def start_backdoor(self):
     from gevent.backdoor import BackdoorServer
     import gevent
     self.bds = BackdoorServer(('127.0.0.1', 12345))
     self.gr_bds = gevent.spawn(self.bds.serve_forever)
Exemple #41
0
class Dissonance(object):
    _name = None
    _web = None
    _manhole = None

    def __init__(self, config):
        opts_for = lambda name: EnvFallbackDict(name, getattr(config, '%s_opts' % name, {}))

        self._opts = EnvFallbackDict(None, getattr(config, 'dissonance_opts', {}))
        storage_class = get_storage_by_name(self._opts.get('storage', getattr(config, 'storage', 'shelve')))

        self.config = config
        self.client = Client()

        self._storage = storage_class(self, opts_for('storage'))
        self.modules = Modules(self)
        self._storage_sync_periodic = Periodic(int(self._opts.get('storage_sync_interval', 600)),
                                               self.modules._save_loaded_module_data)
        self._stop_event = Event()
        self._stop_event.set()

        self.client.events.on('message-create', self._handle_message)

    def _handle_message(self, message, client):
        if message.author == client.me:
            return

        # Schedule the handling of the message to occur during the next iteration of the event loop.
        gevent.spawn_raw(self.__handle_message, message)

    def __handle_message(self, message):
        logger.debug("Incoming message %r", message)
        start = time.time()

        message._dissonance = self
        message.targeting_client = message.content.startswith('doot, ')
        self.modules._handle_message(message)
        end = time.time()

        logger.debug("Took %.5f seconds to handle message %r", end - start, message)

    def _get_module_data(self, module):
        logger.debug("Getting module data for module %s", module.name)
        return self._storage.get_data_for_module_name(module.name)

    @property
    def name(self):
        return self.client.me.username

    @property
    def running(self):
        return not self._stop_event.is_set()

    @property
    def stopped(self):
        return not self.running

    @property
    def version(self):
        return version

    def run(self, auto_join=False):
        """
            Runs Dissonance, loading all the modules, starting the web service, and starting the adapter.

            If auto_join=True, this function will not return, and will run until dissonance stops if starting dissonance from
            outside of a greenlet.

        """
        if self.running:
            raise RuntimeError("Dissonance is already running!")

        logger.info("Starting Dissonance v%s", self.version)

        logger.info("Starting storage %s", self._storage)
        self._storage.start()

        logger.info("Loading modules")
        self.modules.load_all()

        if getattr(self.config, 'web', False) or str(self._opts.get('web', False)).upper() == 'TRUE':
            self._web = Web(self, EnvFallbackDict('web', getattr(self.config, 'web_opts', {})))
            self._web.start()

        if getattr(self.config, 'manhole', False):
            from gevent.backdoor import BackdoorServer
            manhole_opts = EnvFallbackDict('manhole', getattr(self.config, 'manhole_opts', {}))
            self._manhole = BackdoorServer((
                manhole_opts.get('listen_host', '127.0.0.1'),
                int(manhole_opts.get('listen_port', 9001))
            ), locals={
                'client': self.client
            })

            self._manhole.start()

        logger.info("Attempting to log in as %s" % self._opts['email'])
        self.client.login(self._opts['email'], self._opts['password'])
        logger.info("Starting connection to Discord")
        self.client.start()
        self._storage_sync_periodic.start(right_away=False)
        self._stop_event.clear()

        # If we are the main greenlet, chances are we probably want to never return,
        # so the main greenlet won't exit, and tear down everything with it.
        if auto_join and gevent.get_hub().parent == gevent.getcurrent():
            self.join()

    def join(self, timeout=None):
        """
            Blocks until Dissonance is stopped.
        """
        if self.stopped:
            raise RuntimeError("Dissonance is not running!")

        self._stop_event.wait(timeout)

    def stop(self):
        """
            Stops dissonance, turning off the web listener, unloading modules, and stopping the adapter.
        """
        if self.stopped:
            raise RuntimeError("Dissonance is not running!")

        logger.info('Stopping Dissonance')
        try:
            self.modules.unload_all()

            if self._web:
                self._web.stop()
                self._web = None

            if self._manhole:
                self._manhole.stop()
                self._manhole = None

            self.client.stop()
            self._storage_sync_periodic.stop()
            self._storage.stop()

        finally:
            self._stop_event.set()

    def on_module_error(self, module, e):
        print(module, e)
Exemple #42
0
class Service(object):

    def __init__(self, shard=0):
        signal.signal(signal.SIGINT, lambda unused_x, unused_y: self.exit())

        self.name = self.__class__.__name__
        self.shard = shard

        cms.log.initialize_logging(self.name, self.shard)

        # Stores the function to call periodically. It is to be
        # managed with heapq. Format: (next_timeout, period, function,
        # plus)
        self._timeouts = []
        # Whether we want to exit the main loop
        self._exit = False
        # Dictionaries of (to be) connected RemoteService, and
        # dictionaries of callback functions that are going to be
        # called every time the remote service becomes online.
        self.remote_services = {}
        self.on_remote_service_connected = {}
        # Event to signal that something happened and the sleeping in
        # run() must be interrupted
        self.event = gevent.event.Event()
        self.event.clear()

        self._my_coord = ServiceCoord(self.name, self.shard)

        # We setup the listening address for services which want to
        # connect with us.
        try:
            address = get_service_address(self._my_coord)
        except KeyError:
            address = None
        if address is not None:
            self.server = StreamServer(address, self._connection_handler)
            self.backdoor = None

    def _connection_handler(self, socket, address):
        """Receive and act upon an incoming connection.

        A new RemoteService is spawned to take care of the new
        connection.

        """
        try:
            ipaddr, port = address
            ipaddr = gevent.socket.gethostbyname(ipaddr)
            address = Address(ipaddr, port)
        except:
            logger.warning("Error: %s" % (traceback.format_exc()))
            return
        remote_service = RemoteService(self, address=address)
        remote_service.initialize_channel(socket)

    def connect_to(self, service, on_connect=None):
        """Ask the service to connect to another service. A channel is
        established and connected. The connection will be reopened if
        closed.

        service (ServiceCoord): the service to connect to.
        on_connect (function): to be called when the service connects.
        return (RemoteService): the connected RemoteService istance.

        """
        self.on_remote_service_connected[service] = on_connect
        self.remote_services[service] = RemoteService(self, service)
        return self.remote_services[service]

    def add_timeout(self, func, plus, seconds, immediately=False):
        """Registers a function to be called every x seconds.

        func (function): the function to call.
        plus (object): additional data to pass to the function.
        seconds (float): the function will be called every seconds
                         seconds.
        immediately (bool): if True, func will be called also at the
                            beginning.

        """
        next_timeout = monotonic_time()
        if not immediately:
            next_timeout += seconds
        heapq.heappush(self._timeouts, (next_timeout, seconds, func, plus))

        # Wake up the run() cycle
        self.event.set()

    def exit(self):
        """Terminate the service at the next step.

        """
        logger.warning("%s %d received request to shut down" % self._my_coord)
        self._exit = True

        # Wake up the run() cycle
        self.event.set()

    def get_backdoor_path(self):
        """Return the path for a UNIX domain socket to use as backdoor.

        """
        return os.path.join(config.run_dir, "%s_%d" % (self.name, self.shard))

    @rpc_method
    def start_backdoor(self, backlog=50):
        """Start a backdoor server on a local UNIX domain socket.

        """
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise
        else:
            logger.warning("A backdoor socket has been found and deleted.")
        mkdir(os.path.dirname(backdoor_path))
        backdoor_sock = _socket.socket(_socket.AF_UNIX, _socket.SOCK_STREAM)
        backdoor_sock.setblocking(0)
        backdoor_sock.bind(backdoor_path)
        user = pwd.getpwnam("cmsuser")
        # We would like to also set the user to "cmsuser" but only root
        # can do that. Therefore we limit ourselves to the group.
        os.chown(backdoor_path, os.getuid(), user.pw_gid)
        os.chmod(backdoor_path, 0o770)
        backdoor_sock.listen(backlog)
        self.backdoor = BackdoorServer(backdoor_sock, locals={'service': self})
        self.backdoor.start()

    @rpc_method
    def stop_backdoor(self):
        """Stop a backdoor server started by start_backdoor.

        """
        if self.backdoor is not None:
            self.backdoor.stop()
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise

    def run(self):
        """Starts the main loop of the service.

        return (bool): True if successful.

        """
        try:
            self.server.start()

        # This must come before socket.error, because socket.gaierror
        # extends socket.error
        except gevent.socket.gaierror:
            logger.critical("Service %s could not listen on "
                            "specified address, because it cannot "
                            "be resolved." % (self.name))
            return False

        except gevent.socket.error as (error, unused_msg):
            if error == errno.EADDRINUSE:
                logger.critical("Listening port %s for service %s is "
                                "already in use, quitting." %
                                (self.server.address.port,
                                 self.name))
                return False
            elif error == errno.EADDRNOTAVAIL:
                logger.critical("Service %s could not listen on "
                                "specified address, because it is not "
                                "available." % (self.name))
                return False
            else:
                raise

        if config.backdoor:
            self.start_backdoor()

        logger.info("%s %d up and running!" % self._my_coord)

        try:
            while not self._exit:
                next_timeout = self._trigger(maximum=0.5)
                self.event.clear()
                self.event.wait(timeout=next_timeout)
        except Exception as error:
            err_msg = "Exception not managed, quitting. " \
                      "Exception `%s' and traceback `%s'" % \
                      (repr(error), traceback.format_exc())
            logger.critical(err_msg)

        logger.info("%s %d is shutting down" % self._my_coord)

        if config.backdoor:
            self.stop_backdoor()

        self._disconnect_all()
        self.server.stop()
        return True
Exemple #43
0
 def start_backdoor(self):
     from gevent.backdoor import BackdoorServer
     import gevent
     self.bds = BackdoorServer(('127.0.0.1', 12345))
     self.gr_bds = gevent.spawn(self.bds.serve_forever)
Exemple #44
0
def main(json_helper = _JSON_HELPER):
    """main event loop"""
    # catch redis errors and keyboard interrupts
    logging.info('Worker started')
    if BACKDOOR_PORT:
        backdoor = BackdoorServer(('127.0.0.1', BACKDOOR_PORT),
                dict(globals()))
        logging.info('Backdoor server at 127.0.0.1:%d', BACKDOOR_PORT)
        backdoor.start()
    try:
        REDIS.sadd(WORKER_LIST, _PID)
        # main loop
        worker_pool = gevent.pool.Pool(WORKER_THREADS)
        while True:
            # if we're no longer welcome, break out of the main loop
            if not REDIS.sismember(WORKER_LIST, _PID):
                logging.info(
                    'Worker PID released, waiting for threads, then exiting.')
                for thread in _THREADS:
                    thread.join()
                break

            # clean up completed tasks
            for thread in _THREADS:
                if thread.ready():
                    _THREADS.remove(thread)
                    WORKER_STATS.gthreads -= 1
                    logging.debug('GC: %s', thread)

            # yield for outstanding threads
            gevent.sleep()

            # grab the next request from the worker queue, or wait
            request = REDIS.blpop(WORKER_QUEUE, 5)
            if not request:
                # timeout waiting for request, lets us run the loop
                # again and check if we should still be here
                continue

            # request should be JSON
            try:
                request = json.loads(request[1])
            except ValueError:
                logging.error('Invalid JSON for request: %s', request[1])
                continue
            WORKER_STATS.requests.inc()

            # request should be a dict and have a request key with list val
            if (type(request) is not dict or
                    not request.has_key('method') or
                    type(request['method']) not in [unicode, str]):
                logging.error('Missing or invalid method: %s', request)
                continue
            method = request['method']

            # decode the arguments
            args = request.get('args', [])
            kwargs = request.get('kwargs', {})
            reply_to = request.get('reply_channel', None)
            no_exec = request.get('no_exec', None)

            # attempt to resolve the requested function
            # keeping a cache of them along the way
            if _EXEC_CACHE.has_key(method):
                executable = _EXEC_CACHE[method]
            else:
                executable = route_to_class_or_function(
                    method)
                _EXEC_CACHE[method] = executable
            if not executable:
                logging.error('Failed to find class or function at %s',
                    method)
                if reply_to:
                    REDIS.rpush(reply_to, json.dumps({
                        'message' : \
                            'Failed to find class or function at %s' % (
                                method),
                        'response_code' : 404,
                        'error' : True}))
                continue

            # instantiate if we're dealing with a class
            if type(executable) is type:
                if issubclass(executable, prototype.Cacheable):
                    # inherits cacheable, we only need one
                    if not _INST_CACHE.has_key(method):
                        # we don't have one yet, so make one
                        _INST_CACHE[method] = executable()
                        logging.debug('New cacheable instance: %s',
                                _INST_CACHE[method])
                    instance = _INST_CACHE[method]
                else:
                    # instantiate a regular class every call
                    instance = executable()
                    logging.debug('New instance: %s', instance)
                # get the instance method we care about
                if hasattr(instance, method.split('.')[-1]):
                    func = getattr(instance, method.split('.')[-1])
                else:
                    logging.error('Failed to find class or function at %s',
                        method)
                    if reply_to:
                        REDIS.rpush(reply_to, json.dumps({
                            'message' : \
                                'Failed to find class or function at %s' % (
                                    method),
                            'response_code' : 404,
                            'error' : True}))
                    continue
            else:
                # a normal function (outside a class)
                func = executable

            # if no_exec, return just reference to object
            if no_exec:
                if reply_to:
                    REDIS.rpush(reply_to, json.dumps({
                        'found' : True,
                        'ref' : str(func)}))
                    continue

            # execute the function in a greenlet
            _THREADS.append(
                worker_pool.spawn(
                    child, func, args, kwargs, reply_to, json_helper))
            WORKER_STATS.gthreads += 1

    except redis.exceptions.ConnectionError, message:
        # redis isn't there or went away
        # wait 5 secs before exit to not upset upstart
        logging.error('Redis unavailable: %s', message)
        time.sleep(5)
        sys.exit(1)
Exemple #45
0
def start_server():

    def _exit_handler(*a, **k):
        gevent.kill(MAIN, SystemExit)
    sig(signal.SIGTERM, _exit_handler)

    from game import autoenv

    import argparse

    parser = argparse.ArgumentParser(prog=sys.argv[0])
    parser.add_argument('node', type=str)
    parser.add_argument('--host', default='0.0.0.0', type=str)
    parser.add_argument('--port', default=9999, type=int)
    parser.add_argument('--backdoor-host', default='127.0.0.1', type=str)
    parser.add_argument('--backdoor-port', default=19999, type=int)
    parser.add_argument('--no-backdoor', action='store_true')
    parser.add_argument('--freeplay', action='store_true')
    parser.add_argument('--log', default='INFO')
    parser.add_argument('--logfile', default='')
    parser.add_argument('--gidfile', default='')
    parser.add_argument('--credit-multiplier', type=float, default=1)
    parser.add_argument('--no-counting-flee', action='store_true')
    parser.add_argument('--archive-path', default='')
    parser.add_argument('--interconnect', action='store_true', default=False)
    parser.add_argument('--redis-url', default='redis://localhost:6379')
    parser.add_argument('--member-service', default='localhost:7000')
    options = parser.parse_args()

    import options as opmodule
    opmodule.options = options

    autoenv.init('Server')

    import settings

    class ServerLogFormatter(logging.Formatter):
        def format(self, rec):

            if rec.exc_info:
                s = []
                s.append('>>>>>>' + '-' * 74)
                s.append(self._format(rec))
                import traceback
                s.append(u''.join(traceback.format_exception(*rec.exc_info)).strip())
                s.append('<<<<<<' + '-' * 74)
                return u'\n'.join(s)
            else:
                return self._format(rec)

        def _format(self, rec):
            from game.autoenv import Game
            import time
            try:
                g = Game.getgame()
            except:
                g = gevent.getcurrent()

            gr_name = getattr(g, 'gr_name', None) or repr(g)
            gr_name = 'MAIN' if g is MAIN else gr_name

            return u'[%s %s %s] %s' % (
                rec.levelname[0],
                time.strftime('%y%m%d %H:%M:%S'),
                gr_name.decode('utf-8'),
                rec.msg % rec.args if isinstance(rec.msg, basestring) else repr((rec.msg, rec.args)),
            )

    fmter = ServerLogFormatter()

    root = logging.getLogger()

    root.setLevel(getattr(logging, options.log.upper()))
    std = logging.StreamHandler(stream=sys.stdout)
    std.setFormatter(fmter)
    root.handlers = []
    root.addHandler(std)

    if options.logfile:
        from logging.handlers import WatchedFileHandler
        filehdlr = WatchedFileHandler(options.logfile)
        filehdlr.setFormatter(fmter)
        root.addHandler(filehdlr)

    if not options.no_backdoor:
        from gevent.backdoor import BackdoorServer
        gevent.spawn(BackdoorServer((options.backdoor_host, options.backdoor_port)).serve_forever)

    from server.core import Client

    root.info('=' * 20 + settings.VERSION + '=' * 20)
    server = StreamServer((options.host, options.port), Client.spawn, None)
    server.serve_forever()
Exemple #46
0
class Server(object):
    """
    The instrument simulator server

    Handles a set of devices
    """
    def __init__(self, devices=(), backdoor=None):
        self._log = _log
        self._log.info("Bootstraping server")
        if backdoor:
            from gevent.backdoor import BackdoorServer

            banner = ("Welcome to Simulator server console.\n"
                      "You can access me through the "
                      "'server()' function. Have fun!")
            self.backdoor = BackdoorServer(
                backdoor, banner=banner, locals=dict(server=weakref.ref(self)))
            self.backdoor.start()
            self._log.info("Backdoor opened at %r", backdoor)
        else:
            self._log.info("no backdoor declared")

        self.devices = {}
        for device in devices:
            try:
                self.create_device(device)
            except Exception as error:
                dname = device.get("name", device.get("class", "unknown"))
                self._log.error(
                    "error creating device %s (will not be available): %s",
                    dname, error)
                self._log.debug("details: %s", error, exc_info=1)

    def create_device(self, device_info):
        klass_name = device_info.get("class")
        name = device_info.get("name", klass_name)
        self._log.info("Creating device %s (%r)", name, klass_name)
        device, transports = create_device(device_info)
        self.devices[device] = transports
        return device, transports

    def get_device_by_name(self, name):
        for device in self.devices:
            if device.name == name:
                return device

    def start(self):
        tasks = []
        for device in self.devices:
            for interface in self.devices[device]:
                tasks.append(gevent.spawn(interface.serve_forever))
        return tasks

    def stop(self):
        for device in self.devices:
            for transport in self.devices[device]:
                transport.stop()

    def serve_forever(self):
        tasks = self.start()
        try:
            gevent.joinall(tasks)
        finally:
            self.stop()

    def __str__(self):
        return "{0}({1})".format(self.__class__.__name__, self.name)
Exemple #47
0
class Service(object):

    def __init__(self, shard=0, listen_on_address=None):
        signal.signal(signal.SIGINT, lambda unused_x, unused_y: self.exit())

        self.name = self.__class__.__name__
        self.shard = shard
        self._my_coord = ServiceCoord(self.name, self.shard)

        # Dictionaries of (to be) connected RemoteServiceClients.
        self.remote_services = {}

        self.initialize_logging()

        # We setup the listening address for services which want to
        # connect with us.
        try:
            address = get_service_address(self._my_coord)
        except KeyError:
            raise ConfigError("Unable to find address for service %r. "
                              "Is it specified in core_services in cms.conf?" %
                              (self._my_coord,))

        logger.info("--- %s %s %s", self.name, listen_on_address, address)
        if listen_on_address is not None:
            self.rpc_server = StreamServer(
                Address(listen_on_address, address.port),
                self._connection_handler)
        else:
            self.rpc_server = StreamServer(address, self._connection_handler)
        self.backdoor = None

    def initialize_logging(self):
        """Set up additional logging handlers.

        What we do, in detail, is to add a logger to file (whose
        filename depends on the coords) and a remote logger to a
        LogService. We also attach the service coords to all log
        messages.

        """
        filter_ = ServiceFilter(self.name, self.shard)

        # Update shell handler to attach service coords.
        shell_handler.addFilter(filter_)

        # Determine location of log file, and make directories.
        log_dir = os.path.join(config.log_dir,
                               "%s-%d" % (self.name, self.shard))
        mkdir(config.log_dir)
        mkdir(log_dir)

        log_filename = time.strftime("%Y-%m-%d-%H-%M-%S.log")

        # Install a file handler.
        file_handler = FileHandler(os.path.join(log_dir, log_filename),
                                   mode='w', encoding='utf-8')
        if config.file_log_debug:
            file_log_level = logging.DEBUG
        else:
            file_log_level = logging.INFO
        file_handler.setLevel(file_log_level)
        file_handler.setFormatter(DetailedFormatter(False))
        file_handler.addFilter(filter_)
        root_logger.addHandler(file_handler)

        # Provide a symlink to the latest log file.
        try:
            os.remove(os.path.join(log_dir, "last.log"))
        except OSError:
            pass
        os.symlink(log_filename, os.path.join(log_dir, "last.log"))

        # Setup a remote LogService handler (except when we already are
        # LogService, to avoid circular logging).
        if self.name != "LogService":
            log_service = self.connect_to(ServiceCoord("LogService", 0))
            remote_handler = LogServiceHandler(log_service)
            remote_handler.setLevel(logging.INFO)
            remote_handler.addFilter(filter_)
            root_logger.addHandler(remote_handler)

    def _connection_handler(self, sock, address):
        """Receive and act upon an incoming connection.

        A new RemoteServiceServer is spawned to take care of the new
        connection.

        """
        logger.info("!!!!!!!! %s", address)
        try:
            ipaddr = address[0]
            port = address[1]
            logger.info("%s %s", ipaddr, port)
            ipaddr = gevent.socket.gethostbyname(ipaddr)
            address = Address(ipaddr, port)
        except socket.error:
            logger.warning("Unexpected error.", exc_info=True)
            return
        remote_service = RemoteServiceServer(self, address)
        remote_service.handle(sock)

    def connect_to(self, coord, on_connect=None, on_disconnect=None,
                   must_be_present=True):
        """Return a proxy to a remote service.

        Obtain a communication channel to the remote service at the
        given coord (reusing an existing one, if possible), attach the
        on_connect and on_disconnect handlers and return it.

        coord (ServiceCoord): the coord of the service to connect to.
        on_connect (function|None): to be called when the service
            connects.
        on_disconnect (function|None): to be called when it
            disconnects.
        must_be_present (bool): if True, the coord must be present in
            the configuration; otherwise, it can be missing and in
            that case the return value is a fake client (that is, a
            client that never connects and ignores all calls).

        return (RemoteServiceClient): a proxy to that service.

        """
        if coord not in self.remote_services:
            try:
                service = RemoteServiceClient(coord, auto_retry=0.5)
            except KeyError:
                # The coordinates are invalid: raise a ConfigError if
                # the service was needed, or return a dummy client if
                # the service was optional.
                if must_be_present:
                    raise ConfigError("Missing address and port for %s "
                                      "in cms.conf." % (coord, ))
                else:
                    service = FakeRemoteServiceClient(coord, None)
            service.connect()
            self.remote_services[coord] = service
        else:
            service = self.remote_services[coord]

        if on_connect is not None:
            service.add_on_connect_handler(on_connect)

        if on_disconnect is not None:
            service.add_on_disconnect_handler(on_disconnect)

        return service

    def add_timeout(self, func, plus, seconds, immediately=False):
        """Register a function to be called repeatedly.

        func (function): the function to call.
        plus (object): additional data to pass to the function.
        seconds (float): the minimum interval between successive calls
            (may be larger if a call doesn't return on time).
        immediately (bool): whether to call right off or wait also
            before the first call.

        """
        if plus is None:
            plus = {}
        func = functools.partial(func, **plus)
        if immediately:
            gevent.spawn(repeater, func, seconds)
        else:
            gevent.spawn_later(seconds, repeater, func, seconds)

    def exit(self):
        """Terminate the service at the next step.

        """
        logger.warning("%r received request to shut down.", self._my_coord)
        self.rpc_server.stop()

    def get_backdoor_path(self):
        """Return the path for a UNIX domain socket to use as backdoor.

        """
        return os.path.join(config.run_dir, "%s_%d" % (self.name, self.shard))

    @rpc_method
    def start_backdoor(self, backlog=50):
        """Start a backdoor server on a local UNIX domain socket.

        """
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise
        else:
            logger.warning("A backdoor socket has been found and deleted.")
        mkdir(os.path.dirname(backdoor_path))
        backdoor_sock = gevent.socket.socket(socket.AF_UNIX,
                                             socket.SOCK_STREAM)
        backdoor_sock.setblocking(0)
        backdoor_sock.bind(backdoor_path)
        user = pwd.getpwnam(config.cmsuser)
        # We would like to also set the user to "cmsuser" but only root
        # can do that. Therefore we limit ourselves to the group.
        os.chown(backdoor_path, os.getuid(), user.pw_gid)
        os.chmod(backdoor_path, 0o770)
        backdoor_sock.listen(backlog)
        self.backdoor = BackdoorServer(backdoor_sock, locals={'service': self})
        self.backdoor.start()

    @rpc_method
    def stop_backdoor(self):
        """Stop a backdoor server started by start_backdoor.

        """
        if self.backdoor is not None:
            self.backdoor.stop()
        backdoor_path = self.get_backdoor_path()
        try:
            os.remove(backdoor_path)
        except OSError as error:
            if error.errno != errno.ENOENT:
                raise

    def run(self):
        """Starts the main loop of the service.

        return (bool): True if successful.

        """
        try:
            self.rpc_server.start()

        # This must come before socket.error, because socket.gaierror
        # extends socket.error
        except socket.gaierror:
            logger.critical("Service %s could not listen on "
                            "specified address %s, because it cannot "
                            "be resolved.", self.name, self.rpc_server.address.ip)
            return False

        except socket.error as error:
            if error.errno == errno.EADDRINUSE:
                logger.critical("Listening port %s for service %s is "
                                "already in use, quitting.",
                                self.rpc_server.address.port, self.name)
                return False
            elif error.errno == errno.EADDRNOTAVAIL:
                logger.critical("Service %s could not listen on "
                                "specified address, because it is not "
                                "available.", self.name)
                return False
            else:
                raise

        if config.backdoor:
            self.start_backdoor()

        logger.info("%s %d up and running!", *self._my_coord)

        # This call will block until self.rpc_server.stop() is called.
        self.rpc_server.serve_forever()

        logger.info("%s %d is shutting down", *self._my_coord)

        if config.backdoor:
            self.stop_backdoor()

        self._disconnect_all()
        return True

    def _disconnect_all(self):
        """Disconnect all remote services.

        """
        for service in itervalues(self.remote_services):
            if service.connected:
                service.disconnect()

    @rpc_method
    def echo(self, string):
        """Simple RPC method.

        string (string): the string to be echoed.
        return (string): string, again.

        """
        return string

    @rpc_method
    def quit(self, reason=""):
        """Shut down the service

        reason (string): why, oh why, you want me down?

        """
        logger.info("Trying to exit as asked by another service (%s).", reason)
        self.exit()
Exemple #48
0
def main(stdscr, *args, **kwargs):
    global answer, feedback, candidates

    gevent.signal(
        signal.SIGUSR1,
        lambda *args: game_close.set())  # For standard/graceful restart
    #	gevent.signal(signal.SIGINT, lambda *args: None) # Disable SIGINT
    #	signal.signal(signal.SIGQUIT, signal.SIG_IGN) # Disable SIGQUIT
    #	signal.signal(signal.SIGTSTP, signal.SIG_IGN) # Disable SIGTSTP

    logging.info("Window bounds: %s", stdscr.getmaxyx())

    backdoor = BackdoorServer(('0.0.0.0', 4200))
    backdoor.start()
    logging.info("Backdoor started")

    curses.curs_set(0)  # Cursor invisible
    stdscr.nodelay(1)  # Nonblocking input
    MAXY, MAXX = stdscr.getmaxyx()

    curses.init_pair(PAIR_MAIN, *DEFAULT_COLORS)
    curses.init_pair(PAIR_AI, curses.COLOR_RED, curses.COLOR_BLACK)
    curses.init_pair(PAIR_FEEDBACK, curses.COLOR_WHITE, curses.COLOR_BLACK)
    curses.init_pair(PAIR_TAGGED, curses.COLOR_YELLOW, curses.COLOR_BLACK)

    rightscr = stdscr.subwin(0, SPLIT)
    leftscr = stdscr.subwin(VERTSPLIT, SPLIT, 0, 0)

    logging.info("Right screen from %s, size %s", rightscr.getbegyx(),
                 rightscr.getmaxyx())
    logging.info("Left screen from %s, size %s", leftscr.getbegyx(),
                 leftscr.getmaxyx())

    feedback = SlowtypeWindow((VERTSPLIT, 1),
                              (MAXY - VERTSPLIT - 1, SPLIT - 1))

    answer = random.choice(get_words(WORDS_PATH))
    candidates = get_closest(answer, WORDS_PATH, NUM_CANDIDATES - 1) + [answer]

    shuffle_main(leftscr, candidates)

    g_key_handler = spawn(key_handler, stdscr, leftscr)
    first_key.wait()
    g_chatter = spawn(timed_chat, rightscr, MAXY - 2)

    won = game_win_state.get()

    do_ai_fast.set()
    ai_done.wait()

    g_key_handler.kill()
    g_chatter.kill()
    feedback.wait()

    if not won:
        end(stdscr, "LOSS")

    attr = curses.color_pair(PAIR_MAIN)
    leftscr.move(0, 0)
    leftscr.clear()
    leftscr.addstr(
        """WARNING
Experiment 203 (Synthetic Reasoning, Combat)
 has breached containment.
Please select a course of action.
 (1) Isolate system and scrub disks (This will
      destroy all research on Experiment 203)
 (2) Release remaining locks, allow experiment
      full access to base (MAY BE DANGEROUS)
 (3) Activate Emergency Base Procedure XK-682

""", attr)
    leftscr.refresh()

    first = True
    while 1:
        c = gevent_getch(sys.stdin, stdscr)
        if c == ord('1'):
            end(stdscr, "DESTROY")
        elif c == ord('2'):
            end(stdscr, "RELEASE")
        elif c == ord('3') and first:
            first = False
            logging.info("User attempted to arm the nukes")
            n = 3
            leftscr.addstr("Arming nuclear warheads.\nActivation in ", attr)
            y, x = leftscr.getyx()
            for i in range(n, -1, -1):
                leftscr.move(y, x)
                leftscr.addstr("%d seconds..." % i, attr)
                leftscr.refresh()
                gevent.sleep(1)
            leftscr.addstr(
                "\nERROR\nYou do not have security permissions\n to perform this action.",
                attr)
            leftscr.refresh()
Exemple #49
0
#!/usr/bin/env python
#!encoding=utf8

from gevent.backdoor import BackdoorServer
BackdoorServer(('127.0.0.1', 9000)).serve_forever()
Exemple #50
0
class Server(object):
    """
    The emulation server

    Handles a set of devices
    """

    def __init__(self, name='', devices=(), backdoor=None):
        self.name = name
        self._log = logging.getLogger('{0}.{1}'.format(_log.name, name))
        self._log.info('Bootstraping server')
        if backdoor:
            from gevent.backdoor import BackdoorServer
            banner = 'Welcome to Bliss emulator server console.\n' \
                     'My name is {0!r}. You can access me through the ' \
                     '\'server()\' function. Have fun!'.format(name)
            self.backdoor = BackdoorServer(backdoor, banner=banner,
                                           locals=dict(server=weakref.ref(self)))
            self.backdoor.start()
            self._log.info('Backdoor opened at %r', backdoor)

        else:
            self._log.info('no backdoor declared')

        self.devices = {}
        for device in devices:
            try:
                self.create_device(device)
            except Exception as error:
                dname = device.get('name', device.get('class', 'unknown'))
                self._log.error('error creating device %s (will not be available): %s',
                                dname, error)
                self._log.debug('details: %s', error, exc_info=1)

    def terminate(self):
        for device in self.devices:
            for tp in device.transports:
                tp.terminate()

    def create_device(self, device_info):
        klass_name = device_info.get('class')
        name = device_info.get('name', klass_name)
        self._log.info('Creating device %s (%r)', name, klass_name)
        device, transports = create_device(device_info)
        self.devices[device] = transports
        return device, transports

    def get_device_by_name(self, name):
        for device in self.devices:
            if device.name == name:
                return device

    def start(self):
        for device in self.devices:
            for interface in self.devices[device]:
                interface.start()

    def stop(self):
        for device in self.devices:
            for interface in self.devices[device]:
                interface.stop()

    def serve_forever(self):
        stop_events = []
        for device in self.devices:
            for interface in self.devices[device]:
                stop_events.append(interface._stop_event)
        self.start()
        try:
            gevent.joinall(stop_events)
        finally:
            self.stop()

    def __str__(self):
        return '{0}({1})'.format(self.__class__.__name__, self.name)