diff --git a/src/cores/handlers/datamgr/route.rs b/src/cores/handlers/datamgr/route.rs index 02e617c9a3e3e2456427628c77c4670efda82508..311fbb6122e6c2faaa8f55a60dbddea46be92ea6 100644 --- a/src/cores/handlers/datamgr/route.rs +++ b/src/cores/handlers/datamgr/route.rs @@ -16,6 +16,7 @@ use std::time::Duration; use tokio::sync::oneshot; use tokio::time::Instant; use uuid::Uuid; +use crate::cores::handlers::datamgr::datamgr_api::{Device, DeviceList, FreeDevice, FreeDeviceList, FreeStrategy, FreeStrategyList, FreeString, Strategy, StrategyList}; pub static mut DATA_PLUGIN_MANAGER: *mut std::os::raw::c_void = null_mut(); @@ -944,7 +945,7 @@ pub async fn subscribe_handler( } } - Ok(serde_json::json!("Subscribe Ok")) + Ok(json!("Subscribe Ok")) } // 获取消息处理函数 @@ -1052,7 +1053,7 @@ pub async fn message_handler( } let remaining = timeout_duration - elapsed; - let (mut new_system, timeout_result) = + let (new_system, timeout_result) = condvar.wait_timeout(queue_system, remaining).unwrap(); queue_system = new_system; @@ -1206,7 +1207,11 @@ pub struct CallbackContext { static RESPONSE_MAP: Lazy>>>> = Lazy::new(|| Arc::new(Mutex::new(HashMap::new()))); -pub async fn request_handler(_: Arc, _request_context: RequestContext, server_request: ServerRequest) -> ServerResponse { +pub async fn request_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest +) -> ServerResponse { let bad_request = |body_str| { ServerRawResponse::bad_request() .body(Vec::from(body_str)) @@ -1301,7 +1306,11 @@ pub async fn request_handler(_: Arc, _request_context: RequestContext, } -pub async fn reply_handler(_: Arc, _request_context: RequestContext, server_request: ServerRequest) -> ServerResponse { +pub async fn reply_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest +) -> ServerResponse { let headers = server_request.headers; let body = server_request.body.as_ref().unwrap().as_slice(); @@ -1344,3 +1353,935 @@ pub async fn reply_handler(_: Arc, _request_context: RequestContext, s } } } + +pub async fn create_device_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + let cloud_description = get_cstring("x-cloud-description")?; + let cloud_device_file = get_cstring("x-cloud-device-file")?; + let cloud_directory = get_cstring("x-cloud-directory")?; + + unsafe { + let ret = datamgr_api::CreateDevice( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + cloud_description.as_ptr(), + cloud_device_file.as_ptr(), + cloud_directory.as_ptr(), + ); + if ret == 1 { + Ok(json!("Create device success")) + } else { + Err(internal_error("Create device failed")) + } + } +} + +pub async fn create_profile_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_strategy = get_cstring("x-cloud-strategy")?; + + let header_cloud_application = match headers.get("x-cloud-application") { + Some(value) => Some(value.to_string()), + None => None, + }; + + let header_cloud_data_type = match headers.get("x-cloud-data-type") { + Some(value) => Some(value.to_string()), + None => None, + }; + + unsafe { + match (header_cloud_application.as_ref(), header_cloud_data_type.as_ref()) { + (Some(app), Some(dtype)) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud application")), + }; + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud data type")), + }; + let ret = datamgr_api::CreateProfile( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_data_type.as_ptr(), + cloud_strategy.as_ptr(), + ); + if ret == 1 { + Ok(json!("Create profile success")) + } else { + Err(ServerError::internal_error("Create profile failed")) + } + } + + (Some(app), None) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud application")), + }; + let ret = datamgr_api::CreateProfileForApplication( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_strategy.as_ptr(), + ); + if ret == 1 { + Ok(json!("Create profile for application success")) + } else { + Err(ServerError::internal_error("Create profile for application failed")) + } + } + + (None, Some(dtype)) => { + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud data type")), + }; + let ret = datamgr_api::CreateProfileForDataType( + DATA_PLUGIN_MANAGER, + cloud_data_type.as_ptr(), + cloud_strategy.as_ptr(), + ); + if ret == 1 { + Ok(json!("Create profile for data type success")) + } else { + Err(internal_error("Create profile for data type failed")) + } + } + + (None, None) => { + Err(internal_error("Missing required headers: cloud_application or cloud_data_type")) + } + } + } +} + +pub async fn create_strategy_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + let cloud_description = get_cstring("x-cloud-description")?; + let ecc = get_cstring("x-cloud-error-correcting-algorithm")?; + let icc = get_cstring("x-cloud-integrity-check-algorithm")?; + + let life_time = match headers.get("x-cloud-life-time-in-second") { + Some(val) => match val.parse::() { + Ok(v) => v, + Err(_) => return Err(internal_error("Invalid x-cloud-life-time-in-second")), + }, + None => return Err(internal_error("Missing x-cloud-life-time-in-second header")), + }; + + let header_cloud_locations = match headers.get("x-cloud-locations") { + Some(value) => value.to_string(), + None => return Err(internal_error("Missing x-cloud-locations header")), + }; + + // 解析 x-cloud-locations + let mut device_names = Vec::new(); + let mut relative_paths = Vec::new(); + + for entry in header_cloud_locations.split(';') { + let mut device_name: Option = None; + let mut relative_path: Option = None; + + for pair in entry.split(',') { + let mut kv = pair.splitn(2, '='); + let key = kv.next().unwrap_or("").trim(); + let value = kv.next().unwrap_or("").trim(); + + match key { + "deviceName" => device_name = Some(value.to_string()), + "relativePath" => relative_path = Some(value.to_string()), + _ => {} + } + } + + match (device_name, relative_path) { + (Some(dn), Some(rp)) => { + device_names.push(CString::new(dn).map_err(|_| internal_error("Invalid deviceName"))?); + relative_paths.push(CString::new(rp).map_err(|_| internal_error("Invalid relativePath"))?); + } + _ => return Err(internal_error("Malformed x-cloud-locations entry")), + } + } + + let location_count = device_names.len() as i32; + if location_count == 0 { + return Err(internal_error("No valid locations found")); + } + + let device_name_ptrs: Vec<*const c_char> = device_names.iter().map(|s| s.as_ptr()).collect(); + let relative_path_ptrs: Vec<*const c_char> = relative_paths.iter().map(|s| s.as_ptr()).collect(); + + unsafe { + let ret = datamgr_api::CreateStrategy( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + cloud_description.as_ptr(), + location_count, + device_name_ptrs.as_ptr() as *mut *const c_char, + relative_path_ptrs.as_ptr() as *mut *const c_char, + ecc.as_ptr(), + icc.as_ptr(), + life_time, + ); + + if ret == 1 { + Ok(json!("Create strategy success")) + } else { + Err(internal_error("Create strategy failed")) + } + } +} + +pub async fn find_profile_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_application = get_cstring("x-cloud-application")?; + let cloud_data_type = get_cstring("x-cloud-data-type")?; + + unsafe { + let ret = datamgr_api::FindProfile( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_data_type.as_ptr(), + ); + if ret.is_null() { + Err(ServerError::not_found("Profile not found")) + + } else { + let c_str: &CStr = CStr::from_ptr(ret); + + FreeString(ret); + + match c_str.to_str() { + Ok(profile_str) => { + Ok(json!(profile_str)) + }, + Err(_) => Err(internal_error("Failed to convert C string")), + } + } + } +} + +unsafe fn device_to_json(device_ptr: *mut Device) -> Option { + if device_ptr.is_null() { + return None; + } + + let device = *device_ptr; + + let cstr_to_string = |ptr: *mut c_char| { + if ptr.is_null() { + None + } else { + CStr::from_ptr(ptr).to_str().ok().map(|s| s.to_string()) + } + }; + + Some(json!({ + "name": cstr_to_string(device.name), + "description": cstr_to_string(device.description), + "deviceFile": cstr_to_string(device.deviceFile), + "directory": cstr_to_string(device.directory), + })) +} + +unsafe fn device_list_to_json(list_ptr: *mut DeviceList) -> Option { + if list_ptr.is_null() { + return None; + } + + let list = *list_ptr; + let mut devices_json = Vec::with_capacity(list.count as usize); + + for i in 0..list.count { + let device_ptr = *list.devices.add(i as usize); + if let Some(device_json) = device_to_json(device_ptr) { + devices_json.push(device_json); + } + } + + Some(json!(devices_json)) +} + +pub async fn get_device_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + // 获取 cloud-name header + let header_cloud_name = headers.get("x-cloud-name").map(|v| v.to_string()); + + unsafe { + match header_cloud_name { + None => { + let ret = datamgr_api::GetAllDevices( + DATA_PLUGIN_MANAGER + ); + + match device_list_to_json(ret) { + Some(json) => { + FreeDeviceList(ret); + Ok(json) + }, + None => Err(ServerError::not_found("No devices found")), + } + } + Some(ref name) if name == "default" => { + let ret = datamgr_api::GetDefaultDevice( + DATA_PLUGIN_MANAGER + ); + + match device_to_json(ret) { + Some(json) => { + FreeDevice(ret); + Ok(json) + }, + None => Err(ServerError::not_found("Default device not found")), + } + } + Some(name) => { + let c_name = CString::new(name) + .map_err(|_| ServerError::internal_error("Invalid cloud name"))?; + + let ret = datamgr_api::GetDeviceByName( + DATA_PLUGIN_MANAGER, + c_name.as_ptr() + ); + + match device_to_json(ret) { + Some(json) => { + FreeDevice(ret); + Ok(json) + }, + None => Err(ServerError::not_found("Device not found")), + } + } + } + } +} + +unsafe fn strategy_to_json(ptr: *mut Strategy) -> Option { + if ptr.is_null() { + return None; + } + + let strategy = *ptr; + + let cstr_to_string = |s: *mut c_char| { + if s.is_null() { + None + } else { + CStr::from_ptr(s).to_str().ok().map(|s| s.to_string()) + } + }; + + let mut device_names = Vec::new(); + let mut relative_paths = Vec::new(); + + for i in 0..strategy.locationCount { + let dev_name_ptr = *strategy.locationDeviceNames.add(i as usize); + let rel_path_ptr = *strategy.locationRelativePaths.add(i as usize); + + let dev_name = cstr_to_string(dev_name_ptr).unwrap_or_default(); + let rel_path = cstr_to_string(rel_path_ptr).unwrap_or_default(); + + device_names.push(dev_name); + relative_paths.push(rel_path); + } + + Some(json!({ + "name": cstr_to_string(strategy.name), + "description": cstr_to_string(strategy.description), + "locationCount": strategy.locationCount, + "locationDeviceNames": device_names, + "locationRelativePaths": relative_paths, + "errorCorrectingAlgorithm": cstr_to_string(strategy.errorCorrectingAlgorithm), + "integrityCheckAlgorithm": cstr_to_string(strategy.integrityCheckAlgorithm), + "lifeTimeInSecond": strategy.lifeTimeInSecond, + })) +} + +unsafe fn strategy_list_to_json(list_ptr: *mut StrategyList) -> Option { + if list_ptr.is_null() { + return None; + } + + let list = *list_ptr; + let mut strategies_json = Vec::with_capacity(list.count as usize); + + for i in 0..list.count { + let strategy_ptr = *list.strategies.add(i as usize); + if let Some(json) = strategy_to_json(strategy_ptr) { + strategies_json.push(json); + } + } + + Some(json!(strategies_json)) +} + + +pub async fn get_strategy_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + // 获取 cloud-name header + let header_cloud_name = headers.get("x-cloud-name").map(|v| v.to_string()); + + unsafe { + match header_cloud_name { + None => { + let ret = datamgr_api::GetAllStrategies( + DATA_PLUGIN_MANAGER + ); + + match strategy_list_to_json(ret) { + Some(json) => { + FreeStrategyList(ret); + Ok(json) + }, + None => Err(ServerError::not_found("No strategy found")), + } + } + Some(ref name) if name == "default" => { + let ret = datamgr_api::GetDefaultStrategy( + DATA_PLUGIN_MANAGER + ); + + match strategy_to_json(ret) { + Some(json) => { + FreeStrategy(ret); + Ok(json) + }, + None => Err(ServerError::not_found("Default strategy not found")), + } + } + Some(name) => { + let c_name = CString::new(name) + .map_err(|_| ServerError::internal_error("Invalid cloud name"))?; + + let ret = datamgr_api::GetStrategyByName( + DATA_PLUGIN_MANAGER, + c_name.as_ptr() + ); + + match strategy_to_json(ret) { + Some(json) => { + FreeStrategy(ret); + Ok(json) + }, + None => Err(ServerError::not_found("Strategy not found")), + } + } + } + } +} + +pub async fn get_profile_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let header_cloud_application = match headers.get("x-cloud-application") { + Some(value) => Some(value.to_string()), + None => None, + }; + + let header_cloud_data_type = match headers.get("x-cloud-data-type") { + Some(value) => Some(value.to_string()), + None => None, + }; + + unsafe { + let ret = match (header_cloud_application.as_ref(), header_cloud_data_type.as_ref()) { + (Some(app), Some(dtype)) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud application")), + }; + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud data type")), + }; + datamgr_api::GetProfile( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_data_type.as_ptr(), + ) + } + + (Some(app), None) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud application")), + }; + datamgr_api::GetProfileForApplication( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + ) + } + + (None, Some(dtype)) => { + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud data type")), + }; + datamgr_api::GetProfileForDataType( + DATA_PLUGIN_MANAGER, + cloud_data_type.as_ptr(), + ) + } + + (None, None) => { + return Err(ServerError::internal_error("Missing required headers: cloud_application or cloud_data_type")) + } + }; + + if ret.is_null() { + Err(ServerError::not_found("Profile not found")) + + } else { + let c_str: &CStr = CStr::from_ptr(ret); + + FreeString(ret); + + match c_str.to_str() { + Ok(profile_str) => { + Ok(json!(profile_str)) + }, + Err(_) => Err(ServerError::internal_error("Failed to convert C string")), + } + } + } +} + +pub async fn remove_device_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + + unsafe { + let ret = datamgr_api::RemoveDevice( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + ); + + if ret == 1 { + Ok(json!("Remove device success")) + } else { + + Err(ServerError::internal_error("Remove device failed")) + } + } +} + +pub async fn remove_strategy_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + + unsafe { + let ret = datamgr_api::RemoveStrategy( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + ); + + if ret == 1 { + Ok(json!("Remove strategy success")) + } else { + + Err(ServerError::internal_error("Remove strategy failed")) + } + } +} + +pub async fn remove_profile_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let header_cloud_application = match headers.get("x-cloud-application") { + Some(value) => Some(value.to_string()), + None => None, + }; + + let header_cloud_data_type = match headers.get("x-cloud-data-type") { + Some(value) => Some(value.to_string()), + None => None, + }; + + unsafe { + let ret = match (header_cloud_application.as_ref(), header_cloud_data_type.as_ref()) { + (Some(app), Some(dtype)) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud application")), + }; + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud data type")), + }; + datamgr_api::RemoveProfile( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_data_type.as_ptr(), + ) + } + + (Some(app), None) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud application")), + }; + datamgr_api::RemoveProfileForApplication( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + ) + } + + (None, Some(dtype)) => { + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(ServerError::internal_error("Invalid cloud data type")), + }; + datamgr_api::RemoveProfileForDataType( + DATA_PLUGIN_MANAGER, + cloud_data_type.as_ptr(), + ) + } + + (None, None) => { + return Err(ServerError::internal_error("Missing required headers: cloud_application or cloud_data_type")) + } + }; + + if ret == 1 { + Ok(json!("Remove profile success")) + } else { + + Err(ServerError::internal_error("Remove profile failed")) + } + } +} + +pub async fn update_device_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + let cloud_description = get_cstring("x-cloud-new-description")?; + let cloud_device_file = get_cstring("x-cloud-new-device-file")?; + let cloud_directory = get_cstring("x-cloud-new-directory")?; + + unsafe { + let ret = datamgr_api::UpdateDevice( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + cloud_description.as_ptr(), + cloud_device_file.as_ptr(), + cloud_directory.as_ptr(), + ); + if ret == 1 { + Ok(json!("Update device success")) + } else { + Err(internal_error("Update device failed")) + } + } +} + +pub async fn update_strategy_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_name = get_cstring("x-cloud-name")?; + let cloud_description = get_cstring("x-cloud-new-description")?; + let ecc = get_cstring("x-cloud-new-error-correcting-algorithm")?; + let icc = get_cstring("x-cloud-new-integrity-check-algorithm")?; + + let life_time = match headers.get("x-cloud-new-life-time-in-second") { + Some(val) => match val.parse::() { + Ok(v) => v, + Err(_) => return Err(internal_error("Invalid x-cloud-new-life-time-in-second")), + }, + None => return Err(internal_error("Missing x-cloud-new-life-time-in-second header")), + }; + + let header_cloud_locations = match headers.get("x-cloud-new-locations") { + Some(value) => value.to_string(), + None => return Err(internal_error("Missing x-cloud-new-locations header")), + }; + + // 解析 x-cloud-new-locations + let mut device_names = Vec::new(); + let mut relative_paths = Vec::new(); + + for entry in header_cloud_locations.split(';') { + let mut device_name: Option = None; + let mut relative_path: Option = None; + + for pair in entry.split(',') { + let mut kv = pair.splitn(2, '='); + let key = kv.next().unwrap_or("").trim(); + let value = kv.next().unwrap_or("").trim(); + + match key { + "deviceName" => device_name = Some(value.to_string()), + "relativePath" => relative_path = Some(value.to_string()), + _ => {} + } + } + + match (device_name, relative_path) { + (Some(dn), Some(rp)) => { + device_names.push(CString::new(dn).map_err(|_| internal_error("Invalid deviceName"))?); + relative_paths.push(CString::new(rp).map_err(|_| internal_error("Invalid relativePath"))?); + } + _ => return Err(internal_error("Malformed x-cloud-locations entry")), + } + } + + let location_count = device_names.len() as i32; + if location_count == 0 { + return Err(internal_error("No valid locations found")); + } + + let device_name_ptrs: Vec<*const c_char> = device_names.iter().map(|s| s.as_ptr()).collect(); + let relative_path_ptrs: Vec<*const c_char> = relative_paths.iter().map(|s| s.as_ptr()).collect(); + + unsafe { + let ret = datamgr_api::UpdateStrategy( + DATA_PLUGIN_MANAGER, + cloud_name.as_ptr(), + cloud_description.as_ptr(), + location_count, + device_name_ptrs.as_ptr() as *mut *const c_char, + relative_path_ptrs.as_ptr() as *mut *const c_char, + ecc.as_ptr(), + icc.as_ptr(), + life_time, + ); + + if ret == 1 { + Ok(json!("Update strategy success")) + } else { + Err(internal_error("Update strategy failed")) + } + } +} + +pub async fn update_profile_handler( + _: Arc, + _request_context: RequestContext, + server_request: ServerRequest, +) -> ServerResult { + let headers = server_request.headers; + + let internal_error = |msg: &str| -> ServerError { + ServerError::internal_error(msg) + }; + + let get_cstring = |key: &str| { + match headers.get(key) { + Some(val) => CString::new(val.to_string()).map_err(|_| internal_error(&format!("Invalid {}", key))), + None => Err(internal_error(&format!("Missing {} header", key))), + } + }; + + let cloud_strategy = get_cstring("x-cloud-new-strategy")?; + + let header_cloud_application = match headers.get("x-cloud-new-application") { + Some(value) => Some(value.to_string()), + None => None, + }; + + let header_cloud_data_type = match headers.get("x-cloud-new-data-type") { + Some(value) => Some(value.to_string()), + None => None, + }; + + unsafe { + let ret = match (header_cloud_application.as_ref(), header_cloud_data_type.as_ref()) { + (Some(app), Some(dtype)) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud new application")), + }; + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud new data type")), + }; + datamgr_api::UpdateProfile( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_data_type.as_ptr(), + cloud_strategy.as_ptr(), + ) + } + + (Some(app), None) => { + let cloud_application = match CString::new(app.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud new application")), + }; + datamgr_api::UpdateProfileForApplication( + DATA_PLUGIN_MANAGER, + cloud_application.as_ptr(), + cloud_strategy.as_ptr(), + ) + } + + (None, Some(dtype)) => { + let cloud_data_type = match CString::new(dtype.as_str()) { + Ok(cstr) => cstr, + Err(_) => return Err(internal_error("Invalid cloud new data type")), + }; + datamgr_api::UpdateProfileForDataType( + DATA_PLUGIN_MANAGER, + cloud_data_type.as_ptr(), + cloud_strategy.as_ptr(), + ) + } + + (None, None) => { + return Err(internal_error("Missing required headers: cloud_application or cloud_data_type")) + } + }; + + if ret == 1 { + Ok(json!("Update profile success")) + } else { + Err(ServerError::internal_error("Update profile failed")) + } + } +} \ No newline at end of file diff --git a/src/cores/router.rs b/src/cores/router.rs index d67908b2f4189447176628b4b26535a3e2cb90dc..c5e407586101b8adfe6b5591dd6305de794de405 100644 --- a/src/cores/router.rs +++ b/src/cores/router.rs @@ -78,6 +78,19 @@ pub enum RouterKey { DataMgrMessage, DataMgrRequest, DataMgrReply, + DataMgrCreateDevice, + DataMgrCreateProfile, + DataMgrCreateStrategy, + DataMgrFindProfile, + DataMgrGetDevice, + DataMgrGetProfile, + DataMgrGetStrategy, + DataMgrRemoveDevice, + DataMgrRemoveProfile, + DataMgrRemoveStrategy, + DataMgrUpdateDevice, + DataMgrUpdateProfile, + DataMgrUpdateStrategy, // Consensus Service Router Key ConsensusRequests, @@ -496,6 +509,84 @@ impl Router { RouterKey::DataMgrReply, handlers::datamgr::reply_handler ); + + add_route!( + router, + RouterKey::DataMgrCreateDevice, + handlers::datamgr::create_device_handler + ); + + add_route!( + router, + RouterKey::DataMgrCreateProfile, + handlers::datamgr::create_profile_handler + ); + + add_route!( + router, + RouterKey::DataMgrCreateStrategy, + handlers::datamgr::create_strategy_handler + ); + + add_route!( + router, + RouterKey::DataMgrFindProfile, + handlers::datamgr::find_profile_handler + ); + + add_route!( + router, + RouterKey::DataMgrGetDevice, + handlers::datamgr::get_device_handler + ); + + add_route!( + router, + RouterKey::DataMgrGetProfile, + handlers::datamgr::get_profile_handler + ); + + add_route!( + router, + RouterKey::DataMgrGetStrategy, + handlers::datamgr::get_strategy_handler + ); + + add_route!( + router, + RouterKey::DataMgrRemoveDevice, + handlers::datamgr::remove_device_handler + ); + + add_route!( + router, + RouterKey::DataMgrRemoveProfile, + handlers::datamgr::remove_profile_handler + ); + + add_route!( + router, + RouterKey::DataMgrRemoveStrategy, + handlers::datamgr::remove_strategy_handler + ); + + add_route!( + router, + RouterKey::DataMgrUpdateDevice, + handlers::datamgr::update_device_handler + ); + + add_route!( + router, + RouterKey::DataMgrUpdateProfile, + handlers::datamgr::update_profile_handler + ); + + add_route!( + router, + RouterKey::DataMgrUpdateStrategy, + handlers::datamgr::update_strategy_handler + ); } // consensus service routers diff --git a/src/cores/servers/actix_web/mod.rs b/src/cores/servers/actix_web/mod.rs index e051f2c73d677dd1d3272e052e0239bb48b9afac..ef240daf16d630d3e30f870daebdcfb1f1be974e 100644 --- a/src/cores/servers/actix_web/mod.rs +++ b/src/cores/servers/actix_web/mod.rs @@ -919,6 +919,19 @@ pub mod datamgr { app.service(message); app.service(request); app.service(reply); + app.service(create_device); + app.service(create_profile); + app.service(create_strategy); + app.service(find_profile); + app.service(get_device); + app.service(get_profile); + app.service(get_strategy); + app.service(remove_device); + app.service(remove_profile); + app.service(remove_strategy); + app.service(update_device); + app.service(update_profile); + app.service(update_strategy); } #[derive(Serialize, Deserialize, Apiv2Schema)] @@ -931,17 +944,6 @@ pub mod datamgr { pub uuid: String, } - /*define_json_response_method!( - body_required - upload_data, - post, - "/{data_type}", - DataTypePath, - (), - RouterKey::DataMgrUploadData, - "DataMgr" - );*/ - define_raw_response_method!( upload_data, post, @@ -1144,6 +1146,149 @@ pub mod datamgr { RouterKey::DataMgrReply, "DataMgr" ); + + define_json_response_method!( + body_unrequired + create_device, + post, + "/Device", + (), + (), + RouterKey::DataMgrCreateDevice, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + create_profile, + post, + "/Profile", + (), + (), + RouterKey::DataMgrCreateProfile, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + create_strategy, + post, + "/Strategy", + (), + (), + RouterKey::DataMgrCreateStrategy, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + find_profile, + get, + "/Profile/Find", + (), + (), + RouterKey::DataMgrFindProfile, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + get_device, + get, + "/Device", + (), + (), + RouterKey::DataMgrGetDevice, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + get_profile, + get, + "/Profile", + (), + (), + RouterKey::DataMgrGetProfile, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + get_strategy, + get, + "/Strategy", + (), + (), + RouterKey::DataMgrGetStrategy, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + remove_device, + delete, + "/Device", + (), + (), + RouterKey::DataMgrRemoveDevice, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + remove_profile, + delete, + "/Profile", + (), + (), + RouterKey::DataMgrRemoveProfile, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + remove_strategy, + delete, + "/Strategy", + (), + (), + RouterKey::DataMgrRemoveStrategy, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + update_device, + put, + "/Device", + (), + (), + RouterKey::DataMgrUpdateDevice, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + update_profile, + put, + "/Profile", + (), + (), + RouterKey::DataMgrUpdateProfile, + "DataMgr" + ); + + define_json_response_method!( + body_unrequired + update_strategy, + put, + "/Strategy", + (), + (), + RouterKey::DataMgrUpdateStrategy, + "DataMgr" + ); } pub mod consensus {