Add RPC caller and RPC caller session components

Change rpc_caller_interface to follow the new RPC protocol's primitives.
Introduce rpc_caller_session as a session layer built on top of the
rpc_caller_interface. An opened session is tied to an interface of an
RPC endpoint.

Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: Ibd75998d6a9d511b4adc79274cce34b59d9730f8
diff --git a/components/rpc/common/caller/component.cmake b/components/rpc/common/caller/component.cmake
index 9cb5138..0c8934a 100644
--- a/components/rpc/common/caller/component.cmake
+++ b/components/rpc/common/caller/component.cmake
@@ -8,6 +8,16 @@
 	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
 endif()
 
+target_include_directories(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}"
+)
+
+set_property(TARGET ${TGT} APPEND PROPERTY PUBLIC_HEADER
+	"${CMAKE_CURRENT_LIST_DIR}/rpc_caller_session.h"
+	"${CMAKE_CURRENT_LIST_DIR}/rpc_caller.h"
+	)
+
 target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/rpc_caller_session.c"
 	"${CMAKE_CURRENT_LIST_DIR}/rpc_caller.c"
 	)
diff --git a/components/rpc/common/caller/rpc_caller.c b/components/rpc/common/caller/rpc_caller.c
index 2dceabe..4af9d8c 100644
--- a/components/rpc/common/caller/rpc_caller.c
+++ b/components/rpc/common/caller/rpc_caller.c
@@ -1,39 +1,63 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <rpc_caller.h>
-#include <stdint.h>
-#include <protocols/rpc/common/packed-c/encoding.h>
+#include "rpc_caller.h"
 
-void rpc_caller_init(struct rpc_caller *s, void *context)
+rpc_status_t rpc_caller_open_session(struct rpc_caller_interface *caller,
+				     const struct rpc_uuid *service_uuid,
+				     uint16_t endpoint_id)
 {
-	s->context = context;
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
 
-	/* The default encoding scheme - may be overridden by a client */
-	s->encoding = TS_RPC_ENCODING_PACKED_C;
+	return caller->open_session(caller->context, service_uuid, endpoint_id);
 }
 
-void rpc_caller_set_encoding_scheme(struct rpc_caller *s, uint32_t encoding)
+rpc_status_t rpc_caller_find_and_open_session(struct rpc_caller_interface *caller,
+					      const struct rpc_uuid *service_uuid)
 {
-	s->encoding = encoding;
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
+
+	return caller->find_and_open_session(caller->context, service_uuid);
 }
 
-rpc_call_handle rpc_caller_begin(struct rpc_caller *s,
-								uint8_t **req_buf, size_t req_len)
+rpc_status_t rpc_caller_close_session(struct rpc_caller_interface *caller)
 {
-	return s->call_begin(s->context, req_buf, req_len);
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
+
+	return caller->close_session(caller->context);
 }
 
-rpc_status_t rpc_caller_invoke(struct rpc_caller *s, rpc_call_handle handle,
-			uint32_t opcode, rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len)
+rpc_status_t rpc_caller_create_shared_memory(struct rpc_caller_interface *caller, size_t length,
+					     struct rpc_caller_shared_memory *shared_memory)
 {
-	return s->call_invoke(s->context, handle, opcode, opstatus, resp_buf, resp_len);
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
+
+	return caller->create_shared_memory(caller->context, length, shared_memory);
 }
 
-void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle)
+rpc_status_t rpc_caller_release_shared_memory(struct rpc_caller_interface *caller,
+					      struct rpc_caller_shared_memory *shared_memory)
 {
-	s->call_end(s->context, handle);
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
+
+	return caller->release_shared_memory(caller->context, shared_memory);
+}
+
+rpc_status_t rpc_caller_call(struct rpc_caller_interface *caller, uint16_t opcode,
+			     struct rpc_caller_shared_memory *shared_memory, size_t request_length,
+			     size_t *response_length, service_status_t *service_status)
+{
+	if (!caller)
+		return RPC_ERROR_INVALID_VALUE;
+
+	return caller->call(caller->context, opcode, shared_memory, request_length,
+			    response_length, service_status);
 }
diff --git a/components/rpc/common/caller/rpc_caller.h b/components/rpc/common/caller/rpc_caller.h
new file mode 100644
index 0000000..9581fd0
--- /dev/null
+++ b/components/rpc/common/caller/rpc_caller.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPC_CALLER_H
+#define RPC_CALLER_H
+
+#include "rpc_status.h"
+#include "rpc_uuid.h"
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * The rpc_caller public interface may be exported as a public interface to
+ * a shared library.
+ */
+#ifdef EXPORT_PUBLIC_INTERFACE_RPC_CALLER
+#define RPC_CALLER_EXPORTED __attribute__((__visibility__("default")))
+#else
+#define RPC_CALLER_EXPORTED
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Shared memory descriptor of an RPC caller
+ *
+ */
+struct rpc_caller_shared_memory {
+	uint64_t id;	/** Implementation defined ID of the shared memory */
+	void *buffer;	/** Address of the shared memory (virtual) */
+	size_t size;	/** Size of the shared memory */
+};
+
+struct rpc_caller_interface {
+	void *context;
+
+	rpc_status_t (*open_session)(void *context, const struct rpc_uuid *service_uuid,
+				     uint16_t endpoint_id);
+	rpc_status_t (*find_and_open_session)(void *context, const struct rpc_uuid *service_uuid);
+	rpc_status_t (*close_session)(void *context);
+
+	rpc_status_t (*create_shared_memory)(void *context, size_t size,
+					     struct rpc_caller_shared_memory *shared_memory);
+	rpc_status_t (*release_shared_memory)(void *context,
+					      struct rpc_caller_shared_memory *shared_memory);
+
+	rpc_status_t (*call)(void *context, uint16_t opcode,
+			     struct rpc_caller_shared_memory *shared_memory, size_t request_length,
+			     size_t *response_length, service_status_t *service_status);
+};
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_open_session(struct rpc_caller_interface *caller,
+				     const struct rpc_uuid *service_uuid,
+				     uint16_t endpoint_id);
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_find_and_open_session(struct rpc_caller_interface *caller,
+					      const struct rpc_uuid *service_uuid);
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_close_session(struct rpc_caller_interface *caller);
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_create_shared_memory(struct rpc_caller_interface *caller, size_t size,
+					     struct rpc_caller_shared_memory *shared_memory);
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_release_shared_memory(struct rpc_caller_interface *caller,
+					      struct rpc_caller_shared_memory *shared_memory);
+
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_call(struct rpc_caller_interface *caller, uint16_t opcode,
+			     struct rpc_caller_shared_memory *shared_memory, size_t request_length,
+			     size_t *response_length, service_status_t *service_status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPC_CALLER_H */
diff --git a/components/rpc/common/caller/rpc_caller_session.c b/components/rpc/common/caller/rpc_caller_session.c
new file mode 100644
index 0000000..d72a318
--- /dev/null
+++ b/components/rpc/common/caller/rpc_caller_session.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "rpc_caller_session.h"
+#include "util.h"
+#include <string.h>
+
+static rpc_status_t initalize_shared_memory(struct rpc_caller_session *session,
+					    struct rpc_caller_interface *caller,
+					    size_t shared_memory_size)
+{
+	if (shared_memory_size) {
+		rpc_status_t status = RPC_ERROR_INTERNAL;
+
+		status = rpc_caller_create_shared_memory(caller, shared_memory_size,
+							 &session->shared_memory);
+		if (status) {
+			rpc_caller_close_session(caller);
+			return status;
+		}
+
+		session->shared_memory_policy = alloc_for_session;
+	} else {
+		session->shared_memory = (struct rpc_caller_shared_memory){ 0 };
+		session->shared_memory_policy = alloc_for_each_call;
+	}
+
+	return RPC_SUCCESS;
+}
+
+rpc_status_t rpc_caller_session_open(struct rpc_caller_session *session,
+				     struct rpc_caller_interface *caller,
+				     const struct rpc_uuid *service_uuid,
+				     uint16_t endpoint_id,
+				     size_t shared_memory_size)
+{
+	rpc_status_t status = RPC_ERROR_INTERNAL;
+
+	if (!session || !caller || !service_uuid)
+		return RPC_ERROR_INVALID_VALUE;
+
+	status = rpc_caller_open_session(caller, service_uuid, endpoint_id);
+	if (status)
+		return status;
+
+	status = initalize_shared_memory(session, caller, shared_memory_size);
+	if (status)
+		return status;
+
+	session->caller = caller;
+	session->is_call_transaction_in_progress = false;
+	session->request_length = 0;
+
+	return status;
+}
+
+rpc_status_t rpc_caller_session_find_and_open(struct rpc_caller_session *session,
+					      struct rpc_caller_interface *caller,
+					      const struct rpc_uuid *service_uuid,
+					      size_t shared_memory_size)
+{
+	rpc_status_t status = RPC_ERROR_INTERNAL;
+
+	if (!session || !caller || !service_uuid)
+		return RPC_ERROR_INVALID_VALUE;
+
+	status = rpc_caller_find_and_open_session(caller, service_uuid);
+	if (status)
+		return status;
+
+	status = initalize_shared_memory(session, caller, shared_memory_size);
+	if (status)
+		return status;
+
+	session->caller = caller;
+	session->is_call_transaction_in_progress = false;
+	session->request_length = 0;
+
+	return status;
+}
+
+rpc_status_t rpc_caller_session_close(struct rpc_caller_session *session)
+{
+	if (!session)
+		return RPC_ERROR_INVALID_VALUE;
+
+	if (session->is_call_transaction_in_progress)
+		return RPC_ERROR_INVALID_STATE;
+
+	if (session->shared_memory_policy == alloc_for_session) {
+		rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
+
+		rpc_status = rpc_caller_release_shared_memory(session->caller,
+							      &session->shared_memory);
+		if (rpc_status != RPC_SUCCESS)
+			return rpc_status;
+	}
+
+	return rpc_caller_close_session(session->caller);
+}
+
+rpc_call_handle rpc_caller_session_begin(struct rpc_caller_session *session,
+					 uint8_t **request_buffer, size_t request_length,
+					 size_t response_max_length)
+{
+	rpc_status_t status = RPC_ERROR_INTERNAL;
+	size_t required_buffer_length = MAX(request_length, response_max_length);
+
+	if (required_buffer_length > UINT32_MAX)
+		return NULL;
+
+	if (!session || !request_buffer || session->is_call_transaction_in_progress)
+		return NULL;
+
+	switch (session->shared_memory_policy) {
+	case alloc_for_each_call:
+		if (session->shared_memory.buffer || session->shared_memory.size)
+			return NULL; /* There's already a shared memory */
+
+		status = rpc_caller_create_shared_memory(session->caller, required_buffer_length,
+							 &session->shared_memory);
+		if (status)
+			return NULL; /* Failed to create shared memory */
+		break;
+
+	case alloc_for_session:
+		if (!session->shared_memory.buffer || !session->shared_memory.size)
+			return NULL; /* There's no shared memory */
+
+		if (session->shared_memory.size < required_buffer_length)
+			return NULL; /* The allocated shared memory is too small */
+		break;
+
+	default:
+		/* Invalid shared memory policy */
+		return NULL;
+	}
+
+	*request_buffer = session->shared_memory.buffer;
+
+	session->is_call_transaction_in_progress = true;
+	session->request_length = request_length;
+
+	return (rpc_call_handle)session;
+}
+
+rpc_status_t rpc_caller_session_invoke(rpc_call_handle handle, uint32_t opcode,
+				       uint8_t **response_buffer, size_t *response_length,
+				       service_status_t *service_status)
+{
+	struct rpc_caller_session *session = (struct rpc_caller_session *)handle;
+	rpc_status_t status = RPC_ERROR_INTERNAL;
+
+	if (!handle || !response_buffer || !response_length)
+		return RPC_ERROR_INVALID_VALUE;
+
+	if (!session->is_call_transaction_in_progress)
+		return RPC_ERROR_INVALID_STATE;
+
+	if (session->request_length &&
+	    (!session->shared_memory.buffer || !session->shared_memory.size))
+		return RPC_ERROR_INVALID_STATE;
+
+	status = rpc_caller_call(session->caller, opcode, &session->shared_memory,
+				session->request_length, response_length, service_status);
+	if (status || *response_length > session->shared_memory.size) {
+		*response_buffer = NULL;
+		*response_length = 0;
+		return status;
+	}
+
+	*response_buffer = session->shared_memory.buffer;
+
+	return status;
+}
+
+rpc_status_t rpc_caller_session_end(rpc_call_handle handle)
+{
+	struct rpc_caller_session *session = (struct rpc_caller_session *)handle;
+	rpc_status_t status = RPC_ERROR_INTERNAL;
+
+	if (!handle)
+		return RPC_ERROR_INVALID_VALUE;
+
+	if (!session->is_call_transaction_in_progress)
+		return RPC_ERROR_INVALID_STATE;
+
+	if (session->request_length &&
+	    (!session->shared_memory.buffer || !session->shared_memory.size))
+		return RPC_ERROR_INVALID_STATE; /* There's no shared memory */
+
+	switch (session->shared_memory_policy) {
+	case alloc_for_each_call:
+		status = rpc_caller_release_shared_memory(session->caller,
+								&session->shared_memory);
+		if (status)
+			return status; /* Failed to release shared memory */
+
+		session->shared_memory = (struct rpc_caller_shared_memory){ 0 };
+		break;
+
+	case alloc_for_session:
+		/* Nothing to do */
+		break;
+
+	default:
+		return RPC_ERROR_INVALID_STATE;
+	}
+
+	session->is_call_transaction_in_progress = false;
+	session->request_length = 0;
+
+	return RPC_SUCCESS;
+}
diff --git a/components/rpc/common/caller/rpc_caller_session.h b/components/rpc/common/caller/rpc_caller_session.h
new file mode 100644
index 0000000..debcf19
--- /dev/null
+++ b/components/rpc/common/caller/rpc_caller_session.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPC_CALLER_SESSION_H
+#define RPC_CALLER_SESSION_H
+
+#include "rpc_caller.h"
+#include "rpc_status.h"
+#include "rpc_uuid.h"
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *rpc_call_handle;
+
+enum rpc_caller_memory_policy {
+	alloc_for_each_call = 0,
+	alloc_for_session,
+};
+
+/**
+ * @brief RPC caller session
+ *
+ * Builds a session on top of the rpc_caller_interface. It provides high level functions for service
+ * caller implementations and for prior service discovery.
+ */
+struct rpc_caller_session {
+	/** Caller interface */
+	struct rpc_caller_interface *caller;
+
+	/** Shared memory instance for the exchanging of RPC request and response parameters. */
+	struct rpc_caller_shared_memory shared_memory;
+
+	/** Controls how and when the shared memory is allocated for the RPC calls. */
+	enum rpc_caller_memory_policy shared_memory_policy;
+
+	/**
+	 * Indicates if a call transaction has been started by the begin function but was not
+	 * finished yet (i.e. end was not called).
+	 */
+	bool is_call_transaction_in_progress;
+
+	/**
+	 * Stores the request length of the current transaction. Its value is set by the begin
+	 * function and then used in the invoke step.
+	 */
+	size_t request_length;
+};
+
+/**
+ * @brief
+ *
+ * @param session
+ * @param caller
+ * @param service_uuid
+ * @param endpoint_id
+ * @param shared_memory_size
+ * @return RPC_CALLER_EXPORTED
+ */
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_session_open(struct rpc_caller_session *session,
+				     struct rpc_caller_interface *caller,
+				     const struct rpc_uuid *service_uuid,
+				     uint16_t endpoint_id,
+				     size_t shared_memory_size);
+
+/**
+ * @brief
+ *
+ * @param session
+ * @param caller
+ * @param service_uuid
+ * @param shared_memory_size
+ * @return RPC_CALLER_EXPORTED
+ */
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_session_find_and_open(struct rpc_caller_session *session,
+					      struct rpc_caller_interface *caller,
+					      const struct rpc_uuid *service_uuid,
+					      size_t shared_memory_size);
+
+/**
+ * @brief Closes the RPC caller session
+ *
+ * @param session Caller session instance
+ * @return RPC_CALLER_EXPORTED
+ */
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_session_close(struct rpc_caller_session *session);
+
+/**
+ * @brief Begins an RPC call
+ *
+ * The function returns a buffer where the service caller can build the request.
+ *
+ * @param session Caller session instance
+ * @param request_buffer Pointer of the request buffer
+ * @param request_length Request length
+ * @param response_max_length Expected maximal length of the response
+ * @return rpc_call_handle Handle of the started call
+ */
+RPC_CALLER_EXPORTED
+rpc_call_handle rpc_caller_session_begin(struct rpc_caller_session *session,
+					 uint8_t **request_buffer,
+					 size_t request_length,
+					 size_t response_max_length);
+
+/**
+ * @brief Invoke phase of the RPC call
+ *
+ * Invokes the call on the remote side and returns the response buffer and service status. The
+ * service caller can parse the response from the response buffer.
+ * After this call the request buffer is not available for the service caller.
+ *
+ * @param handle RPC call handle
+ * @param opcode The opcode of the remote function
+ * @param response_buffer Pointer of the response buffer
+ * @param response_length Length of the response buffer
+ * @param service_status Service specific status code
+ * @return RPC_CALLER_EXPORTED
+ */
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_session_invoke(rpc_call_handle handle, uint32_t opcode,
+				       uint8_t **response_buffer,
+				       size_t *response_length,
+				       service_status_t *service_status);
+
+/**
+ * @brief Ends the RPC call
+ *
+ * Indicates if the response has been parsed by the service calls and the RPC session can free the
+ * response buffer.
+ *
+ * @param handle RPC call handle
+ * @return RPC_CALLER_EXPORTED
+ */
+RPC_CALLER_EXPORTED
+rpc_status_t rpc_caller_session_end(rpc_call_handle handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPC_CALLER_SESSION_H */
diff --git a/components/rpc/common/interface/component.cmake b/components/rpc/common/interface/component.cmake
index 51f1f24..ae219d6 100644
--- a/components/rpc/common/interface/component.cmake
+++ b/components/rpc/common/interface/component.cmake
@@ -9,7 +9,6 @@
 endif()
 
 set_property(TARGET ${TGT} APPEND PROPERTY PUBLIC_HEADER
-	"${CMAKE_CURRENT_LIST_DIR}/rpc_caller.h"
 	"${CMAKE_CURRENT_LIST_DIR}/rpc_status.h"
 	"${CMAKE_CURRENT_LIST_DIR}/rpc_uuid.h"
 	)
diff --git a/components/rpc/common/interface/rpc_caller.h b/components/rpc/common/interface/rpc_caller.h
deleted file mode 100644
index 387489c..0000000
--- a/components/rpc/common/interface/rpc_caller.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef RPC_CALLER_H
-#define RPC_CALLER_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include "rpc_status.h"
-
-/*
- * The rpc_caller puplic interface may be exported as a public interface to
- * a shared library.
- */
-#ifdef EXPORT_PUBLIC_INTERFACE_RPC_CALLER
-#define RPC_CALLER_EXPORTED __attribute__((__visibility__("default")))
-#else
-#define RPC_CALLER_EXPORTED
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Defines an abstract interface for calling operations provided by an rpc endpoint.
- * Concrete specializations will map the an RPC or direct calling mechanism to
- * suite the deployment.
- */
-
-typedef void *rpc_call_handle;
-
-struct rpc_caller
-{
-	void *context;
-	uint32_t encoding;
-
-	/* A concrete rpc_caller implements these methods */
-	rpc_call_handle (*call_begin)(void *context, uint8_t **req_buf, size_t req_len);
-
-	rpc_status_t (*call_invoke)(void *context, rpc_call_handle handle, uint32_t opcode,
-		     	rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len);
-
-	void (*call_end)(void *context, rpc_call_handle handle);
-};
-
-/*
- * Called by a concrete rpc_caller to initialise the base rpc_caller.
- */
-void rpc_caller_init(struct rpc_caller *s, void *context);
-
-/*
- * Allows a client to specify the parameter encoding scheme that the client
- * intends to use during an RPC session.  It is the client's responsiblity
- * to choose an encoding scheme that is supported by the remote interface.
- */
-RPC_CALLER_EXPORTED void rpc_caller_set_encoding_scheme(struct rpc_caller *s,
-			uint32_t encoding);
-
-/*
- * Starts a call transaction. The returned handle is an identifier for the
- * transaction and must be passed as a parameter to call_invoke() and
- * call_end(). A concrete rpc_caller may perform resource allocation during
- * this call. This will include a buffer for the request message parameters.
- * Returns a NULL handle on failure.
- */
-RPC_CALLER_EXPORTED rpc_call_handle rpc_caller_begin(struct rpc_caller *s,
-			uint8_t **req_buf, size_t req_len);
-
-/*
- * Invokes the operation identified by the opcode. This method blocks
- * until the operation completes. The status of the call is returned. An
- * additional endpoint specific status value is also returned. If a response
- * message was received, the concrete rpc_caller will have allocated a
- * buffer for the reponse. This buffer will hold valid data until the point when
- * call_end() is called for the transaction.
- */
-RPC_CALLER_EXPORTED rpc_status_t rpc_caller_invoke(struct rpc_caller *s, rpc_call_handle handle,
-			uint32_t opcode, rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len);
-
-/*
- * Ends the call transaction, allowing any resource associated with the
- * transaction to be freed.
- */
-RPC_CALLER_EXPORTED void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* RPC_CALLER_H */