Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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
Example #4
0
    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