Exemple #1
0
            def on_authorize_error(err):
                """
                the call to authorize the action _itself_ failed (note this is
                different from the call to authorize succeed, but the
                authorization being denied)
                """
                self.log.failure("Authorization failed", failure=err)
                if publish.acknowledge:

                    if self._router.is_traced:
                        publish.correlation_is_last = False
                        self._router._factory._worker._maybe_trace_rx_msg(session, publish)

                    reply = message.Error(
                        message.Publish.MESSAGE_TYPE,
                        publish.request,
                        ApplicationError.AUTHORIZATION_FAILED,
                        [u"failed to authorize session for publishing to topic URI '{0}': {1}".format(publish.topic, err.value)]
                    )
                    reply.correlation_id = publish.correlation_id
                    reply.correlation_uri = publish.topic
                    reply.correlation_is_anchor = False
                    self._router.send(session, reply)
                else:
                    if self._router.is_traced:
                        publish.correlation_is_last = True
                        self._router._factory._worker._maybe_trace_rx_msg(session, publish)
Exemple #2
0
   def processYield(self, session, yield_):
      """
      Implements :func:`autobahn.wamp.interfaces.IDealer.processYield`
      """
      assert(session in self._session_to_registrations)

      if yield_.request in self._invocations:

         ## get original call message and calling session
         ##
         call_msg, call_session = self._invocations[yield_.request]

         ## validate payload
         ##
         is_valid = True
         try:
            self._router.validate('call_result', call_msg.procedure, yield_.args, yield_.kwargs)
         except Exception as e:
            is_valid = False
            reply = message.Error(message.Call.MESSAGE_TYPE, call_msg.request, ApplicationError.INVALID_ARGUMENT, ["call result from procedure '{0}' with invalid application payload: {1}".format(call_msg.procedure, e)])
         else:
            reply = message.Result(call_msg.request, args = yield_.args, kwargs = yield_.kwargs, progress = yield_.progress)

         ## the calling session might have been lost in the meantime ..
         ##
         if call_session._transport:
            call_session._transport.send(reply)

         ## the call is done if it's a regular call (non-progressive) or if the payload was invalid
         ##
         if not yield_.progress or not is_valid:
            del self._invocations[yield_.request]

      else:
         raise ProtocolError("Dealer.onYield(): YIELD received for non-pending request ID {0}".format(yield_.request))
Exemple #3
0
            def on_authorize_error(err):

                # the call to authorize the action _itself_ failed (note this is different from the
                # call to authorize succeed, but the authorization being denied)
                #
                reply = message.Error(message.Call.MESSAGE_TYPE, call.request, ApplicationError.AUTHORIZATION_FAILED, ["failed to authorize session for calling procedure '{0}': {1}".format(call.procedure, err.value)])
                session._transport.send(reply)
Exemple #4
0
    def processUnsubscribe(self, session, unsubscribe):
        """
      Implements :func:`crossbar.router.interfaces.IBroker.processUnsubscribe`
      """
        #assert(session in self._session_to_subscriptions)

        if unsubscribe.subscription in self._subscription_to_sessions:

            topic, subscribers = self._subscription_to_sessions[
                unsubscribe.subscription]

            subscribers.discard(session)

            if not subscribers:
                del self._subscription_to_sessions[unsubscribe.subscription]

            _, subscribers = self._topic_to_sessions[topic]

            subscribers.discard(session)

            if not subscribers:
                del self._topic_to_sessions[topic]

            self._session_to_subscriptions[session].discard(
                unsubscribe.subscription)

            reply = message.Unsubscribed(unsubscribe.request)

        else:
            reply = message.Error(message.Unsubscribe.MESSAGE_TYPE,
                                  unsubscribe.request,
                                  ApplicationError.NO_SUCH_SUBSCRIPTION)

        session._transport.send(reply)
Exemple #5
0
    def test_call_cancel_two_sessions(self):
        """
        this has 2 different session using the same ID (42) for their Call
        requests to confirm we deal with the fact that these IDs are
        only unique per-session properly
        """
        messages = []

        def session_send(msg):
            messages.append(msg)

        session0 = mock.Mock()
        session0._transport.send = session_send
        session0._session_roles = {'callee': role.RoleCalleeFeatures(call_canceling=True)}

        session1 = mock.Mock()
        session1._transport.send = session_send
        session1._session_roles = {'callee': role.RoleCalleeFeatures(call_canceling=True)}

        dealer = self.router._dealer
        dealer.attach(session0)
        dealer.attach(session1)

        def authorize(*args, **kwargs):
            return defer.succeed({'allow': True, 'disclose': False})

        self.router.authorize = mock.Mock(side_effect=authorize)

        dealer.processRegister(session0,
                               message.Register(1, 'com.example.my.proc', 'exact', message.Register.INVOKE_SINGLE, 2))

        registered_msg = messages[-1]
        self.assertIsInstance(registered_msg, message.Registered)

        # two calls outstanding to the endpoint, both happen to use
        # the same ID (42) which is legal
        dealer.processCall(session0, message.Call(42, 'com.example.my.proc', []))

        invocation_msg0 = messages[-1]
        self.assertIsInstance(invocation_msg0, message.Invocation)
        dealer.processCall(session1, message.Call(42, 'com.example.my.proc', []))

        invocation_msg1 = messages[-1]
        self.assertIsInstance(invocation_msg1, message.Invocation)

        # now, cancel the first session's call
        dealer.processCancel(session0, message.Cancel(
            42,
            "kill",
        ))

        # should receive an INTERRUPT from the dealer now (for the
        # correct session only)
        interrupt_msg0 = messages[-1]
        self.assertIsInstance(interrupt_msg0, message.Interrupt)
        self.assertEqual(interrupt_msg0.request, invocation_msg0.request)

        dealer.processInvocationError(
            session0, message.Error(message.Invocation.MESSAGE_TYPE, invocation_msg0.request, 'wamp.error.canceled'))
Exemple #6
0
    def processYield(self, session, yield_):
        """
        Implements :func:`crossbar.router.interfaces.IDealer.processYield`
        """
        # assert(session in self._session_to_registrations)

        if yield_.request in self._invocations:

            # get the invocation request tracked for the caller
            #
            invocation_request = self._invocations[yield_.request]

            is_valid = True
            if yield_.payload is None:
                # validate normal args/kwargs payload
                try:
                    self._router.validate('call_result', invocation_request.call.procedure, yield_.args, yield_.kwargs)
                except Exception as e:
                    is_valid = False
                    reply = message.Error(message.Call.MESSAGE_TYPE, invocation_request.call.request, ApplicationError.INVALID_ARGUMENT, [u"call result from procedure '{0}' with invalid application payload: {1}".format(invocation_request.call.procedure, e)])
                else:
                    reply = message.Result(invocation_request.call.request, args=yield_.args, kwargs=yield_.kwargs, progress=yield_.progress)
            else:
                reply = message.Result(invocation_request.call.request, payload=yield_.payload, progress=yield_.progress,
                                       enc_algo=yield_.enc_algo, enc_key=yield_.enc_key, enc_serializer=yield_.enc_serializer)

            # the calling session might have been lost in the meantime ..
            #
            if invocation_request.caller._transport:
                self._router.send(invocation_request.caller, reply)

            # the call is done if it's a regular call (non-progressive) or if the payload was invalid
            #
            if not yield_.progress or not is_valid:
                callee_extra = invocation_request.registration.observers_extra.get(session, None)
                if callee_extra:
                    callee_extra.concurrency_current -= 1

                self._remove_invoke_request(invocation_request)

                # check for any calls queued on the registration for which an
                # invocation just returned, and hence there is likely concurrency
                # free again to actually forward calls previously queued calls
                # that were queued because no callee endpoint concurrency was free
                if self._call_store:
                    queued_call = self._call_store.get_queued_call(invocation_request.registration)
                    if queued_call:
                        invocation_sent = self._call(queued_call.session,
                                                     queued_call.call,
                                                     queued_call.registration,
                                                     queued_call.authorization,
                                                     True)
                        # only actually pop the queued call when we really were
                        # able to forward the call now
                        if invocation_sent:
                            self._call_store.pop_queued_call(invocation_request.registration)

        else:
            raise ProtocolError(u"Dealer.onYield(): YIELD received for non-pending request ID {0}".format(yield_.request))
    def test_exception_from_message(self):
        session = protocol.BaseSession()

        @wamp.error(u"com.myapp.error1")
        class AppError1(Exception):
            pass

        @wamp.error(u"com.myapp.error2")
        class AppError2(Exception):
            pass

        session.define(AppError1)
        session.define(AppError2)

        # map defined errors to user exceptions
        emsg = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error1')
        exc = session._exception_from_message(emsg)
        self.assertIsInstance(exc, AppError1)
        self.assertEqual(exc.args, ())

        emsg = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error2')
        exc = session._exception_from_message(emsg)
        self.assertIsInstance(exc, AppError2)
        self.assertEqual(exc.args, ())

        # map undefined error to (generic) exception
        emsg = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error3')
        exc = session._exception_from_message(emsg)
        self.assertIsInstance(exc, exception.ApplicationError)
        self.assertEqual(exc.error, u'com.myapp.error3')
        self.assertEqual(exc.args, ())
        self.assertEqual(exc.kwargs, {})

        emsg = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error3', args=[1, 2, u'hello'])
        exc = session._exception_from_message(emsg)
        self.assertIsInstance(exc, exception.ApplicationError)
        self.assertEqual(exc.error, u'com.myapp.error3')
        self.assertEqual(exc.args, (1, 2, u'hello'))
        self.assertEqual(exc.kwargs, {})

        emsg = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error3', args=[1, 2, u'hello'], kwargs={u'foo': 23, u'bar': u'baz'})
        exc = session._exception_from_message(emsg)
        self.assertIsInstance(exc, exception.ApplicationError)
        self.assertEqual(exc.error, u'com.myapp.error3')
        self.assertEqual(exc.args, (1, 2, u'hello'))
        self.assertEqual(exc.kwargs, {u'foo': 23, u'bar': u'baz'})
Exemple #8
0
 def on_authorize_error(err):
     reply = message.Error(
         message.Register.MESSAGE_TYPE, register.request,
         ApplicationError.AUTHORIZATION_FAILED, [
             "failed to authorize session for registering procedure '{0}': {1}"
             .format(register.procedure, err.value)
         ])
     session._transport.send(reply)
            def on_authorize_error(err):

                # the call to authorize the action _itself_ failed (note this is different from the
                # call to authorize succeed, but the authorization being denied)
                #
                if publish.acknowledge:
                    reply = message.Error(message.Publish.MESSAGE_TYPE, publish.request, ApplicationError.AUTHORIZATION_FAILED, ["failed to authorize session for publishing to topic URI '{0}': {1}".format(publish.topic, err.value)])
                    session._transport.send(reply)
Exemple #10
0
 def on_authorize_error(err):
     reply = message.Error(
         message.Subscribe.MESSAGE_TYPE, subscribe.request,
         ApplicationError.AUTHORIZATION_FAILED, [
             "failed to authorize session for subscribing to topic URI '{0}': {1}"
             .format(subscribe.topic, err.value)
         ])
     session._transport.send(reply)
Exemple #11
0
 def on_authorize_error(err):
     reply = message.Error(
         message.Call.MESSAGE_TYPE, call.request,
         ApplicationError.AUTHORIZATION_FAILED, [
             "failed to authorize session for calling procedure '{}': {}"
             .format(call.procedure, err.value)
         ])
     session._transport.send(reply)
Exemple #12
0
    def processInvocationError(self, session, error):
        """
        Implements :func:`crossbar.router.interfaces.IDealer.processInvocationError`
        """
        # assert(session in self._session_to_registrations)

        if error.request in self._invocations:

            # get the invocation request tracked for the caller
            #
            invocation_request = self._invocations[error.request]

            # validate payload
            #
            try:
                self._router.validate('call_error',
                                      invocation_request.call.procedure,
                                      error.args, error.kwargs)
            except Exception as e:
                reply = message.Error(
                    message.Call.MESSAGE_TYPE, invocation_request.call.request,
                    ApplicationError.INVALID_ARGUMENT, [
                        u"call error from procedure '{0}' with invalid application payload: {1}"
                        .format(invocation_request.call.procedure, e)
                    ])
            else:
                reply = message.Error(message.Call.MESSAGE_TYPE,
                                      invocation_request.call.request,
                                      error.error,
                                      args=error.args,
                                      kwargs=error.kwargs)

            # the calling session might have been lost in the meantime ..
            #
            if invocation_request.caller._transport:
                invocation_request.caller._transport.send(reply)

            # the call is done
            #
            del self._invocations[error.request]

        else:
            raise ProtocolError(
                u"Dealer.onInvocationError(): ERROR received for non-pending request_type {0} and request ID {1}"
                .format(error.request_type, error.request))
Exemple #13
0
   def processRegister(self, session, register):
      """
      Implements :func:`autobahn.wamp.interfaces.IDealer.processRegister`
      """
      assert(session in self._session_to_registrations)

      ## check procedure URI
      ##
      if (not self._option_uri_strict and not  _URI_PAT_LOOSE_NON_EMPTY.match(register.procedure)) or \
         (    self._option_uri_strict and not _URI_PAT_STRICT_NON_EMPTY.match(register.procedure)):

         reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.INVALID_URI, ["register for invalid procedure URI '{0}'".format(register.procedure)])
         session._transport.send(reply)

      else:

         if not register.procedure in self._procs_to_regs:

            ## authorize action
            ##
            d = self._as_future(self._router.authorize, session, register.procedure, IRouter.ACTION_REGISTER)

            def on_authorize_success(authorized):
               if authorized:
                  registration_id = util.id()
                  self._procs_to_regs[register.procedure] = (registration_id, session, register.discloseCaller, register.discloseCallerTransport)
                  self._regs_to_procs[registration_id] = register.procedure

                  self._session_to_registrations[session].add(registration_id)

                  reply = message.Registered(register.request, registration_id)
               else:
                  reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.NOT_AUTHORIZED, ["session is not authorized to register procedure '{0}'".format(register.procedure)])

               session._transport.send(reply)

            def on_authorize_error(err):
               reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.AUTHORIZATION_FAILED, ["failed to authorize session for registering procedure '{0}': {1}".format(register.procedure, err.value)])
               session._transport.send(reply)

            self._add_future_callbacks(d, on_authorize_success, on_authorize_error)

         else:
            reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.PROCEDURE_ALREADY_EXISTS, ["register for already registered procedure '{0}'".format(register.procedure)])
            session._transport.send(reply)
Exemple #14
0
 def on_authorize_error(err):
     if publish.acknowledge:
         reply = message.Error(
             message.Publish.MESSAGE_TYPE, publish.request,
             ApplicationError.AUTHORIZATION_FAILED, [
                 "failed to authorize session for publishing to topic URI '{0}': {1}"
                 .format(publish.topic, err.value)
             ])
         session._transport.send(reply)
Exemple #15
0
        def on_authorize_success(authorization):
            if not authorization[u'allow']:
                # error reply since session is not authorized to register
                #
                reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.NOT_AUTHORIZED, [u"session is not authorized to register procedure '{0}'".format(register.procedure)])

            else:
                registration = self._registration_map.get_observation(register.procedure, register.match)
                if register.force_reregister and registration:
                    for obs in registration.observers:
                        self._registration_map.drop_observer(obs, registration)
                        kicked = message.Unregistered(
                            0,
                            registration=registration.id,
                            reason=u"wamp.error.unregistered",
                        )
                        kicked.correlation = register.correlation
                        self._router.send(obs, kicked)
                    self._registration_map.delete_observation(registration)

                # ok, session authorized to register. now get the registration
                #
                registration_extra = RegistrationExtra(register.invoke)
                registration_callee_extra = RegistrationCalleeExtra(register.concurrency)
                registration, was_already_registered, is_first_callee = self._registration_map.add_observer(session, register.procedure, register.match, registration_extra, registration_callee_extra)

                if not was_already_registered:
                    self._session_to_registrations[session].add(registration)

                # publish WAMP meta events
                #
                if self._router._realm:
                    service_session = self._router._realm.session
                    if service_session and not registration.uri.startswith(u'wamp.'):
                        options = types.PublishOptions(
                            correlation=register.correlation
                        )
                        if is_first_callee:
                            registration_details = {
                                u'id': registration.id,
                                u'created': registration.created,
                                u'uri': registration.uri,
                                u'match': registration.match,
                                u'invoke': registration.extra.invoke,
                            }
                            service_session.publish(u'wamp.registration.on_create', session._session_id, registration_details, options=options)
                        if not was_already_registered:
                            service_session.publish(u'wamp.registration.on_register', session._session_id, registration.id, options=options)

                # acknowledge register with registration ID
                #
                reply = message.Registered(register.request, registration.id)

            # send out reply to register requestor
            #
            reply.correlation = register.correlation
            self._router.send(session, reply)
Exemple #16
0
    def test_call_cancel(self):
        last_message = {'1': []}

        def session_send(msg):
            last_message['1'] = msg

        session = mock.Mock()
        session._transport.send = session_send
        session._session_roles = {'callee': role.RoleCalleeFeatures(call_canceling=True)}

        dealer = self.router._dealer
        dealer.attach(session)

        def authorize(*args, **kwargs):
            return defer.succeed({u'allow': True, u'disclose': False})

        self.router.authorize = mock.Mock(side_effect=authorize)

        dealer.processRegister(session, message.Register(
            1,
            u'com.example.my.proc',
            u'exact',
            message.Register.INVOKE_SINGLE,
            1
        ))

        registered_msg = last_message['1']
        self.assertIsInstance(registered_msg, message.Registered)

        dealer.processCall(session, message.Call(
            2,
            u'com.example.my.proc',
            []
        ))

        invocation_msg = last_message['1']
        self.assertIsInstance(invocation_msg, message.Invocation)

        dealer.processCancel(session, message.Cancel(
            2
        ))

        # should receive an INTERRUPT from the dealer now
        interrupt_msg = last_message['1']
        self.assertIsInstance(interrupt_msg, message.Interrupt)
        self.assertEqual(interrupt_msg.request, invocation_msg.request)

        dealer.processInvocationError(session, message.Error(
            message.Invocation.MESSAGE_TYPE,
            invocation_msg.request,
            u'wamp.error.canceled'
        ))

        call_error_msg = last_message['1']
        self.assertIsInstance(call_error_msg, message.Error)
        self.assertEqual(message.Call.MESSAGE_TYPE, call_error_msg.request_type)
        self.assertEqual(u'wamp.error.canceled', call_error_msg.error)
Exemple #17
0
    def processInvocationError(self, session, error):
        """
      Implements :func:`autobahn.wamp.interfaces.IDealer.processInvocationError`
      """
        assert (session in self._session_to_registrations)

        if error.request in self._invocations:

            ## get original call message and calling session
            ##
            call_msg, call_session = self._invocations[error.request]

            ## validate payload
            ##
            try:
                self._router.validate('call_error', call_msg.procedure,
                                      error.args, error.kwargs)
            except Exception as e:
                reply = message.Error(
                    message.Call.MESSAGE_TYPE, call_msg.request,
                    ApplicationError.INVALID_ARGUMENT, [
                        "call error from procedure '{}' with invalid application payload: {}"
                        .format(call_msg.procedure, e)
                    ])
            else:
                reply = message.Error(message.Call.MESSAGE_TYPE,
                                      call_msg.request,
                                      error.error,
                                      args=error.args,
                                      kwargs=error.kwargs)

            ## the calling session might have been lost in the meantime ..
            ##
            if call_session._transport:
                call_session._transport.send(reply)

            ## the call is done
            ##
            del self._invocations[error.request]

        else:
            raise ProtocolError(
                "Dealer.onInvocationError(): ERROR received for non-pending request_type {} and request ID {}"
                .format(error.request_type, error.request))
Exemple #18
0
            def on_authorize_success(authorization):
                # the call to authorize the action _itself_ succeeded. now go on depending on whether
                # the action was actually authorized or not ..
                #
                if not authorization[u'allow']:
                    reply = message.Error(message.Call.MESSAGE_TYPE, call.request, ApplicationError.NOT_AUTHORIZED, [u"session is not authorized to call procedure '{0}'".format(call.procedure)])
                    self._router.send(session, reply)

                else:
                    self._call(session, call, registration, authorization)
def generate_test_messages():
   return [
      message.Hello(u"realm1", [role.RoleBrokerFeatures()]),
      message.Goodbye(),
      message.Heartbeat(123, 456),
      message.Yield(123456),
      message.Yield(123456, args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Yield(123456, progress = True),
      message.Interrupt(123456),
      message.Interrupt(123456, mode = message.Interrupt.KILL),
      message.Invocation(123456, 789123),
      message.Invocation(123456, 789123, args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Invocation(123456, 789123, timeout = 10000),
      message.Result(123456),
      message.Result(123456, args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Result(123456, progress = True),
      message.Cancel(123456),
      message.Cancel(123456, mode = message.Cancel.KILL),
      message.Call(123456, u'com.myapp.procedure1'),
      message.Call(123456, u'com.myapp.procedure1', args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Call(123456, u'com.myapp.procedure1', timeout = 10000),
      message.Unregistered(123456),
      message.Unregister(123456, 789123),
      message.Registered(123456, 789123),
      message.Register(123456, u'com.myapp.procedure1'),
      message.Register(123456, u'com.myapp.procedure1', pkeys = [10, 11, 12]),
      message.Event(123456, 789123),
      message.Event(123456, 789123, args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Event(123456, 789123, publisher = 300),
      message.Published(123456, 789123),
      message.Publish(123456, u'com.myapp.topic1'),
      message.Publish(123456, u'com.myapp.topic1', args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Publish(123456, u'com.myapp.topic1', excludeMe = False, exclude = [300], eligible = [100, 200, 300], discloseMe = True),
      message.Unsubscribed(123456),
      message.Unsubscribe(123456, 789123),
      message.Subscribed(123456, 789123),
      message.Subscribe(123456, u'com.myapp.topic1'),
      message.Subscribe(123456, u'com.myapp.topic1', match = message.Subscribe.MATCH_PREFIX),
      message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error1'),
      message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error1', args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'}),
      message.Call(123456, u'com.myapp.\u4f60\u597d\u4e16\u754c', args=[1, 2, 3]),
      message.Result(123456, args=[1, 2, 3], kwargs={u'en': u'Hello World', u'jp': u'\u3053\u3093\u306b\u3061\u306f\u4e16\u754c'})
   ]
   def processSubscribe(self, session, subscribe):
      """
      Implements :func:`autobahn.wamp.interfaces.IBroker.processSubscribe`
      """
      #assert(session in self._session_to_subscriptions)

      ## check topic URI
      ##
      if (not self._option_uri_strict and not  _URI_PAT_LOOSE_NON_EMPTY.match(subscribe.topic)) or \
         (    self._option_uri_strict and not _URI_PAT_STRICT_NON_EMPTY.match(subscribe.topic)):

         reply = message.Error(message.Subscribe.MESSAGE_TYPE, subscribe.request, ApplicationError.INVALID_URI, ["subscribe for invalid topic URI '{0}'".format(subscribe.topic)])
         session._transport.send(reply)

      else:

         ## authorize action
         ##
         d = self._as_future(self._router.authorize, session, subscribe.topic, IRouter.ACTION_SUBSCRIBE)

         def on_authorize_success(authorized):
            if not authorized:

               reply = message.Error(message.Subscribe.MESSAGE_TYPE, subscribe.request, ApplicationError.NOT_AUTHORIZED, ["session is not authorized to subscribe to topic '{0}'".format(subscribe.topic)])

            else:

               if not subscribe.topic in self._topic_to_sessions:
                  subscription = util.id()
                  self._topic_to_sessions[subscribe.topic] = (subscription, set())

               subscription, subscribers = self._topic_to_sessions[subscribe.topic]

               if not session in subscribers:
                  subscribers.add(session)

               if not subscription in self._subscription_to_sessions:
                  self._subscription_to_sessions[subscription] = (subscribe.topic, set())

               _, subscribers = self._subscription_to_sessions[subscription]
               if not session in subscribers:
                  subscribers.add(session)

               if not subscription in self._session_to_subscriptions[session]:
                  self._session_to_subscriptions[session].add(subscription)

               reply = message.Subscribed(subscribe.request, subscription)

            session._transport.send(reply)

         def on_authorize_error(err):
            reply = message.Error(message.Subscribe.MESSAGE_TYPE, subscribe.request, ApplicationError.AUTHORIZATION_FAILED, ["failed to authorize session for subscribing to topic URI '{0}': {1}".format(subscribe.topic, err.value)])
            session._transport.send(reply)

         self._add_future_callbacks(d, on_authorize_success, on_authorize_error)
Exemple #21
0
    def processYield(self, session, yield_):
        """
        Implements :func:`crossbar.router.interfaces.IDealer.processYield`
        """
        # assert(session in self._session_to_registrations)

        if yield_.request in self._invocations:

            # get the invocation request tracked for the caller
            #
            invocation_request = self._invocations[yield_.request]

            is_valid = True
            if yield_.payload is None:
                # validate normal args/kwargs payload
                try:
                    self._router.validate('call_result',
                                          invocation_request.call.procedure,
                                          yield_.args, yield_.kwargs)
                except Exception as e:
                    is_valid = False
                    reply = message.Error(
                        message.Call.MESSAGE_TYPE,
                        invocation_request.call.request,
                        ApplicationError.INVALID_ARGUMENT, [
                            u"call result from procedure '{0}' with invalid application payload: {1}"
                            .format(invocation_request.call.procedure, e)
                        ])
                else:
                    reply = message.Result(invocation_request.call.request,
                                           args=yield_.args,
                                           kwargs=yield_.kwargs,
                                           progress=yield_.progress)
            else:
                reply = message.Result(invocation_request.call.request,
                                       payload=yield_.payload,
                                       progress=yield_.progress,
                                       enc_algo=yield_.enc_algo,
                                       enc_key=yield_.enc_key,
                                       enc_serializer=yield_.enc_serializer)

            # the calling session might have been lost in the meantime ..
            #
            if invocation_request.caller._transport:
                self._router.send(invocation_request.caller, reply)

            # the call is done if it's a regular call (non-progressive) or if the payload was invalid
            #
            if not yield_.progress or not is_valid:
                del self._invocations[yield_.request]

        else:
            raise ProtocolError(
                u"Dealer.onYield(): YIELD received for non-pending request ID {0}"
                .format(yield_.request))
Exemple #22
0
   def test_ctor(self):
      e = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error1')
      msg = e.marshal()
      self.assertEqual(len(msg), 5)
      self.assertEqual(msg[0], message.Error.MESSAGE_TYPE)
      self.assertEqual(msg[1], message.Call.MESSAGE_TYPE)
      self.assertEqual(msg[2], 123456)
      self.assertEqual(msg[3], {})
      self.assertEqual(msg[4], u'com.myapp.error1')

      e = message.Error(message.Call.MESSAGE_TYPE, 123456, u'com.myapp.error1', args = [1, 2, 3], kwargs = {u'foo': 23, u'bar': u'hello'})
      msg = e.marshal()
      self.assertEqual(len(msg), 7)
      self.assertEqual(msg[0], message.Error.MESSAGE_TYPE)
      self.assertEqual(msg[1], message.Call.MESSAGE_TYPE)
      self.assertEqual(msg[2], 123456)
      self.assertEqual(msg[3], {})
      self.assertEqual(msg[4], u'com.myapp.error1')
      self.assertEqual(msg[5], [1, 2, 3])
      self.assertEqual(msg[6], {u'foo': 23, u'bar': u'hello'})
Exemple #23
0
    def detach(self, session):
        """
        Implements :func:`crossbar.router.interfaces.IDealer.detach`
        """
        if session in self._session_to_registrations:
            # send out Errors for any in-flight calls we have
            outstanding = self._callee_to_invocations.get(session, [])
            for invoke in outstanding:
                self.log.debug(
                    "Cancelling in-flight INVOKE with id={request} on"
                    " session {session}",
                    request=invoke.call.request,
                    session=session._session_id,
                )
                reply = message.Error(
                    message.Call.MESSAGE_TYPE,
                    invoke.call.request,
                    ApplicationError.CANCELED,
                    [u"callee disconnected from in-flight request"],
                )
                # send this directly to the caller's session
                # (it is possible the caller was disconnected and thus
                # _transport is None before we get here though)
                if invoke.caller._transport:
                    invoke.caller._transport.send(reply)

            for registration in self._session_to_registrations[session]:
                was_registered, was_last_callee = self._registration_map.drop_observer(
                    session, registration)

                if was_registered and was_last_callee:
                    self._registration_map.delete_observation(registration)

                # publish WAMP meta events
                #
                if self._router._realm:
                    service_session = self._router._realm.session
                    if service_session and not registration.uri.startswith(
                            u'wamp.'):
                        if was_registered:
                            service_session.publish(
                                u'wamp.registration.on_unregister',
                                session._session_id, registration.id)
                        if was_last_callee:
                            service_session.publish(
                                u'wamp.registration.on_delete',
                                session._session_id, registration.id)

            del self._session_to_registrations[session]

        else:
            raise Exception(u"session with ID {} not attached".format(
                session._session_id))
Exemple #24
0
            def on_authorize_success(authorized):
               if authorized:
                  registration_id = util.id()
                  self._procs_to_regs[register.procedure] = (registration_id, session, register.discloseCaller, register.discloseCallerTransport)
                  self._regs_to_procs[registration_id] = register.procedure

                  self._session_to_registrations[session].add(registration_id)

                  reply = message.Registered(register.request, registration_id)
               else:
                  reply = message.Error(message.Register.MESSAGE_TYPE, register.request, ApplicationError.NOT_AUTHORIZED, ["session is not authorized to register procedure '{0}'".format(register.procedure)])

               session._transport.send(reply)
Exemple #25
0
        def on_authorize_success(authorization):
            if not authorization[u'allow']:
                # error reply since session is not authorized to register
                #
                reply = message.Error(
                    message.Register.MESSAGE_TYPE, register.request,
                    ApplicationError.NOT_AUTHORIZED, [
                        u"session is not authorized to register procedure '{0}'"
                        .format(register.procedure)
                    ])

            else:
                # ok, session authorized to register. now get the registration
                #
                registration_extra = RegistrationExtra(register.invoke)
                registration, was_already_registered, is_first_callee = self._registration_map.add_observer(
                    session, register.procedure, register.match,
                    registration_extra)

                if not was_already_registered:
                    self._session_to_registrations[session].add(registration)

                # publish WAMP meta events
                #
                if self._router._realm:
                    service_session = self._router._realm.session
                    if service_session and not registration.uri.startswith(
                            u'wamp.'):
                        if is_first_callee:
                            registration_details = {
                                u'id': registration.id,
                                u'created': registration.created,
                                u'uri': registration.uri,
                                u'match': registration.match,
                                u'invoke': registration.extra.invoke,
                            }
                            service_session.publish(
                                u'wamp.registration.on_create',
                                session._session_id, registration_details)
                        if not was_already_registered:
                            service_session.publish(
                                u'wamp.registration.on_register',
                                session._session_id, registration.id)

                # acknowledge register with registration ID
                #
                reply = message.Registered(register.request, registration.id)

            # send out reply to register requestor
            #
            self._router.send(session, reply)
    def processRegister(self, session, register):
        """
      Implements :func:`autobahn.wamp.interfaces.IDealer.processRegister`
      """
        assert (session in self._session_to_registrations)

        ## check procedure URI
        ##
        if (not self._option_uri_strict and not  _URI_PAT_LOOSE_NON_EMPTY.match(register.procedure)) or \
           (    self._option_uri_strict and not _URI_PAT_STRICT_NON_EMPTY.match(register.procedure)):

            reply = message.Error(
                message.Register.MESSAGE_TYPE, register.request,
                ApplicationError.INVALID_URI, [
                    "register for invalid procedure URI '{}'".format(
                        register.procedure)
                ])

        else:

            if not register.procedure in self._procs_to_regs:
                registration_id = util.id()
                self._procs_to_regs[register.procedure] = (
                    registration_id, session, register.discloseCaller)
                self._regs_to_procs[registration_id] = register.procedure

                self._session_to_registrations[session].add(registration_id)

                reply = message.Registered(register.request, registration_id)
            else:
                reply = message.Error(
                    message.Register.MESSAGE_TYPE, register.request,
                    ApplicationError.PROCEDURE_ALREADY_EXISTS, [
                        "register for already registered procedure URI '{}'".
                        format(register.procedure)
                    ])

        session._transport.send(reply)
Exemple #27
0
 def on_authorize_error(err):
     """
     the call to authorize the action _itself_ failed (note this is
     different from the call to authorize succeed, but the
     authorization being denied)
     """
     self.log.failure(err)
     reply = message.Error(
         message.Register.MESSAGE_TYPE, register.request,
         ApplicationError.AUTHORIZATION_FAILED, [
             u"failed to authorize session for registering procedure '{0}': {1}"
             .format(register.procedure, err.value)
         ])
     session._transport.send(reply)
Exemple #28
0
 def on_authorize_error(err):
     """
     the call to authorize the action _itself_ failed (note this is
     different from the call to authorize succeed, but the
     authorization being denied)
     """
     self.log.failure("Authorization of 'call' for '{uri}' failed", uri=call.procedure, failure=err)
     reply = message.Error(
         message.Call.MESSAGE_TYPE,
         call.request,
         ApplicationError.AUTHORIZATION_FAILED,
         [u"failed to authorize session for calling procedure '{0}': {1}".format(call.procedure, err.value)]
     )
     self._router.send(session, reply)
Exemple #29
0
    def processUnregister(self, session, unregister):
        """
      Implements :func:`autobahn.wamp.interfaces.IDealer.processUnregister`
      """
        assert (session in self._session_to_registrations)

        if unregister.registration in self._regs_to_procs:

            ## map registration ID to procedure URI
            procedure = self._regs_to_procs[unregister.registration]

            ## get the session that originally registered the procedure
            _, reg_session, _ = self._procs_to_regs[procedure]

            if session != reg_session:
                ## procedure was registered by a different session!
                ##
                reply = message.Error(message.Unregister.MESSAGE_TYPE,
                                      unregister.request,
                                      ApplicationError.NO_SUCH_REGISTRATION)
            else:
                ## alright. the procedure had been registered by the session
                ## that now wants to unregister it.
                ##
                del self._procs_to_regs[procedure]
                del self._regs_to_procs[unregister.registration]

                self._session_to_registrations[session].discard(
                    unregister.registration)

                reply = message.Unregistered(unregister.request)
        else:
            reply = message.Error(message.Unregister.MESSAGE_TYPE,
                                  unregister.request,
                                  ApplicationError.NO_SUCH_REGISTRATION)

        session._transport.send(reply)
Exemple #30
0
    def _message_from_exception(self, request_type, request, exc):
        """
      Create a WAMP error message from an exception.

      :param request: The request ID this WAMP error message is for.
      :type request: int
      :param exc: The exception.
      :type exc: Instance of :class:`Exception` or subclass thereof.
      """
        if isinstance(exc, exception.ApplicationError):
            msg = message.Error(request_type,
                                request,
                                six.u(exc.error),
                                args=list(exc.args),
                                kwargs=exc.kwargs)
        else:
            if exc.__class__ in self._ecls_to_uri_pat:
                error = self._ecls_to_uri_pat[exc.__class__][0]._uri
            else:
                error = u"wamp.error.runtime_error"

            if hasattr(exc, 'args'):
                if hasattr(exc, 'kwargs'):
                    msg = message.Error(request_type,
                                        request,
                                        error,
                                        args=exc.args,
                                        kwargs=exc.kwargs)
                else:
                    msg = message.Error(request_type,
                                        request,
                                        error,
                                        args=exc.args)
            else:
                msg = message.Error(request_type, request, error)

        return msg