def send_message_blocking(self, message): """ Call from another thread to send a message to the server and wait for the result. Accepts a serializable message. Based on the response either the result is returned or an exception is raised. Parameters ---------- message : :class:`quartjes.connector.messages.Message` Message object to send to the server. Returns ------- result The response returned by the server. Raises ------ MessageHandleError Something went wrong while handling the message on the server. ConnectionError There is an issue with the connection to the server. TimeoutError No response was received within the set timeout. """ serial_message = create_message_string(message) try: result_msg = threads.blockingCallFromThread(reactor, self._r_send_message_and_wait, message.id, serial_message) if result_msg.result_code > 0: raise MessageHandleError(error_code=result_msg.result_code, error_details = result_msg.result) return result_msg.result except TimeoutError: self._waiting_messages.pop(message.id, None) raise
def _r_send_error(self, result, protocol): """ Send an exception to the client. This is the only method that creates XML inside the reactor thread. This might cause problems if the error contains a lot of data, but for now we do not expect this to be the case. Parameters ---------- result Result from twisted encapsulating an exception. protocol Twisted protocol object connected to the client that should receive event notifications. Raises ------ Exception If the exception received is not of type :class:`quartjes.connector.exceptions.MessageHandleError` we reraise the exception instead of sending it to the client. """ error = result.value if not isinstance(error, MessageHandleError): raise error print("Error occurred: %s" % result) msgid = None if error.original_message is not None: msgid = error.original_message.id msg = ResponseMessage(result_code=error.error_code, response_to=msgid, result=error.error_details) protocol.send_message(create_message_string(msg))
def _parse_message(self, string, protocol): """ Parse the contents of a message. Also do processing outside the reactor thread. This method should run in a separate thread to prevent blocking the reactor. Both the parsed original message and a possible return message are returned in a special MessageResult instance. Parameters ---------- string : string Incoming message string to handle. protocol Twisted protocol object connected to the client. Returns ------- result : :class:`MessageResult` Result of parsing the message. Raises ------ MessageHandleError If any error occurs while handling the message. """ #print("Parsing message: %s" % string) msg = parse_message_string(string) result = MessageResult(original_message=msg) if isinstance(msg, MethodCallMessage): # Handle method call res = self._method_call(msg) response_msg = ResponseMessage(result_code=0, result=res, response_to=msg.id) result.response = create_message_string(response_msg) elif isinstance(msg, SubscribeMessage): # Handle subscription to event response_msg = ResponseMessage(result_code=0, result=None, response_to=msg.id) result.response = create_message_string(response_msg) else: raise MessageHandleError(MessageHandleError.RESULT_UNEXPECTED_MESSAGE, msg) return result
def _r_successful_connection(self): """ Handle a succesful connection. Resets the reconnect backoff and makes sure all events that were already subscribed to are active again. """ self.resetDelay() for (service_name, event_name) in self._event_callbacks.keys(): msg = SubscribeMessage(service_name=service_name, event_name=event_name) serial_message = create_message_string(msg) self._current_protocol.send_message(serial_message)
def test_create_and_parse(self): """ Test whether a message can be correctly serialised and deserialised again. """ string = create_message_string(self.message) self.assertIsNotNone(string) self.assertGreater(len(string), 0) result = parse_message_string(string) self.assertEqual(self.message, result)
def test_create_and_parse(self): """ Test whether a message can be correctly serialised and deserialised again. """ string = create_message_string(self.message) self.assertIsNotNone(string) self.assertGreater(len(string), 0) result = parse_message_string(string) self.assertEqual(self.message, result)
def _r_on_connection_established(self, protocol): """ Handle an incoming connection. Parameters ---------- protocol Twisted protocol object connected to the client. """ self._connections[protocol.id] = protocol motd = ServerMotdMessage(client_id=protocol.id) protocol.send_message(create_message_string(motd))
def send_event(self, service_name, event_name, listener, *pargs, **kwargs): """ Notify a client of an event. Parameters ---------- service_name : string Name of the service firing the event. event_name : string Name of the event being fired. listener Twisted protocol object connected to the client that should receive event notifications. *pargs Any additional positional arguments will be sent as positional arguments to the client callback. **kwargs Any additional keyword arguments will be sent as keyword arguments to the client callback. """ msg = EventMessage(service_name, event_name, pargs, kwargs) string = create_message_string(msg) reactor.callFromThread(listener.send_message, string) #@UndefinedVariable