def send_reply(self, response, method_response): """Send back a reply to an rpc call. response (dict): the metadata of the reply. method_response (object): the actual returned value. """ try: response["__data"] = method_response json_message = encode_json(response) except ValueError as error: logger.warning("Cannot send response because of " + "encoding error. %s" % repr(error)) return self._push_right(json_message)
def send_reply(self, response, method_response, binary_response): """Send back a reply to an rpc call. response (dict): the metadata of the reply. method_response (object): the actual returned value. binary_response (bool): True if method_response is a binary string. """ try: if binary_response: response["__data"] = None binary_message = encode_binary(method_response) else: response["__data"] = method_response binary_message = "" json_message = encode_json(response) json_length = encode_length(len(json_message)) except ValueError as error: logger.warning("Cannot send response because of " + "encoding error. %s" % repr(error)) return self._push_right(json_length + json_message + binary_message)
def execute_rpc(self, method, data, callback=None, plus=None, timeout=None): """Method to send an RPC request to the remote service. The message sent to the remote service is of this kind: {"__method": <name of the requested method> "__data": {"<name of first arg>": <value of first arg, ... } "__id": <16 letters random ID> } The __id field is put by the pre_execute method of RPCRequest. Also, if in the arguments we have a field named "binary_data", we send it separatedly as a binary attachment after the JSON encoded message. method (string): the name of the method to call. data (object): the object to pass to the remote method. callback (function): method to call with the RPC response. plus (object): additional object to be passed to the callback. timeout (int/bool): the time (in seconds) to wait for the response of a yielded call; None to signal that the call is not yielded, True to give a default value. return (bool/dict): False if the remote service is not connected; in a non-yielded call True if it is connected; in a yielded call, a dictionary with fields 'completed', 'data', and 'error'. """ # Sanity checks. if callback is not None and timeout is not None: raise ValueError("Cannot use both callback and timeout.") if timeout is not None and plus is not None: raise ValueError("Cannot use both timeout and plus.") # Default timeout. if isinstance(timeout, types.BooleanType): if timeout: timeout = 10 else: raise ValueError("Timeout cannot be False.") # Try to connect, or fail. if not self.connected: self.connect_remote_service() if not self.connected: return False # We start building the request message message = {} message["__method"] = method message["__data"] = data # If timeout is valid, we are in a coroutine, and we use our # callback. if timeout is not None: cb_result = {"data": None, "error": None, "completed": False} @rpc_callback def callback(self, data, error=None): cb_result["data"] = data cb_result["error"] = error cb_result["completed"] = True # And we remember that we need to wait for a reply request = RPCRequest(message, self.service, callback, plus) message = request.pre_execute() # We encode the request and send it if "binary_data" not in data: try: json_message = encode_json(message) json_length = encode_length(len(json_message)) binary_message = "" except ValueError: msg = "Cannot send request of method %s because of " \ "encoding error." % method request.complete({"__error": msg}) return else: try: binary_data = data["binary_data"] del data["binary_data"] json_message = encode_json(message) json_length = encode_length(len(json_message)) binary_message = encode_binary(binary_data) except ValueError: msg = "Cannot send request of method %s because of " \ "encoding error." % method request.complete({"__error": msg}) return ret = self._push_right(json_length + json_message + binary_message) if not ret: msg = "Transfer interrupted" request.complete({"__error": msg}) return if timeout is not None: send_time = time.time() while not self.service._exit and \ not cb_result["completed"] and \ time.time() - send_time < timeout: self.service._step() return cb_result return True