Add direct and dummy RPC caller
Adds two types of RPC caller for testing purposes.
Change-Id: Icba23859ed9db5dc96832b10a985dc670830c4ab
Signed-off-by: Julian Hall <julian.hall@arm.com>
diff --git a/components/rpc/direct/component.cmake b/components/rpc/direct/component.cmake
new file mode 100644
index 0000000..614c429
--- /dev/null
+++ b/components/rpc/direct/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/direct_caller.c"
+ )
+
diff --git a/components/rpc/direct/direct_caller.c b/components/rpc/direct/direct_caller.c
new file mode 100644
index 0000000..001ee7c
--- /dev/null
+++ b/components/rpc/direct/direct_caller.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "direct_caller.h"
+#include <rpc/common/endpoint/call_ep.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include <stdlib.h>
+
+#define DIRECT_CALLER_DEFAULT_REQ_BUF_SIZE (4096)
+#define DIRECT_CALLER_DEFAULT_RESP_BUF_SIZE (4096)
+
+static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len);
+static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
+ int *opstatus, uint8_t **resp_buf, size_t *resp_len);
+static void call_end(void *context, rpc_call_handle handle);
+
+
+struct rpc_caller *direct_caller_init(struct direct_caller *s, struct call_ep *ep,
+ size_t req_buf_size, size_t resp_buf_size)
+{
+ struct rpc_caller *base = &s->rpc_caller;
+
+ base->context = s;
+ base->call_begin = call_begin;
+ base->call_invoke = call_invoke;
+ base->call_end = call_end;
+
+ s->call_ep = ep;
+ s->caller_id = 0;
+ s->is_call_transaction_in_progess = false;
+ s->req_len = 0;
+ s->req_buf_size = req_buf_size;
+ s->resp_buf_size = resp_buf_size;
+ s->req_buf = malloc(s->req_buf_size);
+ s->resp_buf = malloc(s->resp_buf_size);
+
+ if (!s->req_buf || !s->resp_buf) {
+
+ /* Buffer allocation failed */
+ base = NULL;
+ direct_caller_deinit(s);
+ }
+
+ return base;
+}
+
+struct rpc_caller *direct_caller_init_default(struct direct_caller *s, struct call_ep *ep)
+{
+ /* Initialise with default buffer sizes */
+ return direct_caller_init(s, ep,
+ DIRECT_CALLER_DEFAULT_REQ_BUF_SIZE,
+ DIRECT_CALLER_DEFAULT_RESP_BUF_SIZE);
+}
+
+void direct_caller_deinit(struct direct_caller *s)
+{
+ free(s->req_buf);
+ s->req_buf = NULL;
+ free(s->resp_buf);
+ s->resp_buf = NULL;
+}
+
+static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len)
+{
+ struct direct_caller *this_context = (struct direct_caller*)context;
+ rpc_call_handle handle = NULL;
+
+ if (!this_context->is_call_transaction_in_progess &&
+ (req_len <= this_context->req_buf_size)) {
+
+ this_context->is_call_transaction_in_progess = true;
+
+ if (req_buf){
+ *req_buf = this_context->req_buf;
+ this_context->req_len = req_len;
+ }
+
+ handle = this_context;
+ }
+
+ return handle;
+}
+
+static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
+ int *opstatus, uint8_t **resp_buf, size_t *resp_len)
+{
+ struct direct_caller *this_context = (struct direct_caller*)context;
+ rpc_status_t status = TS_RPC_ERROR_INVALID_TRANSACTION;
+
+ if ((handle == this_context) && this_context->is_call_transaction_in_progess) {
+
+ struct call_req req;
+
+ req.opcode = opcode;
+ req.caller_id = this_context->caller_id;
+ req.opstatus = 0;
+ req.req_buf = call_param_buf_init_full(this_context->req_buf,
+ this_context->req_buf_size, this_context->req_len);
+ req.resp_buf = call_param_buf_init_empty(this_context->resp_buf,
+ this_context->resp_buf_size);
+
+ status = call_ep_receive(this_context->call_ep, &req);
+
+ *resp_buf = this_context->resp_buf;
+ *resp_len = call_req_get_resp_buf(&req)->data_len;
+ *opstatus = call_req_get_opstatus(&req);
+ }
+
+ return status;
+}
+
+static void call_end(void *context, rpc_call_handle handle)
+{
+ struct direct_caller *this_context = (struct direct_caller*)context;
+
+ if ((handle == this_context) && this_context->is_call_transaction_in_progess) {
+
+ this_context->req_len = 0;
+ this_context->is_call_transaction_in_progess = false;
+ }
+}
diff --git a/components/rpc/direct/direct_caller.h b/components/rpc/direct/direct_caller.h
new file mode 100644
index 0000000..0f51845
--- /dev/null
+++ b/components/rpc/direct/direct_caller.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DIRECT_CALLER_H
+#define DIRECT_CALLER_H
+
+#include <rpc_caller.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct call_ep;
+
+/** An rpc_caller that calls methods associated with a specific endpoint
+ * directly. Used when the caller and endpoint are running in the same
+ * execution context.
+ **/
+struct direct_caller
+{
+ struct rpc_caller rpc_caller;
+ struct call_ep *call_ep;
+ uint32_t caller_id;
+ bool is_call_transaction_in_progess;
+ size_t req_len;
+ size_t req_buf_size;
+ size_t resp_buf_size;
+ uint8_t *req_buf;
+ uint8_t *resp_buf;
+};
+
+struct rpc_caller *direct_caller_init(struct direct_caller *s, struct call_ep *ep,
+ size_t req_buf_size, size_t resp_buf_size);
+
+struct rpc_caller *direct_caller_init_default(struct direct_caller *s, struct call_ep *ep);
+
+void direct_caller_deinit(struct direct_caller *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DIRECT_CALLER_H */
diff --git a/components/rpc/dummy/component.cmake b/components/rpc/dummy/component.cmake
new file mode 100644
index 0000000..19da9de
--- /dev/null
+++ b/components/rpc/dummy/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/dummy_caller.c"
+ )
diff --git a/components/rpc/dummy/dummy_caller.c b/components/rpc/dummy/dummy_caller.c
new file mode 100644
index 0000000..6d40b80
--- /dev/null
+++ b/components/rpc/dummy/dummy_caller.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "dummy_caller.h"
+#include <stdlib.h>
+
+static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len);
+static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
+ int *opstatus, uint8_t **resp_buf, size_t *resp_len);
+static void call_end(void *context, rpc_call_handle handle);
+
+
+struct rpc_caller *dummy_caller_init(struct dummy_caller *s,
+ rpc_status_t rpc_status, int opstatus)
+{
+ struct rpc_caller *base = &s->rpc_caller;
+
+ base->context = s;
+ base->call_begin = call_begin;
+ base->call_invoke = call_invoke;
+ base->call_end = call_end;
+
+ s->rpc_status = rpc_status;
+ s->opstatus = opstatus;
+ s->req_buf = NULL;
+
+ return base;
+}
+
+void dummy_caller_deinit(struct dummy_caller *s)
+{
+ free(s->req_buf);
+ s->req_buf = NULL;
+}
+
+static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len)
+{
+ struct dummy_caller *this_context = (struct dummy_caller*)context;
+ rpc_call_handle handle = this_context;
+
+ free(this_context->req_buf);
+ this_context->req_buf = malloc(req_len);
+ *req_buf = this_context->req_buf;
+
+ return handle;
+}
+
+static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
+ int *opstatus, uint8_t **resp_buf, size_t *resp_len)
+{
+ struct dummy_caller *this_context = (struct dummy_caller*)context;
+
+ free(this_context->req_buf);
+ this_context->req_buf = NULL;
+
+ *resp_buf = NULL;
+ *resp_len = 0;
+ *opstatus = this_context->opstatus;
+
+ return this_context->rpc_status;
+}
+
+static void call_end(void *context, rpc_call_handle handle)
+{
+ (void)context;
+ (void)handle;
+}
diff --git a/components/rpc/dummy/dummy_caller.h b/components/rpc/dummy/dummy_caller.h
new file mode 100644
index 0000000..215d293
--- /dev/null
+++ b/components/rpc/dummy/dummy_caller.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DUMMY_CALLER
+#define DUMMY_CALLER
+
+#include <rpc_caller.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * An rpc_caller that is used to return a suitable permanent status
+ * code if an attempt is made to invoke a remote method where an
+ * end-to-end rpc session has failed to be established. Intended
+ * to be used when a session with a real rpc endpoint cant't be
+ * established but a client doesn't wish to treat the condition
+ * as a fatal error.
+ */
+struct dummy_caller
+{
+ struct rpc_caller rpc_caller;
+ rpc_status_t rpc_status;
+ int opstatus;
+ uint8_t *req_buf;
+};
+
+struct rpc_caller *dummy_caller_init(struct dummy_caller *s,
+ rpc_status_t rpc_status, int opstatus);
+void dummy_caller_deinit(struct dummy_caller *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DUMMY_CALLER */