Loading system/gd/rust/linux/client/src/command_handler.rs +6 −4 Original line number Diff line number Diff line Loading @@ -523,6 +523,12 @@ impl CommandHandler { let command = get_arg(args, 0)?; if matches!(&command[..], "show" | "discoverable" | "connectable" | "set-name") { if !self.lock_context().adapter_ready { return Err(self.adapter_not_ready()); } } match &command[..] { "enable" => { if self.lock_context().is_restricted { Loading @@ -537,10 +543,6 @@ impl CommandHandler { self.lock_context().manager_dbus.stop(default_adapter); } "show" => { if !self.lock_context().adapter_ready { return Err(self.adapter_not_ready()); } let enabled = self.lock_context().enabled; let address = self.lock_context().adapter_address.unwrap_or_default(); let context = self.lock_context(); Loading system/gd/rust/linux/client/src/main.rs +61 −33 Original line number Diff line number Diff line Loading @@ -362,7 +362,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { .help("Specify a timeout in seconds for a non-interactive command"), ) .get_matches(); let command = value_t!(matches, "command", String); let command = value_t!(matches, "command", String).ok(); let is_restricted = matches.is_present("restricted"); let timeout_secs = value_t!(matches, "timeout", u64); Loading Loading @@ -433,28 +433,36 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // right away. let default_adapter = context.lock().unwrap().default_adapter; { let default_adapter_enabled = { let mut context_locked = context.lock().unwrap(); match context_locked.manager_dbus.rpc.get_adapter_enabled(default_adapter).await { Ok(ret) => { if ret { Ok(enabled) => { if enabled { context_locked.set_adapter_enabled(default_adapter, true); } enabled } Err(e) => { panic!("Bluetooth Manager is not available. Exiting. D-Bus error: {}", e); } } } }; let handler = CommandHandler::new(context.clone()); if command.is_ok() { if command.is_some() { // Timeout applies only to non-interactive commands. if let Ok(timeout_secs) = timeout_secs { let timeout_duration = Duration::from_secs(timeout_secs); match timeout( timeout_duration, handle_client_command(handler, tx, rx, context, command), handle_client_command( handler, tx, rx, context, command, default_adapter_enabled, ), ) .await { Loading @@ -470,31 +478,50 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // There are two scenarios in which handle_client_command is run without a timeout. // - Interactive commands: none of these commands require a timeout. // - Non-interactive commands that have not specified a timeout. handle_client_command(handler, tx, rx, context, command).await?; handle_client_command(handler, tx, rx, context, command, default_adapter_enabled).await?; Result::Ok(()) }) } // If btclient runs without command arguments, the interactive shell // actions are performed. // If btclient runs with command arguments, the command is executed // once. There are two cases to exit. // Case 1: if the command does not need a callback, e.g., "help", // it will exit after running handler.process_cmd_line(). // Case 2: if the command needs a callback, e.g., "media log", // it will exit after the callback has been run in the arm // of ForegroundActions::RunCallback(callback). // If btclient runs without command arguments, the interactive shell actions are performed. // If btclient runs with command arguments, the command is executed once. // There are 2 cases to run the command and 2 cases to exit. // Run: // Case 1: If |run_command_on_ready|, run the command after the callbacks are registered // successfully. // Case 2: If not |run_command_on_ready|, run the command immediately. // Exit: // Case 1: if the command does not need a callback, e.g., "help", it will exit after running // handler.process_cmd_line(). // Case 2: if the command needs a callback, e.g., "media log", it will exit after the callback // has been run in the arm of ForegroundActions::RunCallback(callback). async fn handle_client_command( mut handler: CommandHandler, tx: mpsc::Sender<ForegroundActions>, mut rx: mpsc::Receiver<ForegroundActions>, context: Arc<Mutex<ClientContext>>, command: Result<String, clap::Error>, command: Option<String>, run_command_on_ready: bool, ) -> Result<(), Box<dyn std::error::Error>> { if !run_command_on_ready { if let Some(command) = command.as_ref() { let mut iter = command.split(' ').map(String::from); let first = iter.next().unwrap_or(String::from("")); // Return immediately if the command fails to execute. if !handler.process_cmd_line(&first, &iter.collect::<Vec<String>>()) { return Err("failed process command".into()); } // If there is no callback to wait for, we're done. if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { return Ok(()); } } } let semaphore_fg = Arc::new(tokio::sync::Semaphore::new(1)); // If there are no command arguments, start the interactive shell. if command.is_err() { if command.is_none() { let command_rule_list = handler.get_command_rule_list().clone(); let context_for_closure = context.clone(); Loading Loading @@ -544,7 +571,7 @@ async fn handle_client_command( callback(context.clone()); // Break the loop as a non-interactive command is completed. if command.is_ok() { if command.is_some() { break; } } Loading Loading @@ -759,9 +786,8 @@ async fn handle_client_command( print_info!("Adapter {} is ready", adapter_address.to_string()); // Run the command with the command arguments as the client is // non-interactive. if let Ok(command) = command.as_ref() { if run_command_on_ready { if let Some(command) = command.as_ref() { let mut iter = command.split(' ').map(String::from); let first = iter.next().unwrap_or(String::from("")); if !handler.process_cmd_line(&first, &iter.collect::<Vec<String>>()) { Loading @@ -771,11 +797,13 @@ async fn handle_client_command( // Break the loop immediately if there is no callback // to wait for. if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { break; } } } } ForegroundActions::Readline(result) => match result { Err(rustyline::error::ReadlineError::Interrupted) => { // Ctrl-C cancels the currently typed line, do nothing and ready to do next Loading Loading
system/gd/rust/linux/client/src/command_handler.rs +6 −4 Original line number Diff line number Diff line Loading @@ -523,6 +523,12 @@ impl CommandHandler { let command = get_arg(args, 0)?; if matches!(&command[..], "show" | "discoverable" | "connectable" | "set-name") { if !self.lock_context().adapter_ready { return Err(self.adapter_not_ready()); } } match &command[..] { "enable" => { if self.lock_context().is_restricted { Loading @@ -537,10 +543,6 @@ impl CommandHandler { self.lock_context().manager_dbus.stop(default_adapter); } "show" => { if !self.lock_context().adapter_ready { return Err(self.adapter_not_ready()); } let enabled = self.lock_context().enabled; let address = self.lock_context().adapter_address.unwrap_or_default(); let context = self.lock_context(); Loading
system/gd/rust/linux/client/src/main.rs +61 −33 Original line number Diff line number Diff line Loading @@ -362,7 +362,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { .help("Specify a timeout in seconds for a non-interactive command"), ) .get_matches(); let command = value_t!(matches, "command", String); let command = value_t!(matches, "command", String).ok(); let is_restricted = matches.is_present("restricted"); let timeout_secs = value_t!(matches, "timeout", u64); Loading Loading @@ -433,28 +433,36 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // right away. let default_adapter = context.lock().unwrap().default_adapter; { let default_adapter_enabled = { let mut context_locked = context.lock().unwrap(); match context_locked.manager_dbus.rpc.get_adapter_enabled(default_adapter).await { Ok(ret) => { if ret { Ok(enabled) => { if enabled { context_locked.set_adapter_enabled(default_adapter, true); } enabled } Err(e) => { panic!("Bluetooth Manager is not available. Exiting. D-Bus error: {}", e); } } } }; let handler = CommandHandler::new(context.clone()); if command.is_ok() { if command.is_some() { // Timeout applies only to non-interactive commands. if let Ok(timeout_secs) = timeout_secs { let timeout_duration = Duration::from_secs(timeout_secs); match timeout( timeout_duration, handle_client_command(handler, tx, rx, context, command), handle_client_command( handler, tx, rx, context, command, default_adapter_enabled, ), ) .await { Loading @@ -470,31 +478,50 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { // There are two scenarios in which handle_client_command is run without a timeout. // - Interactive commands: none of these commands require a timeout. // - Non-interactive commands that have not specified a timeout. handle_client_command(handler, tx, rx, context, command).await?; handle_client_command(handler, tx, rx, context, command, default_adapter_enabled).await?; Result::Ok(()) }) } // If btclient runs without command arguments, the interactive shell // actions are performed. // If btclient runs with command arguments, the command is executed // once. There are two cases to exit. // Case 1: if the command does not need a callback, e.g., "help", // it will exit after running handler.process_cmd_line(). // Case 2: if the command needs a callback, e.g., "media log", // it will exit after the callback has been run in the arm // of ForegroundActions::RunCallback(callback). // If btclient runs without command arguments, the interactive shell actions are performed. // If btclient runs with command arguments, the command is executed once. // There are 2 cases to run the command and 2 cases to exit. // Run: // Case 1: If |run_command_on_ready|, run the command after the callbacks are registered // successfully. // Case 2: If not |run_command_on_ready|, run the command immediately. // Exit: // Case 1: if the command does not need a callback, e.g., "help", it will exit after running // handler.process_cmd_line(). // Case 2: if the command needs a callback, e.g., "media log", it will exit after the callback // has been run in the arm of ForegroundActions::RunCallback(callback). async fn handle_client_command( mut handler: CommandHandler, tx: mpsc::Sender<ForegroundActions>, mut rx: mpsc::Receiver<ForegroundActions>, context: Arc<Mutex<ClientContext>>, command: Result<String, clap::Error>, command: Option<String>, run_command_on_ready: bool, ) -> Result<(), Box<dyn std::error::Error>> { if !run_command_on_ready { if let Some(command) = command.as_ref() { let mut iter = command.split(' ').map(String::from); let first = iter.next().unwrap_or(String::from("")); // Return immediately if the command fails to execute. if !handler.process_cmd_line(&first, &iter.collect::<Vec<String>>()) { return Err("failed process command".into()); } // If there is no callback to wait for, we're done. if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { return Ok(()); } } } let semaphore_fg = Arc::new(tokio::sync::Semaphore::new(1)); // If there are no command arguments, start the interactive shell. if command.is_err() { if command.is_none() { let command_rule_list = handler.get_command_rule_list().clone(); let context_for_closure = context.clone(); Loading Loading @@ -544,7 +571,7 @@ async fn handle_client_command( callback(context.clone()); // Break the loop as a non-interactive command is completed. if command.is_ok() { if command.is_some() { break; } } Loading Loading @@ -759,9 +786,8 @@ async fn handle_client_command( print_info!("Adapter {} is ready", adapter_address.to_string()); // Run the command with the command arguments as the client is // non-interactive. if let Ok(command) = command.as_ref() { if run_command_on_ready { if let Some(command) = command.as_ref() { let mut iter = command.split(' ').map(String::from); let first = iter.next().unwrap_or(String::from("")); if !handler.process_cmd_line(&first, &iter.collect::<Vec<String>>()) { Loading @@ -771,11 +797,13 @@ async fn handle_client_command( // Break the loop immediately if there is no callback // to wait for. if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { if !context.lock().unwrap().client_commands_with_callbacks.contains(&first) { break; } } } } ForegroundActions::Readline(result) => match result { Err(rustyline::error::ReadlineError::Interrupted) => { // Ctrl-C cancels the currently typed line, do nothing and ready to do next Loading