def process_call_function_command(message, sender, connection): try: interface = autobus.lookup_interface(message["interface_name"]) function = interface.lookup_function(message["function"]) except (autobus.NoSuchInterfaceException, autobus.NoSuchFunctionException) as e: connection.send_error(message, text=str(e)) return if function.special: function.invoke_special(message, connection) return invoke_message = create_message(RunFunctionCommand, interface_name=interface.name, function=function.name, arguments=message["arguments"]) interface.connection.send(invoke_message) print ("Sending run command to " + str(interface.connection.id) + " with message id " + str(invoke_message["message_id"]) + " whose response is to be forwarded with id " + str(message["message_id"])) # FIXME: This causes a response to a function invocation sent as a notification # to still be sent when the function returns on the remote side. We need to # somehow not add the message to this list and perhaps suppress the "sporadic # message received" warning that would consequently be printed to stdout once # the remote client sends back the return value if the incoming message here # is a notification. interface.connection.pending_responses[invoke_message["message_id"]] = ( sender, message["message_id"])
def process_register_listener_command(message, sender, connection): interface_name = message["interface_name"] event_name = message["event_name"] autobus.register_event_listener(interface_name, event_name, sender) connection.listeners.append((interface_name, event_name)) response = create_message(RegisterListenerResponse, message, interface_name=interface_name, event_name=event_name) connection.send(response)
def process_activate_hack_command(message, sender, connection): hack = message["hack"] valid = True if hack == "buffer": print "Buffer hack activated for connection " + str(sender) connection.output_thread.enable_buffer_hack = True else: valid = False if valid: connection.send(create_message(ActivateHackResponse, message)) else: connection.send_error(message, text="No such hack: " + str(hack))
def invoke_special(self, message, connection): args = message["arguments"] args = [decode_object(arg) for arg in args] try: return_value = self.special_target(*args) except Exception as e: print_exc() return_value = e result = encode_object(return_value) response = create_message(CallFunctionResponse, message, return_value=result) connection.send(response)
def process_register_interface_command(message, sender, connection): name = message["name"] doc = message["doc"] print "Registering interface with name " + name interface = autobus.Interface(name, connection, doc) try: interface.register() except KeyError: connection.send_error(message, text="An interface with the same name " "is already registered.") return response = create_message(RegisterInterfaceResponse, message) connection.send(response)
def process_get_object_value_command(message, sender, connection): interface_name = message["interface_name"] object_name = message["object_name"] try: interface = autobus.lookup_interface(interface_name) object = interface.object_map[object_name] object_value = object.get() except (autobus.NoSuchInterfaceException, KeyError): # Object doesn't exist yet object_value = encode_object(None) response = create_message(GetObjectValueResponse, message, interface_name=interface_name, object_name=object_name, value=object_value) connection.send(response)
def send_error(self, in_reply_to=None, **kwargs): """ Sends an error back to the client. If in_reply_to is itself a notification message, no message will be sent back. Otherwise, an ErrorResponse to the specified message will be sent. The error's fields will be initialized to have any additional keyword arugments specified. You'll typically do: send_error(some_message, text="A random problem happened") """ if in_reply_to == None: in_reply_to = NOTIFICATION message = create_message(ErrorResponse, in_reply_to, **kwargs) self.send(message)
def process_watch_object_command(message, sender, connection): interface_name = message["interface_name"] object_name = message["object_name"] autobus.register_object_watch(interface_name, object_name, sender) connection.watches.append((interface_name, object_name)) try: interface = autobus.lookup_interface(interface_name) object = interface.object_map[object_name] object_value = object.get() except (autobus.NoSuchInterfaceException, KeyError): # Object doesn't exist yet object_value = encode_object(None) response = create_message(WatchObjectResponse, message, interface_name=interface_name, object_name=object_name, value=object_value) connection.send(response)
def notify(self, arguments): """ Sends a message to all connections listening for this event containing the specified arguments, which should be passed into this function as a (possibly empty) list or tuple. """ listener_spec = (self.interface.name, self.name) if listener_spec in listener_map: message = create_message(FireEventCommand, NOTIFICATION, interface_name=self.interface.name, event_name=self.name, arguments=arguments) encoded_message = dumps(message) for connection_id in listener_map[listener_spec]: connection = connection_map[connection_id] connection.send(encoded_message)
def process_run_function_response(message, sender, connection): response = create_message(CallFunctionResponse, RESPONSE, return_value=message["return_value"]) if not message["message_id"] in connection.pending_responses: # Sporadic response received, just ignore it print ("Sporadic run response received from connection " + str(sender) + " for reported message id " + str(message["message_id"]) + ". It will be ignored.") return response_connection_id, response_message_id = connection.pending_responses[message["message_id"]] del connection.pending_responses[message["message_id"]] response["message_id"] = response_message_id if response_connection_id in autobus.connection_map: # Make sure the connection # listening for the response is still alive response_connection = autobus.connection_map[response_connection_id] response_connection.send(response)
def process_register_event_command(message, sender, connection): interface_name = message["interface_name"] event_name = message["event_name"] doc = message["doc"] try: interface = autobus.lookup_interface(interface_name, sender) except autobus.NoSuchInterfaceException as e: connection.send_error(message, text=str(e)) return try: interface.create_and_register_event(sender, event_name, doc) except KeyError: connection.send_error(message, "An event with that name has already " "been registered on that interface.") return response = create_message(RegisterEventResponse, message) connection.send(response)
def notify(self): """ Sends a message to all connections watching this object containing the object's current value. This only calls self.get() once, so it's not generally processor-intensive even when lots of connections are listening for changes to this object. """ watch_spec = (self.interface.name, self.name) if watch_spec in watch_map: current_value = self.get() message = create_message(SetObjectCommand, NOTIFICATION, interface_name=self.interface.name, object_name=self.name, value=current_value) encoded_message = dumps(message) for connection_id in watch_map[watch_spec]: connection = connection_map[connection_id] connection.send(encoded_message)
def process_register_function_command(message, sender, connection): interface_name = message["interface_name"] function_names = message["name"] docs = message["doc"] if isinstance(function_names, basestring) and isinstance(docs, basestring): function_names = [function_names] docs = [docs] try: interface = autobus.lookup_interface(interface_name, sender) except autobus.NoSuchInterfaceException as e: connection.send_error(message, text=str(e)) return try: for function_name, doc in zip(function_names, docs): interface.register_function(sender, function_name, doc, notify=False) except KeyError: connection.send_error(message, "A function with that name has already " "been registered on that interface.") autobus.autobus_interface.notify_object("interface_items") return autobus.autobus_interface.notify_object("interface_items") response = create_message(RegisterFunctionResponse, message) connection.send(response)
def create_error_response(message_id, text): return create_message(ErrorResponse, RESPONSE, message_id=message_id, text=text)
def send_new(self, *args, **kwargs): """ Exactly the same as self.send(libautobus.create_message(*args, **kwargs)). """ self.send(create_message(*args, **kwargs))