Example #1
0
    def onJoin(self, details):
        """
        Called when worker process has joined the node's management realm.
        """
        yield NativeWorkerSession.onJoin(self, details, publish_ready=False)

        # Jinja2 templates for Web (like WS status page et al)
        #
        templates_dir = os.path.abspath(
            pkg_resources.resource_filename("crossbar", "web/templates"))
        if self.debug:
            log.msg("Using Web templates from {}".format(templates_dir))
        self._templates = jinja2.Environment(
            loader=jinja2.FileSystemLoader(templates_dir))

        # factory for producing (per-realm) routers
        self.factory = CrossbarRouterFactory()

        # factory for producing router sessions
        self.session_factory = CrossbarRouterSessionFactory(self.factory)

        # map: realm ID -> RouterRealm
        self.realms = {}

        # map: realm URI -> realm ID
        self.realm_to_id = {}

        # map: transport ID -> RouterTransport
        self.transports = {}

        # map: link ID -> RouterLink
        self.links = {}

        # map: component ID -> RouterComponent
        self.components = {}

        # the procedures registered
        procs = [
            'get_router_realms', 'start_router_realm', 'stop_router_realm',
            'get_router_realm_roles', 'start_router_realm_role',
            'stop_router_realm_role', 'get_router_components',
            'start_router_component', 'stop_router_component',
            'get_router_transports', 'start_router_transport',
            'stop_router_transport', 'get_router_links', 'start_router_link',
            'stop_router_link'
        ]

        dl = []
        for proc in procs:
            uri = '{}.{}'.format(self._uri_prefix, proc)
            if self.debug:
                log.msg("Registering procedure '{}'".format(uri))
            dl.append(
                self.register(getattr(self, proc),
                              uri,
                              options=RegisterOptions(details_arg='details')))

        regs = yield DeferredList(dl)

        if self.debug:
            log.msg("RouterWorker registered {} procedures".format(len(regs)))

        # NativeWorkerSession.publish_ready()
        yield self.publish_ready()
Example #2
0
        def on_registration_create(reg_id, reg_details, details=None):
            """
            Event handler fired when a new registration was created on this router.

            The handler will then also register on the other router, and when receiving
            calls, re-issue those on this router.

            :param reg_id:
            :param reg_details:
            :param details:
            :return:
            """
            # FIXME
            if False and reg_id in self._regs:
                # this should not happen actually, but not sure ..
                self.log.error(
                    'on_registration_create: reg ID {reg_id} already in map {method}',
                    reg_id=reg_id,
                    method=hltype(BridgeSession._setup_invocation_forwarding))
                return

            self._regs[reg_id] = reg_details

            uri = reg_details['uri']
            ERR_MSG = [None]

            @inlineCallbacks
            def on_call(*args, **kwargs):

                assert 'details' in kwargs

                details = kwargs.pop('details')
                options = kwargs.pop('options', None)

                if details.caller is None:
                    raise RuntimeError(
                        "No 'details.caller' while attempting rlink forwarding"
                    )
                if details.caller_authid is None:
                    raise RuntimeError(
                        "No 'details.caller_authid' while attempting rlink forwarding"
                    )
                if details.caller_authrole is None:
                    raise RuntimeError(
                        "No 'details.caller_authrole' while attempting rlink forwarding"
                    )

                self.log.info(
                    'Received invocation on uri={uri}, options={options} (caller={caller}, caller_authid={caller_authid}, caller_authrole={caller_authrole}, forward_for={forward_for})',
                    uri=uri,
                    options=options,
                    caller=details.caller,
                    caller_authid=details.caller_authid,
                    caller_authrole=details.caller_authrole,
                    forward_for=details.forward_for)

                this_forward = {
                    'session': details.caller,
                    'authid': details.caller_authrole,
                    'authrole': details.caller_authrole,
                }

                if details.forward_for:
                    # the call comes already forwarded from a router node ..
                    if len(details.forward_for) >= 0:
                        self.log.debug('SKIP! already forwarded')
                        return

                    forward_for = copy.deepcopy(details.forward_for)
                    forward_for.append(this_forward)
                else:
                    forward_for = [this_forward]

                options = CallOptions(forward_for=forward_for)

                try:
                    result = yield self.call(uri,
                                             *args,
                                             options=options,
                                             **kwargs)
                except TransportLost:
                    return
                except ApplicationError as e:
                    if e.error not in ['wamp.close.normal']:
                        self.log.warn('FAILED TO CALL 1: {} {}'.format(
                            type(e), str(e)))
                    return
                except Exception as e:
                    if not ERR_MSG[0]:
                        self.log.warn('FAILED TO CALL 2: {} {}'.format(
                            type(e), str(e)))
                        ERR_MSG[0] = True
                    return

                self.log.info(
                    "RLink forward-invoked call {dir} (options={options})",
                    dir=self.DIR,
                    options=options,
                )
                return result

            # FIXME
            n = 300
            reg = None
            while n > 0:
                try:
                    reg = yield other.register(on_call,
                                               uri,
                                               options=RegisterOptions(
                                                   details_arg='details',
                                                   invoke=reg_details.get(
                                                       'invoke', None)))
                except:
                    self.log.failure()
                    from autobahn.twisted.util import sleep
                    yield sleep(1)
                    n -= 1
                else:
                    break

            if not reg:
                raise Exception('fatal: could not forward-register')

            self._regs[reg_id]['reg'] = reg

            self.log.info(
                "created forwarding registration: me={me} other={other} reg_id={reg_id} reg_details={reg_details} details={details}",
                me=self,
                other=other,
                reg_id=reg_id,
                reg_details=reg_details,
                details=details,
            )
Example #3
0
    async def onJoin(self, details):
        await self.subscribe(self.on_session_join, 'wamp.session.on_join')
        await self.subscribe(
            self.on_session_leave, 'wamp.session.on_leave'
        )
        await self.register(
            self.attach,
            'org.labgrid.coordinator.attach',
            options=RegisterOptions(details_arg='details')
        )

        # resources
        await self.register(
            self.set_resource,
            'org.labgrid.coordinator.set_resource',
            options=RegisterOptions(details_arg='details')
        )
        await self.register(
            self.get_resources,
            'org.labgrid.coordinator.get_resources'
        )

        # places
        await self.register(
            self.add_place, 'org.labgrid.coordinator.add_place'
        )
        await self.register(
            self.del_place, 'org.labgrid.coordinator.del_place'
        )
        await self.register(
            self.add_place_alias, 'org.labgrid.coordinator.add_place_alias'
        )
        await self.register(
            self.del_place_alias, 'org.labgrid.coordinator.del_place_alias'
        )
        await self.register(
            self.set_place_tags, 'org.labgrid.coordinator.set_place_tags'
        )
        await self.register(
            self.set_place_comment, 'org.labgrid.coordinator.set_place_comment'
        )
        await self.register(
            self.add_place_match, 'org.labgrid.coordinator.add_place_match'
        )
        await self.register(
            self.del_place_match, 'org.labgrid.coordinator.del_place_match'
        )
        await self.register(
            self.acquire_place,
            'org.labgrid.coordinator.acquire_place',
            options=RegisterOptions(details_arg='details')
        )
        await self.register(
            self.release_place,
            'org.labgrid.coordinator.release_place',
            options=RegisterOptions(details_arg='details')
        )
        await self.register(
            self.allow_place,
            'org.labgrid.coordinator.allow_place',
            options=RegisterOptions(details_arg='details')
        )
        await self.register(
            self.get_places, 'org.labgrid.coordinator.get_places'
        )

        # reservations
        await self.register(
            self.create_reservation,
            'org.labgrid.coordinator.create_reservation',
            options=RegisterOptions(details_arg='details'),
        )
        await self.register(
            self.cancel_reservation,
            'org.labgrid.coordinator.cancel_reservation',
        )
        await self.register(
            self.poll_reservation,
            'org.labgrid.coordinator.poll_reservation',
        )
        await self.register(
            self.get_reservations,
            'org.labgrid.coordinator.get_reservations',
        )

        self.poll_task = asyncio.get_event_loop().create_task(self.poll())

        print("Coordinator ready.")
Example #4
0
    async def onJoin(self, details: ComponentConfig):

        # handles to controller database and schema (already initialized/attached in node)
        #
        ready = self.config.extra['ready']
        cbdir = self.config.extra['cbdir']
        config = self.config.extra.get('database', {})

        # create database and attach tables to database slots
        #
        dbpath = config.get('path', '.db-controller')
        assert type(dbpath) == str
        dbpath = os.path.join(cbdir, dbpath)

        maxsize = config.get('maxsize', 128 * 2**20)
        assert type(maxsize) == int
        # allow maxsize 128kiB to 128GiB
        assert maxsize >= 128 * 1024 and maxsize <= 128 * 2**30

        self.log.info('{klass} starting [dbpath={dbpath}, maxsize={maxsize}]',
                      klass=self.__class__.__name__,
                      dbpath=hlid(dbpath),
                      maxsize=hlid(maxsize))

        self._db = zlmdb.Database(dbpath=dbpath,
                                  maxsize=maxsize,
                                  readonly=False,
                                  sync=True)
        self._db.__enter__()
        self._schema = GlobalSchema.attach(self._db)

        # initialize all currently existing mrealms
        try:
            await self._initialize_mrealms()
        except Exception:
            self.log.failure()
            raise

        # expose api on this object fo CFC clients
        domains = [(_CFC_GLOBAL_REALM, self.register)]
        for prefix, register in domains:
            registrations = await register(
                self,
                prefix=prefix,
                options=RegisterOptions(details_arg='details'))
            for reg in registrations:
                if type(reg) == Registration:
                    self.log.info(
                        'Registered CFC Global Realm "{realm}" API <{proc}>',
                        proc=reg.procedure,
                        realm=self._realm)
                else:
                    self.log.error('Error: <{}>'.format(reg.value.args[0]))

        # we are ready to roll
        self.log.info('{note} {klass}',
                      note=hl('Ok, master node "{}" booted and ready!'.format(
                          self._node._node_id),
                              color='red',
                              bold=True),
                      klass=hltype(self.onJoin))

        ready.callback(self)
Example #5
0
    async def start(self, session):
        """
        Start rotating keys and placing key offers with the XBR market maker.

        :param session: WAMP session over which to communicate with the XBR market maker.
        :type session: :class:`autobahn.wamp.protocol.ApplicationSession`
        """
        assert isinstance(
            session, ApplicationSession
        ), 'session must be an ApplicationSession, was "{}"'.format(session)
        assert self._state in [
            SimpleSeller.STATE_NONE, SimpleSeller.STATE_STOPPED
        ], 'seller already running'

        self._state = SimpleSeller.STATE_STARTING
        self._session = session
        self._session_regs = []

        self.log.debug(
            'Start selling from seller delegate address {address} (public key 0x{public_key}..)',
            address=hl(self._caddr),
            public_key=binascii.b2a_hex(self._pkey.public_key[:10]).decode())

        # get the currently active (if any) paying channel for the delegate
        self._channel = await session.call(
            'xbr.marketmaker.get_active_paying_channel', self._addr)
        if not self._channel:
            raise Exception('no active paying channel found')

        channel_oid = self._channel['channel_oid']
        assert type(channel_oid) == bytes and len(channel_oid) == 16
        self._channel_oid = uuid.UUID(bytes=channel_oid)

        procedure = 'xbr.provider.{}.sell'.format(self._provider_id)
        reg = await session.register(
            self.sell,
            procedure,
            options=RegisterOptions(details_arg='details'))
        self._session_regs.append(reg)
        self.log.debug('Registered procedure "{procedure}"',
                       procedure=hl(reg.procedure))

        procedure = 'xbr.provider.{}.close_channel'.format(self._provider_id)
        reg = await session.register(
            self.close_channel,
            procedure,
            options=RegisterOptions(details_arg='details'))
        self._session_regs.append(reg)
        self.log.debug('Registered procedure "{procedure}"',
                       procedure=hl(reg.procedure))

        for key_series in self._keys.values():
            await key_series.start()

        self._xbrmm_config = await session.call('xbr.marketmaker.get_config')

        # get the current (off-chain) balance of the paying channel
        paying_balance = await session.call(
            'xbr.marketmaker.get_paying_channel_balance',
            self._channel_oid.bytes)
        # FIXME
        if type(paying_balance['remaining']) == bytes:
            paying_balance['remaining'] = unpack_uint256(
                paying_balance['remaining'])

        if not paying_balance['remaining'] > 0:
            raise Exception('no off-chain balance remaining on paying channel')

        self._channels[channel_oid] = PayingChannel(
            channel_oid, paying_balance['seq'], paying_balance['remaining'])
        self._state = SimpleSeller.STATE_STARTED

        # FIXME
        self._balance = paying_balance['remaining']
        if type(self._balance) == bytes:
            self._balance = unpack_uint256(self._balance)
        self._seq = paying_balance['seq']

        self.log.info(
            'Ok, seller delegate started [active paying channel {channel_oid} with remaining balance {remaining} at sequence {seq}]',
            channel_oid=hl(self._channel_oid),
            remaining=hlval(self._balance),
            seq=hlval(self._seq))

        return paying_balance['remaining']
Example #6
0
    def onJoin(self, details):

        ## When a (native) worker process has connected back to the router of
        ## the node controller, the worker will publish this event
        ## to signal it's readyness.
        ##
        def on_worker_ready(res):
            id = res['id']
            if id in self._workers:
                ready = self._workers[id].ready
                if not ready.called:
                    ## fire the Deferred previously stored for
                    ## signaling "worker ready"
                    ready.callback(id)
                else:
                    log.msg(
                        "INTERNAL ERROR: on_worker_ready() fired for process {} - ready already called"
                        .format(id))
            else:
                log.msg(
                    "INTERNAL ERROR: on_worker_ready() fired for process {} - no process with that ID"
                    .format(id))

        self.subscribe(
            on_worker_ready,
            'crossbar.node.{}.on_worker_ready'.format(self._node_id))

        yield NativeProcessSession.onJoin(self, details)

        ## register node controller procedures: 'crossbar.node.<ID>.<PROCEDURE>'
        ##
        procs = [
            'shutdown',
            'start_management_transport',
            'get_info',
            'get_workers',
            'get_worker_log',
            'start_router',
            'stop_router',
            'start_container',
            'stop_container',
            'start_guest',
            'stop_guest',
        ]

        dl = []
        for proc in procs:
            uri = '{}.{}'.format(self._uri_prefix, proc)
            if self.debug:
                log.msg("Registering procedure '{}'".format(uri))
            dl.append(
                self.register(getattr(self, proc),
                              uri,
                              options=RegisterOptions(details_arg='details',
                                                      discloseCaller=True)))

        regs = yield DeferredList(dl)

        if self.debug:
            log.msg("{} registered {} procedures".format(
                self.__class__.__name__, len(regs)))
Example #7
0
    def onJoin(self, details):

        self.log.info("Joined realm '{realm}' on node management router",
                      realm=details.realm)

        # When a (native) worker process has connected back to the router of
        # the node controller, the worker will publish this event
        # to signal it's readyness.
        #
        def on_worker_ready(res):
            id = res['id']
            if id in self._workers:
                ready = self._workers[id].ready
                if not ready.called:
                    # fire the Deferred previously stored for
                    # signaling "worker ready"
                    ready.callback(id)
                else:
                    self.log.error(
                        "Internal error: on_worker_ready() fired for process {process}, but already called earlier",
                        process=id)
            else:
                self.log.error(
                    "Internal error: on_worker_ready() fired for process {process}, but no process with that ID",
                    process=id)

        self.subscribe(
            on_worker_ready,
            'crossbar.node.{}.on_worker_ready'.format(self._node_id))

        yield NativeProcessSession.onJoin(self, details)

        # register node controller procedures: 'crossbar.node.<ID>.<PROCEDURE>'
        #
        procs = [
            'shutdown',
            'get_info',
            'get_workers',
            'get_worker_log',
            'start_router',
            'stop_router',
            'start_container',
            'stop_container',
            'start_guest',
            'stop_guest',
        ]

        dl = []
        for proc in procs:
            uri = '{}.{}'.format(self._uri_prefix, proc)
            self.log.debug("Registering management API procedure {proc}",
                           proc=uri)
            dl.append(
                self.register(getattr(self, proc),
                              uri,
                              options=RegisterOptions(details_arg='details')))

        regs = yield DeferredList(dl)

        self.log.debug("Registered {cnt} management API procedures",
                       cnt=len(regs))

        self._started = utcnow()

        self.publish(u"crossbar.node.on_ready", self._node_id)

        self.log.debug("Node controller ready")
    def onJoin(self, details):
        self._max_concurrency = 10
        self._current_concurrency = 0
        self._invocations_served = 0
        self.user_list = user_list()

        arg_kws = ['color']

        reactor.suggestThreadPoolSize(self._max_concurrency)
        verb_translations = {
            'unhide': 'show',
            'color': 'setcolor',
            'keep': 'remove',
            'blink': 'animate',
            'unblink': 'unanimate'
        }

        @inlineCallbacks
        def na_query(task, details=None):
            self._invocations_served += 1
            self._current_concurrency += 1

            if not isinstance(task, dict):
                task = json.loads(task)
            task = byteify(task)

            user_id = task['user'] if (details.caller_authrole == 'processor' and 'user' in task) \
                      else details.caller
            threshold = None
            if details.progress or 'data_callback_uri' in task: threshold = 100
            if 'verb' in task and task['verb'] not in ['add', 'show']:
                threshold = None
            self.log.info(
                "na_query() called with task: {task} ,(current concurrency {current_concurrency} of max {max_concurrency})",
                current_concurrency=self._current_concurrency,
                max_concurrency=self._max_concurrency,
                task=task)

            server = self.user_list.user(user_id)['server']
            (res, succ) = yield threads.deferToThread(server.receive_task,
                                                      task, threshold)
            if (not details.caller_authrole == 'processor'):
                try:
                    del task['user_msg']
                except:
                    pass
            if 'user_msg' in task:
                if succ:
                    yield self.call(task['user_msg'], {
                        'info': {
                            'success': 'Fetching results from NeuroArch'
                        }
                    })
                else:
                    yield self.call(task['user_msg'], {
                        'info': {
                            'error': 'Error executing query on NeuroArch'
                        }
                    })
            if ('data_callback_uri' in task):
                if ('verb' in task and task['verb'] not in ['add', 'show']):
                    try:
                        task['verb'] = verb_translations[task['verb']]
                    except Exception as e:
                        print e
                        pass

                    try:
                        uri = task['user_msg']
                    except:
                        uri = 'ffbo.ui.receive_msg.%s' % user_id
                    args = []
                    if 'color' in task: task['color'] = '#' + task['color']
                    for kw in arg_kws:
                        if kw in task: args.append(task[kw])
                    if len(args) == 1: args = args[0]
                    yield self.call(uri,
                                    {'commands': {
                                        task['verb']: [res, args]
                                    }})
                    yield self.call(
                        uri,
                        {'info': {
                            'success': 'Finished processing command'
                        }})
                else:
                    uri = task['data_callback_uri'] + '.%s' % user_id
                    for c in res:
                        try:
                            succ = yield self.call(uri, c)
                        except ApplicationError as e:
                            print e

                self.na_query_on_end()
                returnValue(succ)
            else:
                if details.progress:
                    for c in res:
                        details.progress(c)
                    self.na_query_on_end()
                    returnValue({
                        'success': {
                            'info':
                            'Finished fetching all results from database'
                        }
                    })
                else:
                    self.na_query_on_end()
                    returnValue({
                        'success': {
                            'info':
                            'Finished fetching all results from database',
                            'data': res
                        }
                    })

        uri = 'ffbo.na.query.%s' % str(details.session)
        yield self.register(
            na_query, uri,
            RegisterOptions(details_arg='details',
                            concurrency=self._max_concurrency))

        # Register a function to retrieve a single neuron information
        def retrieve_neuron(nid):
            self.log.info("retrieve_neuron() called with neuron id: {nid} ",
                          nid=nid)
            res = server.retrieve_neuron(nid)
            print "retrieve neuron result: " + str(res)
            return res

        uri = 'ffbo.na.retrieve_neuron.%s' % str(details.session)
        yield self.register(retrieve_neuron, uri,
                            RegisterOptions(concurrency=self._max_concurrency))
        print "registered %s" % uri

        #######################
        @inlineCallbacks
        def retrieve_by_id(task, details=None):
            # task is a dictionary of {key_type:string, key:string, user:string}
            self._invocations_served += 1
            self._current_concurrency += 1

            if not isinstance(task, dict):
                task = json.loads(task)
            task = byteify(task)

            user_id = task['user'] if (details.caller_authrole == 'processor' and 'user' in task) \
                      else details.caller
            threshold = None

            if details.progress or 'data_callback_uri' in task: threshold = 100

            server = self.user_list.user(user_id)['server']

            (res, succ) = yield threads.deferToThread(server.retrieve_by_id,
                                                      task, threshold)

            if (not details.caller_authrole == 'processor'):
                try:
                    del task['user_msg']
                except:
                    pass
            if 'user_msg' in task:
                if succ:
                    yield self.call(task['user_msg'], {
                        'info': {
                            'success': 'Fetching results from NeuroArch'
                        }
                    })
                else:
                    yield self.call(task['user_msg'], {
                        'info': {
                            'error': 'Error executing query on NeuroArch'
                        }
                    })
            if ('data_callback_uri' in task):
                uri = task['data_callback_uri'] + '.%s' % user_id
                for c in res:
                    try:
                        succ = yield self.call(uri, c)
                    except ApplicationError as e:
                        print e
                self.retrieve_by_id_on_end()
                returnValue(succ)
            else:
                if details.progress:
                    for c in res:
                        details.progress(c)
                    self.retrieve_by_id_on_end()
                    returnValue({
                        'success': {
                            'info':
                            'Finished fetching all results from database'
                        }
                    })
                else:
                    self.retrieve_by_id_on_end()
                    returnValue({
                        'success': {
                            'info':
                            'Finished fetching all results from database',
                            'data': res
                        }
                    })

        uri = 'ffbo.na.retrieve_by_id.%s' % str(details.session)

        yield self.register(
            retrieve_by_id, uri,
            RegisterOptions(details_arg='details',
                            concurrency=self._max_concurrency))

        ###################

        # Listen for ffbo.processor.connected
        @inlineCallbacks
        def register_component():
            self.log.info("Registering a component")
            # CALL server registration
            try:
                # registered the procedure we would like to call
                res = yield self.call('ffbo.server.register', details.session,
                                      'na', 'na_server_test')
                self.log.info(
                    "register new server called with result: {result}",
                    result=res)

            except ApplicationError as e:
                if e.error != 'wamp.error.no_such_procedure':
                    raise e

        yield self.subscribe(register_component, 'ffbo.processor.connected')
        self.log.info("subscribed to topic 'ffbo.processor.connected'")

        # Register for memory management pings
        @inlineCallbacks
        def memory_management():
            clensed_users = yield self.user_list.cleanup()
            self.log.info("Memory Manager removed users: {users}",
                          users=clensed_users)
            for user in clensed_users:
                try:
                    yield self.publish(
                        "ffbo.ui.update.%s" % user,
                        "Inactivity Detected, State Memory has been cleared")
                except Exception as e:
                    self.log.warn(
                        "Failed to alert user {user} or State Memory removal, with error {e}",
                        user=user,
                        e=e)

        yield self.subscribe(memory_management,
                             'ffbo.processor.memory_manager')
        self.log.info("subscribed to topic 'ffbo.processor.memory_management'")

        register_component()
Example #9
0
        def on_registration_create(reg_session, reg_details, details=None):
            """
            Event handler fired when a new registration was created on this router.

            The handler will then also register on the other router, and when receiving
            calls, re-issue those on this router.

            :param reg_id:
            :param reg_details:
            :param details:
            :return:
            """
            if reg_details['uri'].startswith("wamp."):
                return

            if reg_details['id'] in self._regs:
                # this should not happen actually, but not sure ..
                self.log.error('on_registration_create: reg ID {reg_id} already in map {method}',
                               reg_id=reg_details['id'],
                               method=hltype(BridgeSession._setup_invocation_forwarding))
                return

            self._regs[reg_details['id']] = reg_details
            self._regs[reg_details['id']]['reg'] = None

            uri = reg_details['uri']
            ERR_MSG = [None]

            @inlineCallbacks
            def on_call(*args, **kwargs):

                assert 'details' in kwargs

                details = kwargs.pop('details')
                options = kwargs.pop('options', None)

                if details.caller is None or details.caller_authrole is None or details.caller_authid is None:
                    raise RuntimeError("Internal error attempting rlink forwarding")

                self.log.info(
                    'Received invocation on uri={uri}, options={options} (caller={caller}, caller_authid={caller_authid}, caller_authrole={caller_authrole}, forward_for={forward_for})',
                    uri=uri,
                    options=options,
                    caller=details.caller,
                    caller_authid=details.caller_authid,
                    caller_authrole=details.caller_authrole,
                    forward_for=details.forward_for)

                this_forward = {
                    'session': details.caller,
                    'authid': details.caller_authrole,
                    'authrole': details.caller_authrole,
                }

                if details.forward_for:
                    # the call comes already forwarded from a router node ..
                    if len(details.forward_for) >= 0:
                        self.log.debug('SKIP! already forwarded')
                        return

                    forward_for = copy.deepcopy(details.forward_for)
                    forward_for.append(this_forward)
                else:
                    forward_for = [this_forward]

                options = CallOptions(forward_for=forward_for)

                try:
                    result = yield self.call(uri, *args, options=options, **kwargs)
                except TransportLost:
                    return
                except ApplicationError as e:
                    if e.error not in ['wamp.close.normal']:
                        self.log.warn('FAILED TO CALL 1: {} {}'.format(type(e), str(e)))
                    return
                except Exception as e:
                    if not ERR_MSG[0]:
                        self.log.warn('FAILED TO CALL 2: {} {}'.format(type(e), str(e)))
                        ERR_MSG[0] = True
                    return

                self.log.info(
                    "RLink forward-invoked call {dir} (options={options})",
                    dir=self.DIR,
                    options=options,
                )
                return result

            try:
                reg = yield other.register(on_call,
                                           uri,
                                           options=RegisterOptions(
                                               details_arg='details',
                                               invoke=reg_details.get('invoke', None),
                                           ))
            except Exception as e:
                # FIXME: partially fixes https://github.com/crossbario/crossbar/issues/1894,
                #  however we need to make sure this situation never happens.
                if isinstance(e, ApplicationError) and e.error == 'wamp.error.procedure_already_exists':
                    other_leg = 'local' if self.IS_REMOTE_LEG else 'remote'
                    self.log.debug(f"on_registration_create: tried to register procedure {uri} on {other_leg} "
                                   f"session but it's already registered.")
                    return
                raise Exception("fatal: could not forward-register '{}'".format(uri))

            # so ... if, during that "yield" above while we register
            # on the "other" router, *this* router may have already
            # un-registered. If that happened, our registration will
            # be gone, so we immediately un-register on the other side
            if reg_details['id'] not in self._regs:
                self.log.info("registration already gone: {uri}", uri=reg_details['uri'])
                yield reg.unregister()
            else:
                self._regs[reg_details['id']]['reg'] = reg

            self.log.info(
                "created forwarding registration: me={me} other={other} reg_id={reg_id} reg_details={reg_details} details={details} reg_session={reg_session}",
                me=self._session_id,
                other=other._session_id,
                reg_id=reg_details['id'],
                reg_details=reg_details,
                details=details,
                reg_session=reg_session,
            )
class Backend(ApplicationSession):
    REGISTER_OPTIONS = RegisterOptions(details_arg='details')
    SUBSCRIBE_OPTIONS = SubscribeOptions(details_arg='details')
    counter = 0

    @inlineCallbacks
    def onJoin(self, details=None):
        self.log.info(
            "Backend component is connected - session ID - {}".format(
                details.session))

        yield self.subscribe(self.on_session_join, 'wamp.session.on_join')
        yield self.subscribe(self.on_session_leave, 'wamp.session.on_leave')
        yield self.register(self.get_user,
                            'com.example.database.get_user',
                            options=self.REGISTER_OPTIONS)
        yield self.register(self.get_config,
                            'com.example.database.get_config',
                            options=self.REGISTER_OPTIONS)
        yield self.register(self.create_user,
                            'com.example.database.create_user',
                            options=self.REGISTER_OPTIONS)
        yield self.register(self.update_settings,
                            'com.example.database.update_settings',
                            options=self.REGISTER_OPTIONS)
        yield self.register(self.ping,
                            'com.example.ping',
                            options=self.REGISTER_OPTIONS)

        while True:
            ## PUBLISH an event
            ##
            yield self.publish(u'com.example.oncounter', self.counter)
            self.log.info("published to 'oncounter' with counter {counter}",
                          counter=self.counter)
            self.counter += 1

            yield sleep(1)

    @staticmethod
    def ping(details=None):
        return "pong"

    @staticmethod
    def get_user(username, details=None):
        try:
            user = UserSerializer(
                User.objects.get(username__exact=username)).data
            return user
        except User.DoesNotExist:
            return None

    @staticmethod
    def get_config(details=None):
        try:
            return UserSerializer(
                User.objects.get(
                    username=details.caller_authid)).data['settings']
        except User.DoesNotExist:
            return None

    @staticmethod
    def create_user(data, details=None):
        try:
            # Add user
            salt = generate_wcs(12).decode('utf8')
            user = User(username=data['username'],
                        role=data['role'],
                        password='******'.join([
                            'salted_autobahn_auth', salt,
                            str(settings.ITERATIONS),
                            str(settings.KEYLEN),
                            derive_key(data['password'], salt,
                                       settings.ITERATIONS,
                                       settings.KEYLEN).decode('ascii')
                        ]),
                        settings={},
                        created_by=details.caller_authid)
            user.save()
            return True
        except IntegrityError as e:
            return str(e)
        except Exception as e:
            return str(e)

    @staticmethod
    def update_settings(settings, details=None):
        try:
            old_settings = User.objects.get(
                username__exact=details.caller_authid)
            old_settings.settings = settings
            old_settings.save()
            return True
        except User.DoesNotExist:
            return False

    @staticmethod
    def on_session_join(session_details):
        user = session_details['authid']
        role = session_details['authrole']
        session = int(session_details['session'])

        print("User {} with role {} connected with session {}".format(
            user, role, session))

    @staticmethod
    def on_session_leave(session):
        print(session, "left")
Example #11
0
    def onJoin(self, details):

        # REGISTER celery tasks as procedures for remote calling
        #
        for t in CROSSBAR_CELERY_TASKS:
            code = compile(
                '%s = lambda *args, **kwargs: %s.delay(*args, caller_session_id=kwargs["caller_details"].caller).addCallback(returnData)'
                % (t.get('cb_rpc'), t.get('task')), '<string>', 'exec')
            if (sys.version_info > (3, 0)):
                exec code in ns
            else:
                exec(code, ns)

            reg = yield self.register(
                ns[t.get('cb_rpc')],
                'com.example.%s' % t.get('cb_rpc'),
                options=RegisterOptions(details_arg='caller_details'))
            print("procedure %s() registered" % t.get('cb_rpc'))

        ## Register DATA_GET_LIST tasks
        for t in GET_LIST_DATA_TASKS:
            cb_rpc = 'get_list_%s%s' % (t.get('app'), t.get('model'))
            code = compile(
                '%s = lambda *args, **kwargs: data_get_list_task.delay("%s", "%s", %s, %s, filter=args[0], caller_session_id=kwargs["caller_details"].caller).addCallback(returnData)'
                % (cb_rpc, t.get('app'), t.get('model'), t.get('fields'),
                   t.get('filter_fields')), '<string>', 'exec')

            if (sys.version_info > (3, 0)):
                exec code in ns_get_list
            else:
                ecec(code, ns_get_list)

            reg = yield self.register(
                ns_get_list[cb_rpc],
                'com.example.%s' % cb_rpc,
                options=RegisterOptions(details_arg='caller_details'))
            print("procedure %s() registered" % cb_rpc)

        ## Register DATA_GET_DETAIL tasks
        for t in GET_DETAIL_DATA_TASKS:
            cb_rpc = 'get_detail_%s%s' % (t.get('app'), t.get('model'))
            code = compile(
                '%s = lambda item_id, **kwargs: data_get_detail_task.delay("%s", "%s", %s, item_id, caller_session_id=kwargs["caller_details"].caller).addCallback(returnData)'
                % (cb_rpc, t.get('app'), t.get('model'), t.get('fields')),
                '<string>', 'exec')

            if (sys.version_info > (3, 0)):
                exec code in ns_get_detail
            else:
                exec(code, ns_get_detail)

            reg = yield self.register(
                ns_get_detail[cb_rpc],
                'com.example.%s' % cb_rpc,
                options=RegisterOptions(details_arg='caller_details'))
            print("procedure %s() registered" % cb_rpc)

        ## Register DATA_CREATE tasks
        for t in CREATE_DATA_TASKS:
            cb_rpc = 'create_%s%s' % (t.get('app'), t.get('model'))
            code = compile(
                '%s = lambda *args, **kwargs: data_create_task.delay("%s", "%s", %s, create_dict=args[0], caller_session_id=kwargs["caller_details"].caller).addCallback(returnData)'
                % (cb_rpc, t.get('app'), t.get('model'), t.get('fields')),
                '<string>', 'exec')

            if (sys.version_info > (3, 0)):
                exec code in ns_create
            else:
                exec(code, ns_create)

            reg = yield self.register(
                ns_create[cb_rpc],
                'com.example.%s' % cb_rpc,
                options=RegisterOptions(details_arg='caller_details'))
            print("procedure %s() registered" % cb_rpc)
Example #12
0
    def test1(self):
        """
        The following produces this trace when ran alone (only one instance of the component):

        https://gist.githubusercontent.com/oberstet/4280447fe9b6691819a7287f5b0f9663/raw/76932f731cc54a8cbc3e8f5b32b145f3e493f9f2/gistfile1.txt

        and produces this trace when 2 instances are run in parallel:

        https://gist.githubusercontent.com/oberstet/21bbd4f66c04a767627576ff92a05eee/raw/51b5ca58e4a44f76dba42654b0b0b37006592829/gistfile1.txt
        """

        # REGISTER
        def add2(a, b):
            print('----------------------------')
            print("add2 called on {}".format(self._ident))
            return [a + b, self._ident, self._type]

        reg = yield self.register(add2,
                                  u'com.example.add2',
                                  options=RegisterOptions(invoke=u'random'))
        print('----------------------------')
        print('procedure registered: com.myexample.add2')

        # SUBSCRIBE
        def oncounter(counter, id, type):
            print('----------------------------')
            self.log.info(
                "'oncounter' event, counter value: {counter} from component {id} ({type})",
                counter=counter,
                id=id,
                type=type)

        sub = yield self.subscribe(oncounter, u'com.example.oncounter')
        print('----------------------------')
        self.log.info("subscribed to topic 'oncounter'")

        x = 0
        counter = 0
        while counter < 5 or True:

            # CALL
            try:
                res = yield self.call(u'com.example.add2', x, 3)
                print('----------------------------')
                self.log.info(
                    "add2 result: {result} from {callee} ({callee_type})",
                    result=res[0],
                    callee=res[1],
                    callee_type=res[2])
                x += 1
            except ApplicationError as e:
                ## ignore errors due to the frontend not yet having
                ## registered the procedure we would like to call
                if e.error != 'wamp.error.no_such_procedure':
                    raise e

            # PUBLISH
            published = []
            for i in range(1):
                yield published.append(
                    self.publish(u'com.example.oncounter',
                                 counter,
                                 self._ident,
                                 self._type,
                                 options=PublishOptions(acknowledge=True,
                                                        exclude_me=False)))
            #yield DeferredList(published)
            print('----------------------------')
            self.log.info("published to 'oncounter' with counter {counter}",
                          counter=counter)
            counter += 1

            yield sleep(1)

        yield reg.unregister()
        yield sub.unsubscribe()

        self.leave()
Example #13
0
 def getRegisterOptions(self):
     return RegisterOptions(details_arg='details')
Example #14
0
# VERTRAG, EINEM DELIKT ODER ANDERS IM ZUSAMMENHANG MIT DER BENUTZUNG
# ODER SONSTIGE VERWENDUNG DER SOFTWARE ENTSTANDEN.
#
###############################################################################

import logging
import glob
import os
import sys
from datetime import datetime
import GSV6_UnitCodes
from Queue import Empty

from autobahn.wamp.types import RegisterOptions

spezialOptions = RegisterOptions(details_arg="details")


class GSVeventHandler():
    # here we register all "wamp" functions and all "wamp" listners around GSV-6CPU-Modul
    def __init__(self, session, gsv_lib, antwortQueue, frameRouter):
        self.session = session
        self.gsv_lib = gsv_lib
        self.antwortQueue = antwortQueue
        self.frameRouter = frameRouter
        # start register
        self.regCalls()

    def regCalls(self):
        # print('register...')
        self.session.register(self.startStopTransmisson, u"de.me_systeme.gsv.startStopTransmission", spezialOptions)
def create_component(args, extra):

    log = txaio.make_logger()

    # 'transports' can also be a list of dicts containing more
    # detailed connection information (and multiple ways to connect)
    client = Component(
        transports=args.url,
        realm=args.realm,
        extra=extra,
        authentication={
            "anonymous": {
                "authrole": "anonymous",
            },
        }
    )

    info = {
        "ident": "unknown",
        "type": "Python",
    }

    @client.on_connect
    def connected(session, x):
        log.info("Client connected: {klass}, {extra}", klass=session.__class__, extra=session.config.extra)

    @client.on_join
    @inlineCallbacks
    def joined(session, details):
        log.info("Joined: {details}", details=details)

        info["ident"] = details.authid

        log.info("Component ID is  {ident}", **info)
        log.info("Component type is  {type}", **info)

        # this could go in a "main" procedure to be passed to
        # Component, declared as "def main(reactor, session):" and
        # passed to Component() via "main="
        x = 0
        counter = 0
        while True:

            # CALL
            try:
                res = yield session.call(u'com.example.add2', x, 3)
                print('----------------------------')
                log.info("add2 result: {result}", result=res[0])
                log.info("from component {id} ({type})", id=res[1], type=res[2])
                x += 1
            except ApplicationError as e:
                # ignore errors due to the frontend not yet having
                # registered the procedure we would like to call
                if e.error != 'wamp.error.no_such_procedure':
                    raise e

            # PUBLISH
            yield session.publish(u'com.example.oncounter', counter, info["ident"], info["type"])
            print('----------------------------')
            log.info("published to 'oncounter' with counter {counter}",
                     counter=counter)
            counter += 1

            yield sleep(2)  # note this is an "async sleep" using callLater()

    @client.register(
        "com.example.add2",
        options=RegisterOptions(invoke=u'roundrobin'),
    )
    def add2(a, b):
        print('----------------------------')
        print("add2 called on {}".format(info["ident"]))
        return [ a + b, info["ident"], info["type"]]


    @client.subscribe("com.example.oncounter")
    def oncounter(counter, ident, kind):
        print('----------------------------')
        log.info("'oncounter' event, counter value: {counter}", counter=counter)
        log.info("from component {ident} ({kind})", ident=ident, kind=kind)

    @client.on_leave
    def left(session, details):
        log.info("session left: {}".format(details))

    return client
Example #16
0
    def onJoin(self, details):
        """
        Called when worker process has joined the node's management realm.
        """
        yield NativeWorkerSession.onJoin(self, details, publish_ready=False)

        # factory for producing (per-realm) routers
        self._router_factory = RouterFactory(self._node_id)

        # factory for producing router sessions
        self._router_session_factory = RouterSessionFactory(
            self._router_factory)

        # map: realm ID -> RouterRealm
        self.realms = {}

        # map: realm URI -> realm ID
        self.realm_to_id = {}

        # map: component ID -> RouterComponent
        self.components = {}

        # map: transport ID -> RouterTransport
        self.transports = {}

        # the procedures registered
        procs = [
            'get_router_realms',
            'start_router_realm',
            'stop_router_realm',
            'get_router_realm_roles',
            'start_router_realm_role',
            'stop_router_realm_role',
            'get_router_realm_uplinks',
            'start_router_realm_uplink',
            'stop_router_realm_uplink',
            'get_router_components',
            'start_router_component',
            'stop_router_component',
            'get_router_transports',
            'start_router_transport',
            'stop_router_transport',
        ]

        dl = []
        for proc in procs:
            uri = '{}.{}'.format(self._uri_prefix, proc)
            self.log.debug("Registering management API procedure {proc}",
                           proc=uri)
            dl.append(
                self.register(getattr(self, proc),
                              uri,
                              options=RegisterOptions(details_arg='details')))

        regs = yield DeferredList(dl)

        self.log.debug("Registered {cnt} management API procedures",
                       cnt=len(regs))

        # NativeWorkerSession.publish_ready()
        yield self.publish_ready()
Example #17
0
    async def start(self, session):
        """
        Start rotating keys and placing key offers with the XBR market maker.

        :param session: WAMP session over which to communicate with the XBR market maker.
        :type session: :class:`autobahn.wamp.protocol.ApplicationSession`
        """
        assert isinstance(
            session, ApplicationSession
        ), 'session must be an ApplicationSession, was "{}"'.format(session)
        assert self._state in [
            SimpleSeller.STATE_NONE, SimpleSeller.STATE_STOPPED
        ], 'seller already running'

        self._state = SimpleSeller.STATE_STARTING
        self._session = session
        self._session_regs = []

        self.log.info(
            'Start selling from seller delegate address {address} (public key 0x{public_key}..)',
            address=hl(self._caddr),
            public_key=binascii.b2a_hex(self._pkey.public_key[:10]).decode())

        procedure = 'xbr.provider.{}.sell'.format(self._provider_id)
        reg = await session.register(
            self.sell,
            procedure,
            options=RegisterOptions(details_arg='details'))
        self._session_regs.append(reg)
        self.log.debug('Registered procedure "{procedure}"',
                       procedure=hl(reg.procedure))

        procedure = 'xbr.provider.{}.close_channel'.format(self._provider_id)
        reg = await session.register(
            self.close_channel,
            procedure,
            options=RegisterOptions(details_arg='details'))
        self._session_regs.append(reg)
        self.log.debug('Registered procedure "{procedure}"',
                       procedure=hl(reg.procedure))

        for key_series in self._keys.values():
            await key_series.start()

        # get the currently active (if any) paying channel for the delegate
        channel = await session.call(
            'xbr.marketmaker.get_active_paying_channel', self._addr)

        # get the current (off-chain) balance of the paying channel
        paying_balance = await session.call(
            'xbr.marketmaker.get_paying_channel_balance', channel['channel'])
        # FIXME
        if type(paying_balance['remaining']) == bytes:
            paying_balance['remaining'] = unpack_uint256(
                paying_balance['remaining'])

        self.log.info(
            'Delegate has currently active paying channel address {paying_channel_adr}',
            paying_channel_adr=hl(
                '0x' + binascii.b2a_hex(channel['channel']).decode()))

        self._channels[channel['channel']] = PayingChannel(
            channel['channel'], paying_balance['seq'],
            paying_balance['remaining'])
        self._state = SimpleSeller.STATE_STARTED

        # FIXME
        self._channel = channel
        self._balance = paying_balance['remaining']
        if type(self._balance) == bytes:
            self._balance = unpack_uint256(self._balance)
        self._seq = paying_balance['seq']

        return paying_balance['remaining']
Example #18
0
)


@component.on_join
@inlineCallbacks
def join(session, details):
    print("joined {}: {}".format(session, details))
    yield sleep(1)
    print("Calling 'com.example'")
    res = yield session.call(u"example.foo", 42, something="nothing")
    print("Result: {}".format(res))
    yield session.leave()


@component.register(
    u"example.foo",
    options=RegisterOptions(details_arg='details'),
)
@inlineCallbacks
def foo(*args, **kw):
    print("foo called: {}, {}".format(args, kw))
    for x in range(5, 0, -1):
        print("  returning in {}".format(x))
        yield sleep(1)
    print("returning '42'")
    returnValue(42)


if __name__ == "__main__":
    run([component])
Example #19
0
    async def onJoin(self, details):

        self.log.info("Connected: {details}", details=details)

        self._ident = details.authid
        self._type = 'Python'

        self.log.info("Component ID is  {ident}", ident=self._ident)
        self.log.info("Component type is  {type}", type=self._type)

        # REGISTER
        def add2(a, b):
            print('----------------------------')
            print("add2 called on {}".format(self._ident))
            return [a + b, self._ident, self._type]

        await self.register(add2,
                            'com.example.add2',
                            options=RegisterOptions(invoke='roundrobin'))
        print('----------------------------')
        print('procedure registered: com.myexample.add2')

        # SUBSCRIBE
        def oncounter(counter, id, type):
            print('----------------------------')
            self.log.info("'oncounter' event, counter value: {counter}",
                          counter=counter)
            self.log.info("from component {id} ({type})", id=id, type=type)

        await self.subscribe(oncounter, 'com.example.oncounter')

        print('----------------------------')
        self.log.info("subscribed to topic 'oncounter'")

        x = 0
        counter = 0
        while True:

            # CALL
            try:
                res = await self.call('com.example.add2', x, 3)
                print('----------------------------')
                self.log.info("add2 result: {result}", result=res[0])
                self.log.info("from component {id} ({type})",
                              id=res[1],
                              type=res[2])
                x += 1
            except ApplicationError as e:
                ## ignore errors due to the frontend not yet having
                ## registered the procedure we would like to call
                if e.error != 'wamp.error.no_such_procedure':
                    raise e

            # PUBLISH
            self.publish('com.example.oncounter',
                         counter,
                         self._ident,
                         self._type,
                         options=PublishOptions(exclude_me=False,
                                                acknowledge=True))
            print('----------------------------')
            self.log.info("published to 'oncounter' with counter {counter}",
                          counter=counter)
            counter += 1

            await asyncio.sleep(2)