diff --git a/adb_client/src/device/adb_message_device.rs b/adb_client/src/device/adb_message_device.rs index b0974b4..d397dab 100644 --- a/adb_client/src/device/adb_message_device.rs +++ b/adb_client/src/device/adb_message_device.rs @@ -11,18 +11,18 @@ use super::{ADBTransportMessage, MessageCommand, models::MessageSubcommand}; #[derive(Debug)] pub struct ADBMessageDevice { transport: T, - local_id: Option, - remote_id: Option, +} + +#[derive(Debug, Clone, Copy)] +pub struct ADBSession { + pub local_id: u32, + pub remote_id: u32, } impl ADBMessageDevice { /// Instantiate a new [`ADBMessageTransport`] pub fn new(transport: T) -> Self { - Self { - transport, - local_id: None, - remote_id: None, - } + Self { transport } } pub(crate) fn get_transport(&mut self) -> &T { @@ -34,12 +34,15 @@ impl ADBMessageDevice { } /// Receive a message and acknowledge it by replying with an `OKAY` command - pub(crate) fn recv_and_reply_okay(&mut self) -> Result { + pub(crate) fn recv_and_reply_okay( + &mut self, + session: ADBSession, + ) -> Result { let message = self.transport.read_message()?; self.transport.write_message(ADBTransportMessage::new( MessageCommand::Okay, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, &[], ))?; Ok(message) @@ -60,11 +63,12 @@ impl ADBMessageDevice { pub(crate) fn recv_file( &mut self, + session: ADBSession, mut output: W, ) -> std::result::Result<(), RustADBError> { let mut len: Option = None; loop { - let payload = self.recv_and_reply_okay()?.into_payload(); + let payload = self.recv_and_reply_okay(session)?.into_payload(); let mut rdr = Cursor::new(&payload); while rdr.position() != payload.len() as u64 { match len.take() { @@ -97,8 +101,7 @@ impl ADBMessageDevice { pub(crate) fn push_file( &mut self, - local_id: u32, - remote_id: u32, + session: ADBSession, mut reader: R, ) -> std::result::Result<(), RustADBError> { let mut buffer = [0; BUFFER_SIZE]; @@ -111,8 +114,8 @@ impl ADBMessageDevice { let message = ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, + session.local_id, + session.remote_id, &serialized_message, ); @@ -131,8 +134,8 @@ impl ADBMessageDevice { let message = ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, + session.local_id, + session.remote_id, &serialized_message, ); @@ -159,8 +162,8 @@ impl ADBMessageDevice { let message = ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, + session.local_id, + session.remote_id, &serialized_message, ); @@ -173,24 +176,27 @@ impl ADBMessageDevice { } } - pub(crate) fn begin_synchronization(&mut self) -> Result<()> { - self.open_session(b"sync:\0")?; - Ok(()) + pub(crate) fn begin_synchronization(&mut self) -> Result { + self.open_session(b"sync:\0") } - pub(crate) fn stat_with_explicit_ids(&mut self, remote_path: &str) -> Result { + pub(crate) fn stat_with_explicit_ids( + &mut self, + session: ADBSession, + remote_path: &str, + ) -> Result { let stat_buffer = MessageSubcommand::Stat.with_arg(remote_path.len() as u32); let message = ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, &bincode::serialize(&stat_buffer).map_err(|_e| RustADBError::ConversionError)?, ); self.send_and_expect_okay(message)?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, remote_path.as_bytes(), ))?; let response = self.transport.read_message()?; @@ -200,24 +206,25 @@ impl ADBMessageDevice { .map_err(|_e| RustADBError::ConversionError) } - pub(crate) fn end_transaction(&mut self) -> Result<()> { + pub(crate) fn end_transaction(&mut self, session: ADBSession) -> Result<()> { let quit_buffer = MessageSubcommand::Quit.with_arg(0u32); self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, &bincode::serialize(&quit_buffer).map_err(|_e| RustADBError::ConversionError)?, ))?; let _discard_close = self.transport.read_message()?; Ok(()) } - pub(crate) fn open_session(&mut self, data: &[u8]) -> Result { + pub(crate) fn open_session(&mut self, data: &[u8]) -> Result { let mut rng = rand::rng(); + let local_id: u32 = rng.random(); let message = ADBTransportMessage::new( MessageCommand::Open, - rng.random(), // Our 'local-id' + local_id, // Our 'local-id' 0, data, ); @@ -225,21 +232,25 @@ impl ADBMessageDevice { let response = self.get_transport_mut().read_message()?; - self.local_id = Some(response.header().arg1()); - self.remote_id = Some(response.header().arg0()); + if response.header().command() != MessageCommand::Okay { + return Err(RustADBError::ADBRequestFailed(format!( + "Open session failed: got {} in respone instead of OKAY", + response.header().command() + ))); + } - Ok(response) - } + if response.header().arg1() != local_id { + return Err(RustADBError::ADBRequestFailed(format!( + "Open session failed: respones used {} for our local_id instead of {local_id}", + response.header().arg1() + ))); + } - pub(crate) fn get_local_id(&self) -> Result { - self.local_id.ok_or(RustADBError::ADBRequestFailed( - "connection not opened, no local_id".into(), - )) - } + let session = ADBSession { + local_id, + remote_id: response.header().arg0(), + }; - pub(crate) fn get_remote_id(&self) -> Result { - self.remote_id.ok_or(RustADBError::ADBRequestFailed( - "connection not opened, no remote_id".into(), - )) + Ok(session) } } diff --git a/adb_client/src/device/commands/framebuffer.rs b/adb_client/src/device/commands/framebuffer.rs index d41422f..b20b3d0 100644 --- a/adb_client/src/device/commands/framebuffer.rs +++ b/adb_client/src/device/commands/framebuffer.rs @@ -11,9 +11,9 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn framebuffer_inner(&mut self) -> Result, Vec>> { - self.open_session(b"framebuffer:\0")?; + let session = self.open_session(b"framebuffer:\0")?; - let response = self.recv_and_reply_okay()?; + let response = self.recv_and_reply_okay(session)?; let mut payload_cursor = Cursor::new(response.payload()); @@ -36,7 +36,7 @@ impl ADBMessageDevice { break; } - let response = self.recv_and_reply_okay()?; + let response = self.recv_and_reply_okay(session)?; framebuffer_data.extend_from_slice(&response.into_payload()); @@ -69,7 +69,7 @@ impl ADBMessageDevice { break; } - let response = self.recv_and_reply_okay()?; + let response = self.recv_and_reply_okay(session)?; framebuffer_data.extend_from_slice(&response.into_payload()); diff --git a/adb_client/src/device/commands/install.rs b/adb_client/src/device/commands/install.rs index 92d0ba6..2ba5342 100644 --- a/adb_client/src/device/commands/install.rs +++ b/adb_client/src/device/commands/install.rs @@ -14,11 +14,12 @@ impl ADBMessageDevice { let file_size = apk_file.metadata()?.len(); - self.open_session(format!("exec:cmd package 'install' -S {}\0", file_size).as_bytes())?; + let session = + self.open_session(format!("exec:cmd package 'install' -S {}\0", file_size).as_bytes())?; let transport = self.get_transport().clone(); - let mut writer = MessageWriter::new(transport, self.get_local_id()?, self.get_remote_id()?); + let mut writer = MessageWriter::new(transport, session.local_id, session.remote_id); std::io::copy(&mut apk_file, &mut writer)?; diff --git a/adb_client/src/device/commands/pull.rs b/adb_client/src/device/commands/pull.rs index 9e5bc55..e9b13a3 100644 --- a/adb_client/src/device/commands/pull.rs +++ b/adb_client/src/device/commands/pull.rs @@ -10,10 +10,10 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn pull, W: Write>(&mut self, source: A, output: W) -> Result<()> { - self.begin_synchronization()?; + let session = self.begin_synchronization()?; let source = source.as_ref(); - let adb_stat_response = self.stat_with_explicit_ids(source)?; + let adb_stat_response = self.stat_with_explicit_ids(session, source)?; if adb_stat_response.file_perm == 0 { return Err(RustADBError::UnknownResponseType( @@ -21,11 +21,13 @@ impl ADBMessageDevice { )); } - let local_id = self.get_local_id()?; - let remote_id = self.get_remote_id()?; - self.get_transport_mut().write_message_with_timeout( - ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, &[]), + ADBTransportMessage::new( + MessageCommand::Okay, + session.local_id, + session.remote_id, + &[], + ), std::time::Duration::from_secs(4), )?; @@ -34,19 +36,19 @@ impl ADBMessageDevice { bincode::serialize(&recv_buffer).map_err(|_e| RustADBError::ConversionError)?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, &recv_buffer, ))?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, source.as_bytes(), ))?; - self.recv_file(output)?; - self.end_transaction()?; + self.recv_file(session, output)?; + self.end_transaction(session)?; Ok(()) } } diff --git a/adb_client/src/device/commands/push.rs b/adb_client/src/device/commands/push.rs index d87ee7a..a781cf3 100644 --- a/adb_client/src/device/commands/push.rs +++ b/adb_client/src/device/commands/push.rs @@ -10,7 +10,7 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn push>(&mut self, stream: R, path: A) -> Result<()> { - self.begin_synchronization()?; + let session = self.begin_synchronization()?; let path_header = format!("{},0777", path.as_ref()); @@ -21,14 +21,13 @@ impl ADBMessageDevice { self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - self.get_local_id()?, - self.get_remote_id()?, + session.local_id, + session.remote_id, &send_buffer, ))?; - self.push_file(self.get_local_id()?, self.get_remote_id()?, stream)?; - - self.end_transaction()?; + self.push_file(session, stream)?; + self.end_transaction(session)?; Ok(()) } diff --git a/adb_client/src/device/commands/shell.rs b/adb_client/src/device/commands/shell.rs index eea7097..4a1ae5e 100644 --- a/adb_client/src/device/commands/shell.rs +++ b/adb_client/src/device/commands/shell.rs @@ -10,14 +10,7 @@ use crate::{ impl ADBMessageDevice { /// Runs 'command' in a shell on the device, and write its output and error streams into output. pub(crate) fn shell_command(&mut self, command: &[&str], output: &mut dyn Write) -> Result<()> { - let response = self.open_session(format!("shell:{}\0", command.join(" "),).as_bytes())?; - - if response.header().command() != MessageCommand::Okay { - return Err(RustADBError::ADBRequestFailed(format!( - "wrong command {}", - response.header().command() - ))); - } + let session = self.open_session(format!("shell:{}\0", command.join(" "),).as_bytes())?; loop { let response = self.get_transport_mut().read_message()?; @@ -38,21 +31,22 @@ impl ADBMessageDevice { mut reader: &mut dyn Read, mut writer: Box<(dyn Write + Send)>, ) -> Result<()> { - self.open_session(b"shell:\0")?; + let session = self.open_session(b"shell:\0")?; let mut transport = self.get_transport().clone(); - let local_id = self.get_local_id()?; - let remote_id = self.get_remote_id()?; - // Reading thread, reads response from adbd std::thread::spawn(move || -> Result<()> { loop { let message = transport.read_message()?; // Acknowledge for more data - let response = - ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, &[]); + let response = ADBTransportMessage::new( + MessageCommand::Okay, + session.local_id, + session.remote_id, + &[], + ); transport.write_message(response)?; match message.header().command() { @@ -67,7 +61,8 @@ impl ADBMessageDevice { }); let transport = self.get_transport().clone(); - let mut shell_writer = ShellMessageWriter::new(transport, local_id, remote_id); + let mut shell_writer = + ShellMessageWriter::new(transport, session.local_id, session.remote_id); // Read from given reader (that could be stdin e.g), and write content to device adbd if let Err(e) = std::io::copy(&mut reader, &mut shell_writer) { diff --git a/adb_client/src/device/commands/stat.rs b/adb_client/src/device/commands/stat.rs index 27619b0..bc51303 100644 --- a/adb_client/src/device/commands/stat.rs +++ b/adb_client/src/device/commands/stat.rs @@ -4,9 +4,9 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn stat(&mut self, remote_path: &str) -> Result { - self.begin_synchronization()?; - let adb_stat_response = self.stat_with_explicit_ids(remote_path)?; - self.end_transaction()?; + let session = self.begin_synchronization()?; + let adb_stat_response = self.stat_with_explicit_ids(session, remote_path)?; + self.end_transaction(session)?; Ok(adb_stat_response) } }