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)
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))
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)
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)
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'))
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'})
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)
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)
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)
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))
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)
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)
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)
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)
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))
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)
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))
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'})
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))
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_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)
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)
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)
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)
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