Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: runtime check graph #165

Merged
merged 6 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions build/ten_runtime/feature/test.gni
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ template("ten_package_test_prepare_app") {
app_run_root_dir = "${test_case_root_dir}/${_target_name}"

install_app_dummy_output_file =
"${target_gen_dir}/install_app_dummy_output_file"
"${target_gen_dir}/${_target_name}/install_app_dummy_output_file"
halajohn marked this conversation as resolved.
Show resolved Hide resolved
install_app_depfile = "${target_gen_dir}/install_app_depfile"

action("${test_case_unique_target_name}_${_target_name}_install_app") {
Expand Down Expand Up @@ -168,7 +168,7 @@ template("ten_package_test_prepare_app") {
}

install_all_dummy_output_file =
"${target_gen_dir}/install_all_dummy_output_file"
"${target_gen_dir}/${_target_name}/install_all_dummy_output_file"

action("${test_case_unique_target_name}_${_target_name}_install_all") {
script = "//build/ten_runtime/feature/install_all.py"
Expand Down Expand Up @@ -290,7 +290,8 @@ template("ten_package_test_prepare_app") {
}

# App building phase.
build_app_dummy_output_file = "${target_gen_dir}/build_app_dummy_output_file"
build_app_dummy_output_file =
"${target_gen_dir}/${_target_name}/build_app_dummy_output_file"

action("${test_case_unique_target_name}_${_target_name}_build") {
script = "//build/ten_runtime/feature/build_pkg.py"
Expand Down Expand Up @@ -543,7 +544,7 @@ template("ten_package_standalone_pkg") {
pkg_root_dir = "${test_case_root_dir}/${_target_name}"

install_standalone_dummy_output_file =
"${target_gen_dir}/install_standalone_dummy_output_file"
"${target_gen_dir}/${_target_name}/install_standalone_dummy_output_file"
install_standalone_depfile = "${target_gen_dir}/install_standalone_depfile"

action("${test_case_unique_target_name}_${_target_name}_install_pkg") {
Expand Down Expand Up @@ -624,7 +625,8 @@ template("ten_package_standalone_pkg") {
]
}

install_all_dummy_output_file = "${target_gen_dir}/install_dummy_output_file"
install_all_dummy_output_file =
"${target_gen_dir}/${_target_name}/install_dummy_output_file"

# Install dependencies of the standalone package.
action("${test_case_unique_target_name}_${_target_name}_install") {
Expand Down Expand Up @@ -689,7 +691,8 @@ template("ten_package_standalone_pkg") {
}

# Build this standalone package.
build_pkg_dummy_output_file = "${target_gen_dir}/build_pkg_dummy_output_file"
build_pkg_dummy_output_file =
"${target_gen_dir}/${_target_name}/build_pkg_dummy_output_file"

action("${test_case_unique_target_name}_${_target_name}_build") {
script = "//build/ten_runtime/feature/build_pkg.py"
Expand Down
19 changes: 19 additions & 0 deletions core/include_internal/ten_runtime/app/graph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
#pragma once

#include "ten_runtime/ten_config.h"

#include <stdbool.h>

#include "ten_utils/lib/error.h"
#include "ten_utils/lib/json.h"

typedef struct ten_app_t ten_app_t;

TEN_RUNTIME_PRIVATE_API bool ten_app_check_start_graph_cmd_json(
ten_app_t *self, ten_json_t *start_graph_cmd_json, ten_error_t *err);
2 changes: 2 additions & 0 deletions core/src/ten_runtime/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ glob("app") {
"msg_interface",
"ten_env",
]

public_deps = [ "//core/src/ten_rust:ten_rust_binding" ]
}
51 changes: 51 additions & 0 deletions core/src/ten_runtime/app/graph.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
#include "include_internal/ten_runtime/app/graph.h"

#include "include_internal/ten_runtime/app/app.h"
#include "include_internal/ten_runtime/app/base_dir.h"
#include "include_internal/ten_runtime/common/constant_str.h"
#include "include_internal/ten_rust/ten_rust.h"
#include "ten_runtime/app/app.h"
#include "ten_utils/macro/memory.h"

bool ten_app_check_start_graph_cmd_json(ten_app_t *self,
ten_json_t *start_graph_cmd_json,
ten_error_t *err) {
TEN_ASSERT(self && ten_app_check_integrity(self, true), "Should not happen.");
TEN_ASSERT(start_graph_cmd_json, "Invalid argument.");

const char *base_dir = ten_app_get_base_dir(self);

// The pkg_info of extensions in the graph is read from the ten_packages
// directory under the base dir of app. If the base dir is not set, the app
// might be running in a thread, ex: the smoke testing. In this case, we can
// not retrieve the enough information to check the graph.
if (!base_dir || ten_c_string_is_empty(base_dir)) {
TEN_LOGD("The base dir of app [%s] is not set, skip checking graph.",
ten_app_get_uri(self));
return true;
}

bool free_json_string = false;
const char *graph_json_str = ten_json_to_string(
start_graph_cmd_json, TEN_STR_UNDERLINE_TEN, &free_json_string);

const char *err_msg = NULL;
bool rc = ten_rust_check_graph_for_app(base_dir, graph_json_str, &err_msg);

if (free_json_string) {
TEN_FREE(graph_json_str);
}

if (!rc) {
ten_error_set(err, TEN_ERRNO_INVALID_GRAPH, err_msg);
ten_rust_free_cstring(err_msg);
}

return rc;
}
46 changes: 46 additions & 0 deletions core/src/ten_runtime/app/msg_interface/start_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "include_internal/ten_runtime/app/app.h"
#include "include_internal/ten_runtime/app/close.h"
#include "include_internal/ten_runtime/app/engine_interface.h"
#include "include_internal/ten_runtime/app/graph.h"
#include "include_internal/ten_runtime/app/metadata.h"
#include "include_internal/ten_runtime/app/msg_interface/common.h"
#include "include_internal/ten_runtime/app/predefined_graph.h"
Expand All @@ -24,7 +25,12 @@
#include "include_internal/ten_runtime/msg/msg.h"
#include "include_internal/ten_runtime/protocol/protocol.h"
#include "ten_runtime/app/app.h"
#include "ten_runtime/common/status_code.h"
#include "ten_runtime/msg/cmd_result/cmd_result.h"
#include "ten_runtime/msg/msg.h"
#include "ten_utils/lib/json.h"
#include "ten_utils/lib/smart_ptr.h"
#include "ten_utils/log/log.h"
#include "ten_utils/macro/check.h"

static bool ten_app_fill_start_graph_cmd_extensions_info_from_predefined_graph(
Expand Down Expand Up @@ -53,6 +59,39 @@ static bool ten_app_fill_start_graph_cmd_extensions_info_from_predefined_graph(
return true;
}

bool ten_app_check_start_graph_cmd(ten_app_t *self,
ten_connection_t *connection,
ten_shared_ptr_t *cmd, ten_error_t *err) {
TEN_ASSERT(self && ten_app_check_integrity(self, true), "Invalid argument.");
TEN_ASSERT(cmd && ten_cmd_base_check_integrity(cmd), "Invalid argument.");
TEN_ASSERT(ten_msg_get_type(cmd) == TEN_MSG_TYPE_CMD_START_GRAPH,
"Invalid argument.");
TEN_ASSERT(err && ten_error_check_integrity(err), "Invalid argument.");

ten_json_t *cmd_json = ten_msg_to_json(cmd, err);
if (!cmd_json) {
TEN_ASSERT(0,
"Failed to convert start graph cmd to json, should not happen.");
return false;
}

bool rc = ten_app_check_start_graph_cmd_json(self, cmd_json, err);

ten_json_destroy(cmd_json);

if (!rc && connection) {
ten_shared_ptr_t *ret_cmd =
ten_cmd_result_create_from_cmd(TEN_STATUS_CODE_ERROR, cmd);
ten_msg_set_property(ret_cmd, TEN_STR_DETAIL,
ten_value_create_string(ten_error_errmsg(err)), NULL);
ten_msg_clear_and_set_dest_from_msg_src(ret_cmd, cmd);
ten_connection_send_msg(connection, ret_cmd);
ten_shared_ptr_destroy(ret_cmd);
}

return rc;
}

bool ten_app_handle_start_graph_cmd(ten_app_t *self,
ten_connection_t *connection,
ten_shared_ptr_t *cmd, ten_error_t *err) {
Expand All @@ -75,6 +114,13 @@ bool ten_app_handle_start_graph_cmd(ten_app_t *self,
ten_engine_t *engine =
ten_app_get_engine_based_on_dest_graph_id_from_msg(self, cmd);
if (engine == NULL) {
// The graph should be only checked once.
if (!ten_app_check_start_graph_cmd(self, connection, cmd, err)) {
TEN_LOGE("[%s] Failed to check start_graph cmd, %s",
ten_app_get_uri(self), ten_error_errmsg(err));
return false;
}

// The engine does not exist, create one, and send 'cmd' to the newly
// created engine.
engine = ten_app_create_engine(self, cmd);
Expand Down
9 changes: 9 additions & 0 deletions core/src/ten_runtime/app/predefined_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "include_internal/ten_runtime/app/app.h"
#include "include_internal/ten_runtime/app/engine_interface.h"
#include "include_internal/ten_runtime/app/graph.h"
#include "include_internal/ten_runtime/app/metadata.h"
#include "include_internal/ten_runtime/common/constant_str.h"
#include "include_internal/ten_runtime/engine/engine.h"
Expand All @@ -25,6 +26,7 @@
#include "ten_utils/lib/error.h"
#include "ten_utils/lib/json.h"
#include "ten_utils/lib/string.h"
#include "ten_utils/log/log.h"
#include "ten_utils/macro/check.h"
#include "ten_utils/value/value_get.h"

Expand Down Expand Up @@ -149,6 +151,13 @@ bool ten_app_start_predefined_graph(
return false;
}

if (!ten_app_check_start_graph_cmd_json(self, start_graph_cmd_json, err)) {
// TODO(Wei): The graph check does not support message conversion now, so we
// can not return false here. WIP: issues#160.
TEN_LOGW("[%s] The predefined graph is invalid, %s", ten_app_get_uri(self),
ten_error_errmsg(err));
}

ten_shared_ptr_t *start_graph_cmd =
ten_msg_create_from_json(start_graph_cmd_json, NULL);

Expand Down
2 changes: 1 addition & 1 deletion core/src/ten_runtime/app/ten_env/on_xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static void ten_app_on_configure_done_internal(ten_app_t *self) {
}

rc = ten_app_start_auto_start_predefined_graph(self, &err);
TEN_ASSERT(rc, "Should not happen.");
TEN_ASSERT(rc, "Should not happen, %s.", ten_error_errmsg(&err));

ten_error_deinit(&err);
}
Expand Down
15 changes: 12 additions & 3 deletions core/src/ten_runtime/engine/msg_interface/cmd_result.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "ten_utils/lib/smart_ptr.h"
#include "ten_utils/lib/string.h"
#include "ten_utils/macro/check.h"
#include "ten_utils/value/value_get.h"
#include "ten_utils/value/value_is.h"

static bool ten_engine_close_duplicated_remote_or_upgrade_it_to_normal(
Expand Down Expand Up @@ -156,9 +157,17 @@ static bool ten_engine_handle_cmd_result_for_cmd_start_graph(
"The engine should be started because of receiving a 'start_graph' "
"command.");

ten_engine_return_error_for_cmd_start_graph(
self, original_start_graph_cmd, "Failed to connect to %s",
ten_msg_get_src_app_uri(cmd_result));
ten_value_t *err_msg_value =
ten_msg_peek_property(cmd_result, TEN_STR_DETAIL, NULL);
if (err_msg_value) {
TEN_ASSERT(ten_value_is_string(err_msg_value), "Should not happen.");
ten_engine_return_error_for_cmd_start_graph(
self, original_start_graph_cmd, ten_value_peek_string(err_msg_value));
} else {
ten_engine_return_error_for_cmd_start_graph(
self, original_start_graph_cmd, "Failed to start engine in app [%s].",
ten_msg_get_src_app_uri(cmd_result));
}
} else {
TEN_ASSERT(0, "Should not happen.");
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/ten_runtime/metadata/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static bool ten_metadata_load_from_json_string(ten_value_t *metadata,
TEN_ASSERT(metadata && ten_value_check_integrity(metadata) && json_str,
"Should not happen.");

ten_json_t *json = ten_json_from_string(json_str, NULL);
ten_json_t *json = ten_json_from_string(json_str, err);
if (!json) {
return false;
}
Expand Down
38 changes: 38 additions & 0 deletions core/src/ten_rust/src/pkg_info/binding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Copyright © 2024 Agora
// This file is part of TEN Framework, an open source project.
// Licensed under the Apache License, Version 2.0, with certain conditions.
// Refer to the "LICENSE" file in the root directory for more information.
//
use std::ffi::{c_char, CStr, CString};

#[no_mangle]
pub extern "C" fn ten_rust_check_graph_for_app(
app_base_dir: *const c_char,
graph_json: *const c_char,
out_err_msg: *mut *const c_char,
) -> bool {
assert!(!app_base_dir.is_null(), "Invalid argument.");
assert!(!graph_json.is_null(), "Invalid argument.");

let c_app_base_dir = unsafe { CStr::from_ptr(app_base_dir) };
let c_graph_json = unsafe { CStr::from_ptr(graph_json) };

let rust_app_base_dir = c_app_base_dir.to_str().unwrap();
let rust_graph_json = c_graph_json.to_str().unwrap();

let ret = crate::pkg_info::ten_rust_check_graph_for_app(
rust_app_base_dir,
rust_graph_json,
);
if ret.is_err() {
let err_msg = ret.err().unwrap().to_string();
let c_err_msg =
CString::new(err_msg).expect("Failed to allocate memory.");
unsafe {
*out_err_msg = c_err_msg.into_raw();
}
return false;
}
true
}
Loading
Loading