This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/master by this push:
new f0fc059 Add C client SDK and examples (#470)
f0fc059 is described below
commit f0fc0593b395ef4ce010a2e39dc05f6a43e06197
Author: Mingshen Sun <[email protected]>
AuthorDate: Tue Jan 26 10:39:50 2021 -0800
Add C client SDK and examples (#470)
---
cmake/scripts/test.sh | 4 +
examples/c/.clang-format | 2 +
examples/c/Makefile | 38 +++++
examples/c/builtin_echo.c | 193 ++++++++++++++++++++++++
sdk/c/Makefile | 22 +++
sdk/c/cbindgen.toml | 32 ++++
sdk/c/teaclave_client_sdk.h | 123 ++++++++++++++++
sdk/rust/Cargo.toml | 6 +
sdk/rust/src/bindings.rs | 350 ++++++++++++++++++++++++++++++++++++++++++++
sdk/rust/src/lib.rs | 112 ++++++++++++++
10 files changed, 882 insertions(+)
diff --git a/cmake/scripts/test.sh b/cmake/scripts/test.sh
index 6702253..6ecf1e3 100755
--- a/cmake/scripts/test.sh
+++ b/cmake/scripts/test.sh
@@ -232,6 +232,10 @@ run_examples() {
python3 builtin_password_check.py
popd
+ pushd ${TEACLAVE_PROJECT_ROOT}/examples/c
+ make run
+ popd
+
# kill all background services
cleanup
}
diff --git a/examples/c/.clang-format b/examples/c/.clang-format
new file mode 100644
index 0000000..80d3293
--- /dev/null
+++ b/examples/c/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
diff --git a/examples/c/Makefile b/examples/c/Makefile
new file mode 100644
index 0000000..2cc0b68
--- /dev/null
+++ b/examples/c/Makefile
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+all: builtin_echo
+
+CFLAGS := -I../../sdk/c -Ltarget/debug/ -lteaclave_client_sdk
+
+ifeq ($(DCAP),ON)
+ CFLAGS += -DDCAP
+endif
+
+target/debug/libteaclave_client_sdk.so:
+ RUSTFLAGS="$(RUSTFLAGS)" cargo build --manifest-path
../../sdk/rust/Cargo.toml --target-dir target
+
+builtin_echo: builtin_echo.c target/debug/libteaclave_client_sdk.so
+ gcc -o $@ builtin_echo.c $(CFLAGS)
+
+run: builtin_echo
+ LD_LIBRARY_PATH=target/debug ./builtin_echo
+
+clean:
+ @rm -rf target
+ @rm builtin_echo
diff --git a/examples/c/builtin_echo.c b/examples/c/builtin_echo.c
new file mode 100644
index 0000000..acd6f1c
--- /dev/null
+++ b/examples/c/builtin_echo.c
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+#include "teaclave_client_sdk.h"
+#include <stdio.h>
+#include <string.h>
+
+#define BUFFER_SIZE 4086
+
+const char *authentication_service_address = "localhost:7776";
+const char *frontend_service_address = "localhost:7777";
+const char *enclave_info_path = "../../release/services/enclave_info.toml";
+#ifdef DCAP
+const char *as_root_ca_cert_path = "../../keys/dcap_root_ca_cert.pem";
+#else
+const char *as_root_ca_cert_path = "../../keys/ias_root_ca_cert.pem";
+#endif
+const char *user_id = "test_id";
+const char *user_password = "test_password";
+
+const char *register_function_request_serialized =
+ "{"
+ " \"request\": \"register_function\","
+ " \"name\": \"builtin-echo\","
+ " \"description\": \"Native Echo Function\","
+ " \"executor_type\": \"builtin\","
+ " \"public\": true,"
+ " \"payload\": [],"
+ " \"arguments\": ["
+ " \"message\""
+ " ],"
+ " \"inputs\": [],"
+ " \"outputs\": []"
+ "}";
+
+const char *create_task_request_serialized =
+ "{"
+ " \"request\": \"create_task\","
+ " \"function_id\": \"%s\","
+ " \"function_arguments\": \"{\\\"message\\\": \\\"Hello, "
+ "Teaclave!\\\"}\","
+ " \"executor\": \"builtin\","
+ " \"inputs_ownership\": [],"
+ " \"outputs_ownership\": []"
+ "}";
+
+int login(char *token, size_t *token_len) {
+ int ret = 0;
+
+ AuthenticationClient *authentication_client =
+ teaclave_connect_authentication_service(authentication_service_address,
+ enclave_info_path,
+ as_root_ca_cert_path);
+ if (authentication_client == NULL) {
+ fprintf(stderr,
+ "[-] Failed to connect to the authentication service.\n");
+ ret = 1;
+ goto bail;
+ }
+
+ ret = teaclave_user_register(authentication_client, user_id,
user_password);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to register user.\n");
+ fprintf(stderr, "[-] Maybe `%s' already exists. Continue. \n",
user_id);
+ }
+
+ ret = teaclave_user_login(authentication_client, user_id, user_password,
+ token, token_len);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to login.\n");
+ goto bail;
+ }
+ printf("[+] token: %s\n", token);
+
+bail:
+ if (authentication_client) {
+ ret = teaclave_close_authentication_service(authentication_client);
+ if (ret != 0) {
+ fprintf(stderr,
+ "[-] Failed to close the authentication service
client.\n");
+ }
+ }
+
+ return ret;
+}
+
+int main() {
+ int ret = 0;
+
+ char token[BUFFER_SIZE] = {0};
+ char serialized_response[BUFFER_SIZE] = {0};
+ char function_id[BUFFER_SIZE] = {0};
+ char serialized_request[BUFFER_SIZE] = {0};
+ char task_result[BUFFER_SIZE] = {0};
+ char task_id[BUFFER_SIZE] = {0};
+
+ /* Login. */
+ size_t token_len = BUFFER_SIZE;
+ ret = login(token, &token_len);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to login.\n");
+ goto bail;
+ }
+
+ /* Connect to the frontend serivice. */
+ FrontendClient *frontend_client = teaclave_connect_frontend_service(
+ frontend_service_address, enclave_info_path, as_root_ca_cert_path);
+ if (frontend_client == NULL) {
+ fprintf(stderr, "[-] Failed to connect to the frontend service.\n");
+ ret = 1;
+ goto bail;
+ }
+
+ /* Set user id and token. */
+ ret = teaclave_set_credential(frontend_client, user_id, token);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to set credential.\n");
+ goto bail;
+ }
+
+ /* Register function. */
+ size_t serialized_response_len = BUFFER_SIZE;
+ ret = teaclave_register_function_serialized(
+ frontend_client, register_function_request_serialized,
+ serialized_response, &serialized_response_len);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to register the function.\n");
+ goto bail;
+ }
+
+ sscanf(serialized_response, "{\"function_id\":\"%45s", function_id);
+ printf("[+] function_id: %s\n", function_id);
+
+ /* Create task. */
+ snprintf(serialized_request, BUFFER_SIZE, create_task_request_serialized,
+ function_id);
+
+ memset(serialized_response, 0, BUFFER_SIZE);
+ ret = teaclave_create_task_serialized(frontend_client, serialized_request,
+ serialized_response,
+ &serialized_response_len);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to create a task.\n");
+ goto bail;
+ }
+
+ sscanf(serialized_response, "{\"task_id\":\"%41s", task_id);
+ printf("[+] task_id: %s\n", task_id);
+
+ /* Invoke task. */
+ ret = teaclave_invoke_task(frontend_client, task_id);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to invoke the task.\n");
+ goto bail;
+ }
+
+ /* Get task result. */
+ size_t task_result_len = BUFFER_SIZE;
+ ret = teaclave_get_task_result(frontend_client, task_id, task_result,
+ &task_result_len);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to get the task result.\n");
+ goto bail;
+ }
+
+ printf("[+] Task result in string: %s\n", task_result);
+
+bail:
+ ret = teaclave_close_frontend_service(frontend_client);
+ if (ret != 0) {
+ fprintf(stderr, "[-] Failed to close the frontend service client.\n");
+ }
+
+ return ret;
+}
diff --git a/sdk/c/Makefile b/sdk/c/Makefile
new file mode 100644
index 0000000..533ddb7
--- /dev/null
+++ b/sdk/c/Makefile
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+RUST_CLIENT_SDK_SOURCE:=$(wildcard ../rust/src/*.rs)
+
+all: $(RUST_CLIENT_SDK_SOURCE)
+ rustup run nightly cbindgen ../rust -c cbindgen.toml -o
teaclave_client_sdk.h
diff --git a/sdk/c/cbindgen.toml b/sdk/c/cbindgen.toml
new file mode 100644
index 0000000..dfbe67a
--- /dev/null
+++ b/sdk/c/cbindgen.toml
@@ -0,0 +1,32 @@
+language = "C"
+
+header = """
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+"""
+
+autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated
using cbindgen.
+ * To generate this file:
+ * 1. Get the latest cbindgen using `cargo install --force cbindgen`
+ * 2. Run `rustup run nightly cbindgen ../rust -c cbindgen.toml -o
+ teaclave_client_sdk.h` or `make`.
+ */"""
+
+[parse.expand]
+crates = ["teaclave-client-sdk"]
diff --git a/sdk/c/teaclave_client_sdk.h b/sdk/c/teaclave_client_sdk.h
new file mode 100644
index 0000000..96f40dd
--- /dev/null
+++ b/sdk/c/teaclave_client_sdk.h
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
+ * To generate this file:
+ * 1. Get the latest cbindgen using `cargo install --force cbindgen`
+ * 2. Run `rustup run nightly cbindgen ../rust -c cbindgen.toml -o
+ teaclave_client_sdk.h` or `make`.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef struct AuthenticationClient AuthenticationClient;
+
+typedef struct FrontendClient FrontendClient;
+
+struct AuthenticationClient *teaclave_connect_authentication_service(const
char *address,
+ const
char *enclave_info_path,
+ const
char *as_root_ca_cert_path);
+
+int teaclave_close_authentication_service(struct AuthenticationClient *client);
+
+int teaclave_user_register(struct AuthenticationClient *client,
+ const char *user_id,
+ const char *user_password);
+
+int teaclave_user_login(struct AuthenticationClient *client,
+ const char *user_id,
+ const char *user_password,
+ char *token,
+ size_t *token_len);
+
+struct FrontendClient *teaclave_connect_frontend_service(const char *address,
+ const char
*enclave_info_path,
+ const char
*as_root_ca_cert_path);
+
+int teaclave_close_frontend_service(struct FrontendClient *client);
+
+int teaclave_set_credential(struct FrontendClient *client,
+ const char *user_id,
+ const char *user_token);
+
+int teaclave_invoke_task(struct FrontendClient *client, const char *task_id);
+
+int teaclave_get_task_result(struct FrontendClient *client,
+ const char *task_id,
+ char *task_result,
+ size_t *task_result_len);
+
+int teaclave_user_register_serialized(struct AuthenticationClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_user_login_serialized(struct AuthenticationClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_register_function_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_get_function_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_register_input_file_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_register_output_file_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_create_task_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_assign_data_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_approve_task_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_invoke_task_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+int teaclave_get_task_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml
index 4264c17..a195685 100644
--- a/sdk/rust/Cargo.toml
+++ b/sdk/rust/Cargo.toml
@@ -6,6 +6,9 @@ description = "Teaclave Rust Client SDK"
license = "Apache-2.0"
edition = "2018"
+[lib]
+crate-type = ["lib", "cdylib", "staticlib"]
+
[dependencies]
teaclave_types = { path = "../../types", features = ["app"] }
teaclave_attestation = { path = "../../attestation" }
@@ -13,4 +16,7 @@ teaclave_rpc = { path = "../../rpc" }
teaclave_proto = { path = "../../services/proto" }
anyhow = { version = "1.0.26" }
url = { version = "2.1.1" }
+serde_json = { version = "1.0.39" }
+serde = { version = "1.0.92" }
pem = "0.7.0"
+libc = "0.2.68"
diff --git a/sdk/rust/src/bindings.rs b/sdk/rust/src/bindings.rs
new file mode 100644
index 0000000..41386af
--- /dev/null
+++ b/sdk/rust/src/bindings.rs
@@ -0,0 +1,350 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use libc::size_t;
+use std::ffi::CStr;
+use std::ffi::CString;
+use std::fs;
+use std::os::raw::c_char;
+use std::os::raw::c_int;
+use std::ptr;
+
+use crate::{
+ AuthenticationClient, AuthenticationService, EnclaveInfo, FrontendClient,
FrontendService,
+};
+
+macro_rules! unwrap_or_return_null {
+ ( $e:expr ) => {
+ match $e {
+ Ok(x) => x,
+ Err(_) => return ptr::null_mut(),
+ }
+ };
+}
+
+macro_rules! unwrap_or_return_one {
+ ( $e:expr ) => {
+ match $e {
+ Ok(x) => x,
+ Err(_) => return 1,
+ }
+ };
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_connect_authentication_service(
+ address: *const c_char,
+ enclave_info_path: *const c_char,
+ as_root_ca_cert_path: *const c_char,
+) -> *mut AuthenticationClient {
+ if address.is_null() || enclave_info_path.is_null() ||
as_root_ca_cert_path.is_null() {
+ return ptr::null_mut();
+ }
+
+ let address = unsafe {
CStr::from_ptr(address).to_string_lossy().into_owned() };
+ let enclave_info_path = unsafe {
+ CStr::from_ptr(enclave_info_path)
+ .to_string_lossy()
+ .into_owned()
+ };
+ let as_root_ca_cert_path = unsafe {
+ CStr::from_ptr(as_root_ca_cert_path)
+ .to_string_lossy()
+ .into_owned()
+ };
+ let enclave_info =
unwrap_or_return_null!(EnclaveInfo::from_file(enclave_info_path));
+ let bytes = unwrap_or_return_null!(fs::read(as_root_ca_cert_path));
+ let as_root_ca_cert = unwrap_or_return_null!(pem::parse(bytes)).contents;
+ let client = unwrap_or_return_null!(AuthenticationService::connect(
+ &address,
+ &enclave_info,
+ &as_root_ca_cert
+ ));
+
+ Box::into_raw(Box::new(client))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn teaclave_close_authentication_service(
+ client: *mut AuthenticationClient,
+) -> c_int {
+ if client.is_null() {
+ return 1;
+ }
+
+ Box::from_raw(client);
+
+ 0
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_user_register(
+ client: &mut AuthenticationClient,
+ user_id: *const c_char,
+ user_password: *const c_char,
+) -> c_int {
+ if (client as *mut AuthenticationClient).is_null()
+ || user_id.is_null()
+ || user_password.is_null()
+ {
+ return 1;
+ }
+
+ let user_id = unsafe {
CStr::from_ptr(user_id).to_string_lossy().into_owned() };
+ let user_password = unsafe {
CStr::from_ptr(user_password).to_string_lossy().into_owned() };
+ unwrap_or_return_one!(client.user_register(&user_id, &user_password));
+
+ 0
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_user_login(
+ client: &mut AuthenticationClient,
+ user_id: *const c_char,
+ user_password: *const c_char,
+ token: *mut c_char,
+ token_len: *mut size_t,
+) -> c_int {
+ if (client as *mut AuthenticationClient).is_null()
+ || user_id.is_null()
+ || user_password.is_null()
+ || token.is_null()
+ || token_len.is_null()
+ {
+ return 1;
+ }
+
+ let user_id = unsafe {
CStr::from_ptr(user_id).to_string_lossy().into_owned() };
+ let user_password = unsafe {
CStr::from_ptr(user_password).to_string_lossy().into_owned() };
+
+ let token_string = unwrap_or_return_one!(client.user_login(&user_id,
&user_password));
+ let token_c_string = unwrap_or_return_one!(CString::new(token_string));
+ let bytes = token_c_string.as_bytes_with_nul();
+
+ unsafe {
+ if *token_len < bytes.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(bytes.as_ptr(), token as _, bytes.len());
+ *token_len = bytes.len();
+ }
+ }
+
+ 0
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_connect_frontend_service(
+ address: *const c_char,
+ enclave_info_path: *const c_char,
+ as_root_ca_cert_path: *const c_char,
+) -> *mut FrontendClient {
+ if address.is_null() || enclave_info_path.is_null() ||
as_root_ca_cert_path.is_null() {
+ return ptr::null_mut();
+ }
+
+ let address = unsafe {
CStr::from_ptr(address).to_string_lossy().into_owned() };
+ let enclave_info_path = unsafe {
+ CStr::from_ptr(enclave_info_path)
+ .to_string_lossy()
+ .into_owned()
+ };
+ let as_root_ca_cert_path = unsafe {
+ CStr::from_ptr(as_root_ca_cert_path)
+ .to_string_lossy()
+ .into_owned()
+ };
+ let enclave_info =
unwrap_or_return_null!(EnclaveInfo::from_file(enclave_info_path));
+ let bytes = unwrap_or_return_null!(fs::read(as_root_ca_cert_path));
+ let as_root_ca_cert = unwrap_or_return_null!(pem::parse(bytes)).contents;
+ let client = unwrap_or_return_null!(FrontendService::connect(
+ &address,
+ &enclave_info,
+ &as_root_ca_cert
+ ));
+
+ Box::into_raw(Box::new(client))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn teaclave_close_frontend_service(client: *mut
FrontendClient) -> c_int {
+ if client.is_null() {
+ return 1;
+ }
+
+ Box::from_raw(client);
+
+ 0
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_set_credential(
+ client: &mut FrontendClient,
+ user_id: *const c_char,
+ user_token: *const c_char,
+) -> c_int {
+ if (client as *mut FrontendClient).is_null() || user_id.is_null() ||
user_token.is_null() {
+ return 1;
+ }
+
+ let user_id = unsafe {
CStr::from_ptr(user_id).to_string_lossy().into_owned() };
+ let user_token = unsafe {
CStr::from_ptr(user_token).to_string_lossy().into_owned() };
+ client.set_credential(&user_id, &user_token);
+
+ 0
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_invoke_task(
+ client: &mut FrontendClient,
+ task_id: *const c_char,
+) -> c_int {
+ if (client as *mut FrontendClient).is_null() || task_id.is_null() {
+ return 1;
+ }
+
+ let task_id = unsafe {
CStr::from_ptr(task_id).to_string_lossy().into_owned() };
+ match client.invoke_task(&task_id) {
+ Ok(_) => 0,
+ Err(_) => 1,
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn teaclave_get_task_result(
+ client: &mut FrontendClient,
+ task_id: *const c_char,
+ task_result: *mut c_char,
+ task_result_len: *mut size_t,
+) -> c_int {
+ if (client as *mut FrontendClient).is_null() || task_id.is_null() {
+ return 1;
+ }
+
+ let task_id = unsafe {
CStr::from_ptr(task_id).to_string_lossy().into_owned() };
+ match client.get_task_result(&task_id) {
+ Ok(result) => {
+ unsafe {
+ if *task_result_len < result.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(result.as_ptr(), task_result as
_, result.len());
+ *task_result_len = result.len();
+ }
+ }
+ 0
+ }
+ Err(_) => 1,
+ }
+}
+
+macro_rules! generate_function_serialized {
+ ( $client_type:ident, $c_function_name:ident, $rust_function_name:ident)
=> {
+ #[no_mangle]
+ pub extern "C" fn $c_function_name(
+ client: &mut $client_type,
+ serialized_request: *const c_char,
+ serialized_response: *mut c_char,
+ serialized_response_len: *mut size_t,
+ ) -> c_int {
+ if (client as *mut $client_type).is_null()
+ || serialized_request.is_null()
+ || serialized_response.is_null()
+ || serialized_response_len.is_null()
+ {
+ return 1;
+ }
+
+ let serialized_request = unsafe {
+ CStr::from_ptr(serialized_request)
+ .to_string_lossy()
+ .into_owned()
+ };
+ let function_id_string =
+
unwrap_or_return_one!(client.$rust_function_name(&serialized_request));
+ let function_id_c_string =
unwrap_or_return_one!(CString::new(function_id_string));
+ let bytes = function_id_c_string.as_bytes_with_nul();
+
+ unsafe {
+ if *serialized_response_len < bytes.len() {
+ return 1;
+ } else {
+ ptr::copy_nonoverlapping(bytes.as_ptr(),
serialized_response as _, bytes.len());
+ *serialized_response_len = bytes.len();
+ }
+ }
+
+ 0
+ }
+ };
+}
+
+generate_function_serialized!(
+ AuthenticationClient,
+ teaclave_user_register_serialized,
+ user_register_serialized
+);
+generate_function_serialized!(
+ AuthenticationClient,
+ teaclave_user_login_serialized,
+ user_login_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_register_function_serialized,
+ register_function_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_get_function_serialized,
+ get_function_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_register_input_file_serialized,
+ register_input_file_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_register_output_file_serialized,
+ register_output_file_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_create_task_serialized,
+ create_task_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_assign_data_serialized,
+ assign_data_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_approve_task_serialized,
+ approve_task_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_invoke_task_serialized,
+ invoke_task_serialized
+);
+generate_function_serialized!(
+ FrontendClient,
+ teaclave_get_task_serialized,
+ get_task_serialized
+);
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
index 7357d19..633b9ce 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -20,7 +20,9 @@ use std::collections::HashMap;
use std::convert::TryInto;
use teaclave_attestation::verifier;
use
teaclave_proto::teaclave_authentication_service::TeaclaveAuthenticationApiClient;
+use teaclave_proto::teaclave_authentication_service_proto as
authentication_proto;
use teaclave_proto::teaclave_frontend_service::TeaclaveFrontendClient;
+use teaclave_proto::teaclave_frontend_service_proto as frontend_proto;
use teaclave_rpc::config::SgxTrustedTlsClientConfig;
use teaclave_rpc::endpoint::Endpoint;
use teaclave_types::FileAuthTag;
@@ -41,6 +43,8 @@ pub use teaclave_types::{
EnclaveInfo, Executor, FileCrypto, FunctionInput, FunctionOutput,
TaskResult,
};
+pub mod bindings;
+
pub struct AuthenticationClient {
api_client: TeaclaveAuthenticationApiClient,
}
@@ -61,6 +65,16 @@ impl AuthenticationClient {
Ok(response)
}
+ pub fn user_register_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: authentication_proto::UserRegisterRequest =
+ serde_json::from_str(serialized_request)?;
+ let response: authentication_proto::UserRegisterResponse =
+ self.user_register_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn user_register(&mut self, user_id: &str, user_password: &str) ->
Result<()> {
let request = UserRegisterRequest::new(user_id, user_password);
let _response = self.user_register_with_request(request)?;
@@ -77,6 +91,16 @@ impl AuthenticationClient {
Ok(response)
}
+ pub fn user_login_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: authentication_proto::UserLoginRequest =
+ serde_json::from_str(serialized_request)?;
+ let response: authentication_proto::UserLoginResponse =
+ self.user_login_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn user_login(&mut self, user_id: &str, user_password: &str) ->
Result<String> {
let request = UserLoginRequest::new(user_id, user_password);
let response = self.user_login_with_request(request)?;
@@ -106,6 +130,7 @@ impl AuthenticationService {
}
}
+#[repr(C)]
pub struct FrontendService;
impl FrontendService {
@@ -145,6 +170,17 @@ impl FrontendClient {
self.api_client.set_metadata(metadata);
}
+ pub fn register_function_serialized(&mut self, serialized_request: &str)
-> Result<String> {
+ let request: frontend_proto::RegisterFunctionRequest =
+ serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::RegisterFunctionResponse = self
+ .register_function_with_request(request.try_into()?)?
+ .into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn register_function_with_request(
&mut self,
request: RegisterFunctionRequest,
@@ -195,6 +231,15 @@ impl FrontendClient {
Ok(response)
}
+ pub fn get_function_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::GetFunctionRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::GetFunctionResponse =
+ self.get_function_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn get_function(&mut self, function_id: &str) -> Result<Function> {
let function_id = function_id.try_into()?;
let request = GetFunctionRequest::new(function_id);
@@ -212,6 +257,17 @@ impl FrontendClient {
Ok(response)
}
+ pub fn register_input_file_serialized(&mut self, serialized_request: &str)
-> Result<String> {
+ let request: frontend_proto::RegisterInputFileRequest =
+ serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::RegisterInputFileResponse = self
+ .register_input_file_with_request(request.try_into()?)?
+ .into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn register_input_file(
&mut self,
url: &str,
@@ -235,6 +291,17 @@ impl FrontendClient {
Ok(response)
}
+ pub fn register_output_file_serialized(&mut self, serialized_request:
&str) -> Result<String> {
+ let request: frontend_proto::RegisterOutputFileRequest =
+ serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::RegisterOutputFileResponse = self
+ .register_output_file_with_request(request.try_into()?)?
+ .into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn register_output_file(&mut self, url: &str, file_crypto: FileCrypto)
-> Result<String> {
let url = Url::parse(url)?;
let request = RegisterOutputFileRequest::new(url, file_crypto);
@@ -243,6 +310,15 @@ impl FrontendClient {
Ok(response.data_id.to_string())
}
+ pub fn create_task_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::CreateTaskRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::CreateTaskResponse =
+ self.create_task_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn create_task_with_request(
&mut self,
request: CreateTaskRequest,
@@ -302,6 +378,15 @@ impl FrontendClient {
Ok(response)
}
+ pub fn assign_data_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::AssignDataRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::AssignDataResponse =
+ self.assign_data_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn assign_data(
&mut self,
task_id: &str,
@@ -343,6 +428,15 @@ impl FrontendClient {
Ok(())
}
+ pub fn approve_task_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::ApproveTaskRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::ApproveTaskResponse =
+ self.approve_task_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn invoke_task_with_request(
&mut self,
request: InvokeTaskRequest,
@@ -352,6 +446,15 @@ impl FrontendClient {
Ok(response)
}
+ pub fn invoke_task_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::InvokeTaskRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::InvokeTaskResponse =
+ self.invoke_task_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn invoke_task(&mut self, task_id: &str) -> Result<()> {
let request = InvokeTaskRequest::new(task_id.try_into()?);
let _ = self.invoke_task_with_request(request)?;
@@ -365,6 +468,15 @@ impl FrontendClient {
Ok(response)
}
+ pub fn get_task_serialized(&mut self, serialized_request: &str) ->
Result<String> {
+ let request: frontend_proto::GetTaskRequest =
serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::GetTaskResponse =
+ self.get_task_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
pub fn get_task_result(&mut self, task_id: &str) -> Result<Vec<u8>> {
loop {
let request = GetTaskRequest::new(task_id.try_into()?);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]