You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2022/01/26 18:55:37 UTC
[incubator-teaclave] branch master updated: Update Rust and C API for cancel_task, fix task status updating (#601)
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 9c6c94f Update Rust and C API for cancel_task, fix task status updating (#601)
9c6c94f is described below
commit 9c6c94f827097e10de044d1cdfedf0cab2a80a33
Author: Hongbo <12...@users.noreply.github.com>
AuthorDate: Wed Jan 26 10:55:30 2022 -0800
Update Rust and C API for cancel_task, fix task status updating (#601)
---
sdk/c/teaclave_client_sdk.h | 136 +++++++++++++++++++++++++--
sdk/payload/wasm/teaclave_context/Cargo.lock | 7 ++
sdk/rust/src/bindings.rs | 27 ++++++
sdk/rust/src/lib.rs | 86 +++++++++++++++--
services/management/enclave/src/service.rs | 9 +-
5 files changed, 250 insertions(+), 15 deletions(-)
diff --git a/sdk/c/teaclave_client_sdk.h b/sdk/c/teaclave_client_sdk.h
index 22a6d5b..affaa62 100644
--- a/sdk/c/teaclave_client_sdk.h
+++ b/sdk/c/teaclave_client_sdk.h
@@ -52,6 +52,10 @@ typedef struct FrontendClient FrontendClient;
*
* * The function returns an opaque pointer (handle) of the service. On error,
* the function returns NULL.
+ *
+ * # Safety
+ *
+ * `address`, `enclave_info_path`, `as_root_ca_cert_path` should be C string (null terminated).
*/
struct AuthenticationClient *teaclave_connect_authentication_service(const char *address,
const char *enclave_info_path,
@@ -61,12 +65,22 @@ struct AuthenticationClient *teaclave_connect_authentication_service(const char
* Close and free the authentication service handle, i.e., the
* `AuthenticaionClient` type opaque pointer. The function returns 0 for
* success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * This function is unsafe because improper use may lead to
+ * memory problems. For example, a double-free may occur if the
+ * function is called twice on the same raw pointer.
*/
int teaclave_close_authentication_service(struct AuthenticationClient *client);
/**
* Register a new user with `user_id` and `user_password`. The function returns
* 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * `user_id`, `user_password`, `role`, `attribute` should be C string (null terminated).
*/
int teaclave_user_register(struct AuthenticationClient *client,
const char *user_id,
@@ -79,6 +93,10 @@ int teaclave_user_register(struct AuthenticationClient *client,
* will be save in the `token` buffer, and length will be set in the
* `token_len` argument. The function returns 0 for success. On error, the
* function returns 1.
+ *
+ * # Safety
+ *
+ * `user_id`, `user_password` should be C string (null terminated), token and token_len should be consistent.
*/
int teaclave_user_login(struct AuthenticationClient *client,
const char *user_id,
@@ -104,6 +122,10 @@ int teaclave_user_login(struct AuthenticationClient *client,
*
* * The function returns an opaque pointer (handle) of the service. On error,
* the function returns NULL.
+ *
+ * # Safety
+ *
+ * All arguments should be C string (null terminated).
*/
struct FrontendClient *teaclave_connect_frontend_service(const char *address,
const char *enclave_info_path,
@@ -113,36 +135,68 @@ struct FrontendClient *teaclave_connect_frontend_service(const char *address,
* Close and free the frontend service handle, i.e., the `FrontendClient` type
* opaque pointer. The function returns 0 for success. On error, the function
* returns 1.
+ *
+ * # Safety
+ *
+ * This function is unsafe because improper use may lead to
+ * memory problems. For example, a double-free may occur if the
+ * function is called twice on the same raw pointer.
*/
int teaclave_close_frontend_service(struct FrontendClient *client);
/**
* Set user's credential with `user_id` and `user_token`. The function returns
* 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * `user_id` and `user_token` should be C string (null terminated).
*/
-int teaclave_frontend_set_credential(struct FrontendClient *client,
- const char *user_id,
- const char *user_token);
+int teaclave_authentication_set_credential(struct AuthenticationClient *client,
+ const char *user_id,
+ const char *user_token);
/**
* Set user's credential with `user_id` and `user_token`. The function returns
* 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * `user_id` and `user_token` should be C string (null terminated).
*/
-int teaclave_authentication_set_credential(struct AuthenticationClient *client,
- const char *user_id,
- const char *user_token);
+int teaclave_frontend_set_credential(struct FrontendClient *client,
+ const char *user_id,
+ const char *user_token);
/**
* Invoke task with `task_id`. The function returns 0 for success. On error,
* the function returns 1.
+ *
+ * # Safety
+ *
+ * `task_id` should be C string (null terminated).
*/
int teaclave_invoke_task(struct FrontendClient *client, const char *task_id);
/**
+ * Cancel task with `task_id`. The function returns 0 for success. On error,
+ * the function returns 1.
+ *
+ * # Safety
+ *
+ * `task_id` should be C string (null terminated).
+ */
+int teaclave_cancel_task(struct FrontendClient *client, const char *task_id);
+
+/**
* Get task result of `task_id`. The result will be save in the `task_result`
* buffer, and set corresponding `task_result_len` argument. Note that this is
* a blocking function and wait for the return of the task. The function
* returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_get_task_result(struct FrontendClient *client,
const char *task_id,
@@ -165,6 +219,10 @@ int teaclave_get_task_result(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_user_register_serialized(struct AuthenticationClient *client,
const char *serialized_request,
@@ -187,6 +245,10 @@ int teaclave_user_register_serialized(struct AuthenticationClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_user_login_serialized(struct AuthenticationClient *client,
const char *serialized_request,
@@ -209,6 +271,10 @@ int teaclave_user_login_serialized(struct AuthenticationClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_register_function_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -231,6 +297,10 @@ int teaclave_register_function_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_get_function_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -253,6 +323,10 @@ int teaclave_get_function_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_register_input_file_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -275,6 +349,10 @@ int teaclave_register_input_file_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_register_output_file_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -297,6 +375,10 @@ int teaclave_register_output_file_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_create_task_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -319,6 +401,10 @@ int teaclave_create_task_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_assign_data_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -341,6 +427,10 @@ int teaclave_assign_data_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_approve_task_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -363,6 +453,10 @@ int teaclave_approve_task_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_invoke_task_serialized(struct FrontendClient *client,
const char *serialized_request,
@@ -385,6 +479,36 @@ int teaclave_invoke_task_serialized(struct FrontendClient *client,
* # Return
*
* The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
+ */
+int teaclave_cancel_task_serialized(struct FrontendClient *client,
+ const char *serialized_request,
+ char *serialized_response,
+ size_t *serialized_response_len);
+
+/**
+ * Send JSON serialized request to the service with the `client` and
+ * get the serialized response.
+ *
+ * # Arguments
+ *
+ * * `client`: service client.
+ * * `serialized_request`; JSON serialized request
+ * * `serialized_response`: buffer to store the JSON serialized response.
+ * * `serialized_response_len`: length of the allocated
+ * `serialized_response`, will be set as the length of
+ * `serialized_response` when return successfully.
+ *
+ * # Return
+ *
+ * The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
*/
int teaclave_get_task_serialized(struct FrontendClient *client,
const char *serialized_request,
diff --git a/sdk/payload/wasm/teaclave_context/Cargo.lock b/sdk/payload/wasm/teaclave_context/Cargo.lock
new file mode 100644
index 0000000..f2bb38c
--- /dev/null
+++ b/sdk/payload/wasm/teaclave_context/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "teaclave_context"
+version = "0.2.0"
diff --git a/sdk/rust/src/bindings.rs b/sdk/rust/src/bindings.rs
index 4ca54ba..e7a7297 100644
--- a/sdk/rust/src/bindings.rs
+++ b/sdk/rust/src/bindings.rs
@@ -328,6 +328,28 @@ pub unsafe extern "C" fn teaclave_invoke_task(
}
}
+/// Cancel task with `task_id`. The function returns 0 for success. On error,
+/// the function returns 1.
+///
+/// # Safety
+///
+/// `task_id` should be C string (null terminated).
+#[no_mangle]
+pub unsafe extern "C" fn teaclave_cancel_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 = CStr::from_ptr(task_id).to_string_lossy().into_owned();
+ match client.invoke_task(&task_id) {
+ Ok(_) => 0,
+ Err(_) => 1,
+ }
+}
+
/// Get task result of `task_id`. The result will be save in the `task_result`
/// buffer, and set corresponding `task_result_len` argument. Note that this is
/// a blocking function and wait for the return of the task. The function
@@ -470,6 +492,11 @@ generate_function_serialized!(
);
generate_function_serialized!(
FrontendClient,
+ teaclave_cancel_task_serialized,
+ cancel_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 78d6c69..69c9f3a 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -34,10 +34,11 @@ pub use teaclave_proto::teaclave_authentication_service::{
pub use teaclave_proto::teaclave_frontend_service::GetFunctionResponse as Function;
pub use teaclave_proto::teaclave_frontend_service::{
ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
- CreateTaskRequest, CreateTaskResponse, GetFunctionRequest, GetFunctionResponse, GetTaskRequest,
- GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse, RegisterFunctionRequest,
- RegisterFunctionRequestBuilder, RegisterFunctionResponse, RegisterInputFileRequest,
- RegisterInputFileResponse, RegisterOutputFileRequest, RegisterOutputFileResponse,
+ CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
+ GetFunctionRequest, GetFunctionResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest,
+ InvokeTaskResponse, RegisterFunctionRequest, RegisterFunctionRequestBuilder,
+ RegisterFunctionResponse, RegisterInputFileRequest, RegisterInputFileResponse,
+ RegisterOutputFileRequest, RegisterOutputFileResponse,
};
pub use teaclave_types::{
EnclaveInfo, Executor, FileCrypto, FunctionInput, FunctionOutput, TaskResult,
@@ -498,13 +499,44 @@ impl FrontendClient {
loop {
let request = GetTaskRequest::new(task_id.try_into()?);
let response = self.get_task_with_request(request)?;
- if let TaskResult::Ok(task_outputs) = response.result {
- return Ok(task_outputs.return_value);
+ match response.result {
+ TaskResult::NotReady => {
+ std::thread::sleep(std::time::Duration::from_secs(1));
+ }
+ TaskResult::Ok(task_outputs) => {
+ return Ok(task_outputs.return_value);
+ }
+ TaskResult::Err(task_error) => {
+ return Err(anyhow::anyhow!(task_error.reason));
+ }
}
- let one_second = std::time::Duration::from_secs(1);
- std::thread::sleep(one_second);
}
}
+
+ pub fn cancel_task_with_request(
+ &mut self,
+ request: CancelTaskRequest,
+ ) -> Result<CancelTaskResponse> {
+ let response = self.api_client.cancel_task(request)?;
+
+ Ok(response)
+ }
+
+ pub fn cancel_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
+ let request: frontend_proto::CancelTaskRequest = serde_json::from_str(serialized_request)?;
+ let response: frontend_proto::CancelTaskResponse =
+ self.cancel_task_with_request(request.try_into()?)?.into();
+ let serialized_response = serde_json::to_string(&response)?;
+
+ Ok(serialized_response)
+ }
+
+ pub fn cancel_task(&mut self, task_id: &str) -> Result<()> {
+ let request = CancelTaskRequest::new(task_id.try_into()?);
+ let _ = self.cancel_task_with_request(request)?;
+
+ Ok(())
+ }
}
#[cfg(test)]
@@ -741,4 +773,42 @@ mod tests {
client.assign_data(&task_id, None, Some(outputs)).unwrap();
client.approve_task(&task_id).unwrap();
}
+
+ #[test]
+ fn test_cancel_task() {
+ let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
+ let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
+ let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
+ let mut client =
+ AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
+ .unwrap();
+ let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
+ client.set_credential(ADMIN_ID, &token);
+ let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
+ let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
+
+ let mut client =
+ FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
+ client.set_credential(USER_ID, &token);
+ let function_id = "function-00000000-0000-0000-0000-000000000002";
+ let function_arguments = hashmap!("arg1" => "arg1_value");
+ let outputs_ownership = hashmap!("output" => vec![USER_ID.to_string()]);
+ let task_id = client
+ .create_task(
+ &function_id,
+ Some(function_arguments),
+ "mesapy",
+ None,
+ Some(outputs_ownership),
+ )
+ .unwrap();
+
+ print!("SDK DEBUG: task created");
+
+ let result = client.cancel_task(&task_id);
+ print!("SDK DEBUG: canceled, {:?}", result);
+
+ let task = client.get_task_result(&task_id);
+ assert!(task.is_err());
+ }
}
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index 0293450..294abe2 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -662,17 +662,24 @@ impl TeaclaveManagement for TeaclaveManagementService {
self.enqueue_to_db(CANCEL_QUEUE_KEY.as_bytes(), &ts)?;
}
_ => {
+ // early cancelation
// race will not affect correctness/privacy
- let task: Task<Cancel> = ts.try_into().map_err(|e| {
+ let mut task: Task<Cancel> = ts.try_into().map_err(|e| {
log::warn!("Cancel state error: {:?}", e);
TeaclaveManagementServiceError::PermissionDenied
})?;
log::debug!("Canceled Task: {:?}", task);
+ task.update_result(TaskResult::Err(TaskFailure {
+ reason: "Task canceled".to_string(),
+ }))
+ .map_err(|_| TeaclaveManagementServiceError::PermissionDenied)?;
let ts: TaskState = task.into();
self.write_to_db(&ts)
.map_err(|_| TeaclaveManagementServiceError::StorageError)?;
+
+ log::warn!("Canceled Task: writtenback");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org