Skip to content

Commit

Permalink
chore: internal updates (#74)
Browse files Browse the repository at this point in the history
* chore: update adb_client README.md

* chore(internal): add assert_command() method on ADBTransportMessage

* chore: minor internal changes

* chore: add server-only models
  • Loading branch information
cli-s1n authored Dec 13, 2024
1 parent 5a3ac68 commit 9002ecc
Show file tree
Hide file tree
Showing 46 changed files with 173 additions and 228 deletions.
29 changes: 10 additions & 19 deletions adb_cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,29 @@ Usage is quite simple, and tends to look like `adb`:
- To use ADB server as a proxy:

```bash
user@laptop ~/adb_client (main)> adb_cli --help
Rust ADB (Android Debug Bridge) CLI
user@laptop ~/adb_client (main)> adb_cli local --help
Device related commands using server

Usage: adb_cli [OPTIONS] <COMMAND>
Usage: adb_cli local [OPTIONS] <COMMAND>

Commands:
host-features List available server features
push Push a file on device
pull Pull a file from device
list List a directory on device
stat Stat a file specified on device
shell Spawn an interactive shell or run a list of commands on the device
pull Pull a file from device
push Push a file on device
stat Stat a file on device
run Run an activity on device specified by the intent
reboot Reboot the device
install Install an APK on device
framebuffer Dump framebuffer of device
host-features List available server features
list List a directory on device
logcat Get logs of device
version Print current ADB version
kill Ask ADB server to quit immediately
devices List connected devices
track-devices Track new devices showing up
pair Pair device with a given code
connect Connect device over WI-FI
disconnect Disconnect device over WI-FI
sms Send a SMS with given phone number and given content
rotate Rotate device screen from 90°
help Print this message or the help of the given subcommand(s)

Options:
-d, --debug
-a, --address <ADDRESS> [default: 127.0.0.1:5037]
-s, --serial <SERIAL> Serial id of a specific device. Every request will be sent to this device
-h, --help Print help
-V, --version Print version
```

- To interact directly with end devices
Expand Down
5 changes: 4 additions & 1 deletion adb_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ fn main() -> Result<()> {
log::info!("Starting installation of APK {}...", path.display());
device.install(&path)?;
}
DeviceCommands::Framebuffer { path } => device.framebuffer(&path)?,
DeviceCommands::Framebuffer { path } => {
device.framebuffer(&path)?;
log::info!("Successfully dumped framebuffer at path {path}");
}
}

Ok(())
Expand Down
14 changes: 5 additions & 9 deletions adb_client/src/device/adb_message_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,11 @@ impl<T: ADBMessageTransport> ADBMessageDevice<T> {
message: ADBTransportMessage,
) -> Result<ADBTransportMessage> {
self.transport.write_message(message)?;
let message = self.transport.read_message()?;
let received_command = message.header().command();
if received_command != MessageCommand::Okay {
return Err(RustADBError::ADBRequestFailed(format!(
"expected command OKAY after message, got {}",
received_command
)));
}
Ok(message)

self.transport.read_message().and_then(|message| {
message.assert_command(MessageCommand::Okay)?;
Ok(message)
})
}

pub(crate) fn recv_file<W: std::io::Write>(
Expand Down
20 changes: 7 additions & 13 deletions adb_client/src/device/adb_tcp_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{io::Read, net::SocketAddr};
use super::adb_message_device::ADBMessageDevice;
use super::models::MessageCommand;
use super::ADBTransportMessage;
use crate::{ADBDeviceExt, ADBMessageTransport, ADBTransport, Result, RustADBError, TcpTransport};
use crate::{ADBDeviceExt, ADBMessageTransport, ADBTransport, Result, TcpTransport};

/// Represent a device reached and available over USB.
#[derive(Debug)]
Expand Down Expand Up @@ -38,19 +38,13 @@ impl ADBTcpDevice {

self.get_transport_mut().write_message(message)?;

let message = self.get_transport_mut().read_message()?;
// At this point, we should have received a STLS command indicating that the device wants to upgrade connection with TLS
self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Stls))?;

// At this point, we should have received a STLS message
if message.header().command() != MessageCommand::Stls {
return Err(RustADBError::ADBRequestFailed(format!(
"Wrong command received {}",
message.header().command()
)));
};

let message = ADBTransportMessage::new(MessageCommand::Stls, 1, 0, &[]);

self.get_transport_mut().write_message(message)?;
self.get_transport_mut()
.write_message(ADBTransportMessage::new(MessageCommand::Stls, 1, 0, &[]))?;

// Upgrade TCP connection to TLS
self.get_transport_mut().upgrade_connection()?;
Expand Down
18 changes: 15 additions & 3 deletions adb_client/src/device/adb_transport_message.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};

use crate::RustADBError;
use crate::{Result, RustADBError};

use super::models::MessageCommand;

Expand Down Expand Up @@ -66,7 +66,7 @@ impl ADBTransportMessageHeader {
command_u32 ^ 0xFFFFFFFF
}

pub fn as_bytes(&self) -> Result<Vec<u8>, RustADBError> {
pub fn as_bytes(&self) -> Result<Vec<u8>> {
bincode::serialize(&self).map_err(|_e| RustADBError::ConversionError)
}
}
Expand All @@ -88,6 +88,18 @@ impl ADBTransportMessage {
&& ADBTransportMessageHeader::compute_crc32(&self.payload) == self.header.data_crc32
}

pub fn assert_command(&self, expected_command: MessageCommand) -> Result<()> {
let our_command = self.header().command();
if expected_command == our_command {
return Ok(());
}

Err(RustADBError::WrongResponseReceived(
our_command.to_string(),
expected_command.to_string(),
))
}

pub fn header(&self) -> &ADBTransportMessageHeader {
&self.header
}
Expand All @@ -104,7 +116,7 @@ impl ADBTransportMessage {
impl TryFrom<[u8; 24]> for ADBTransportMessageHeader {
type Error = RustADBError;

fn try_from(value: [u8; 24]) -> Result<Self, Self::Error> {
fn try_from(value: [u8; 24]) -> Result<Self> {
bincode::deserialize(&value).map_err(|_e| RustADBError::ConversionError)
}
}
43 changes: 16 additions & 27 deletions adb_client/src/device/adb_usb_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,14 @@ impl ADBUSBDevice {
self.get_transport_mut().write_message(message)?;

let message = self.get_transport_mut().read_message()?;
message.assert_command(MessageCommand::Auth)?;

// At this point, we should have received either:
// - an AUTH message with arg0 == 1
// - a CNXN message
let auth_message = match message.header().command() {
MessageCommand::Auth if message.header().arg0() == AUTH_TOKEN => message,
MessageCommand::Auth if message.header().arg0() != AUTH_TOKEN => {
return Err(RustADBError::ADBRequestFailed(
"Received AUTH message with type != 1".into(),
))
}
c => {
// At this point, we should have receive an AUTH message with arg0 == 1
let auth_message = match message.header().arg0() {
AUTH_TOKEN => message,
v => {
return Err(RustADBError::ADBRequestFailed(format!(
"Wrong command received {}",
c
"Received AUTH message with type != 1 ({v})"
)))
}
};
Expand Down Expand Up @@ -225,20 +218,16 @@ impl ADBUSBDevice {

let response = self
.get_transport_mut()
.read_message_with_timeout(Duration::from_secs(10))?;

match response.header().command() {
MessageCommand::Cnxn => log::info!(
"Authentication OK, device info {}",
String::from_utf8(response.into_payload())?
),
_ => {
return Err(RustADBError::ADBRequestFailed(format!(
"wrong response {}",
response.header().command()
)))
}
}
.read_message_with_timeout(Duration::from_secs(10))
.and_then(|message| {
message.assert_command(MessageCommand::Cnxn)?;
Ok(message)
})?;

log::info!(
"Authentication OK, device info {}",
String::from_utf8(response.into_payload())?
);

Ok(())
}
Expand Down
13 changes: 5 additions & 8 deletions adb_client/src/device/commands/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,10 @@ impl<T: ADBMessageTransport> ADBMessageDevice<T> {
v => return Err(RustADBError::UnimplementedFramebufferImageVersion(v)),
};

let message = self.get_transport_mut().read_message()?;
match message.header().command() {
MessageCommand::Clse => Ok(img),
c => Err(RustADBError::ADBRequestFailed(format!(
"Wrong command received {}",
c
))),
}
self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Clse))?;

Ok(img)
}
}
12 changes: 4 additions & 8 deletions adb_client/src/device/commands/reboot.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use crate::{
device::{adb_message_device::ADBMessageDevice, MessageCommand},
ADBMessageTransport, RebootType, Result, RustADBError,
ADBMessageTransport, RebootType, Result,
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn reboot(&mut self, reboot_type: RebootType) -> Result<()> {
self.open_session(format!("reboot:{}\0", reboot_type).as_bytes())?;

let message = self.get_transport_mut().read_message()?;

if message.header().command() != MessageCommand::Okay {
return Err(RustADBError::ADBShellNotSupported);
}

Ok(())
self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Okay))
}
}
23 changes: 11 additions & 12 deletions adb_client/src/device/message_writer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::io::{ErrorKind, Write};
use std::io::{Error, ErrorKind, Result, Write};

use crate::ADBMessageTransport;

Expand All @@ -24,26 +24,25 @@ impl<T: ADBMessageTransport> MessageWriter<T> {
}

impl<T: ADBMessageTransport> Write for MessageWriter<T> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let message =
ADBTransportMessage::new(MessageCommand::Write, self.local_id, self.remote_id, buf);
self.transport
.write_message(message)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?;

match self.transport.read_message() {
Ok(response) => match response.header().command() {
MessageCommand::Okay => Ok(buf.len()),
c => Err(std::io::Error::new(
ErrorKind::Other,
format!("wrong response received: {c}"),
)),
},
Err(e) => Err(std::io::Error::new(ErrorKind::Other, e)),
Ok(response) => {
response
.assert_command(MessageCommand::Okay)
.map_err(|e| Error::new(ErrorKind::Other, e))?;
Ok(buf.len())
}
Err(e) => Err(Error::new(ErrorKind::Other, e)),
}
}

fn flush(&mut self) -> std::io::Result<()> {
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
2 changes: 1 addition & 1 deletion adb_client/src/emulator_device/adb_emulator_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl TryFrom<ADBServerDevice> for ADBEmulatorDevice {
fn try_from(value: ADBServerDevice) -> std::result::Result<Self, Self::Error> {
ADBEmulatorDevice::new(
value.identifier.clone(),
Some(*value.get_transport().get_socketaddr().ip()),
Some(*value.transport.get_socketaddr().ip()),
)
}
}
Expand Down
6 changes: 2 additions & 4 deletions adb_client/src/emulator_device/commands/rotate.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use crate::{models::ADBEmulatorCommand, ADBEmulatorDevice, Result};
use crate::{emulator_device::ADBEmulatorCommand, ADBEmulatorDevice, Result};

impl ADBEmulatorDevice {
/// Send a SMS to this emulator with given content with given phone number
pub fn rotate(&mut self) -> Result<()> {
let transport = self.connect()?;
transport.send_command(ADBEmulatorCommand::Rotate)?;
Ok(())
self.connect()?.send_command(ADBEmulatorCommand::Rotate)
}
}
8 changes: 3 additions & 5 deletions adb_client/src/emulator_device/commands/sms.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use crate::{models::ADBEmulatorCommand, ADBEmulatorDevice, Result};
use crate::{emulator_device::ADBEmulatorCommand, ADBEmulatorDevice, Result};

impl ADBEmulatorDevice {
/// Send a SMS to this emulator with given content with given phone number
pub fn send_sms(&mut self, phone_number: &str, content: &str) -> Result<()> {
let transport = self.connect()?;
transport.send_command(ADBEmulatorCommand::Sms(
self.connect()?.send_command(ADBEmulatorCommand::Sms(
phone_number.to_string(),
content.to_string(),
))?;
Ok(())
))
}
}
2 changes: 2 additions & 0 deletions adb_client/src/emulator_device/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod adb_emulator_device;
mod commands;
mod models;
pub use adb_emulator_device::ADBEmulatorDevice;
pub(crate) use models::ADBEmulatorCommand;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt::Display;

pub(crate) enum ADBEmulatorCommand {
pub enum ADBEmulatorCommand {
Authenticate(String),
Sms(String, String),
Rotate,
Expand Down
2 changes: 2 additions & 0 deletions adb_client/src/emulator_device/models/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod adb_emulator_command;
pub use adb_emulator_command::ADBEmulatorCommand;
3 changes: 3 additions & 0 deletions adb_client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub enum RustADBError {
/// Indicates that ADB server responded an unknown response type.
#[error("Unknown response type {0}")]
UnknownResponseType(String),
/// Indicated that an unexpected command has been received
#[error("Wrong response command received: {0}. Expected {1}")]
WrongResponseReceived(String, String),
/// Indicates that ADB server responses an unknown device state.
#[error("Unknown device state {0}")]
UnknownDeviceState(String),
Expand Down
4 changes: 1 addition & 3 deletions adb_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ pub use device::{ADBTcpDevice, ADBUSBDevice};
pub use emulator_device::ADBEmulatorDevice;
pub use error::{Result, RustADBError};
pub use mdns::*;
pub use models::{
AdbStatResponse, AdbVersion, DeviceLong, DeviceShort, DeviceState, MDNSBackend, RebootType,
};
pub use models::{AdbStatResponse, RebootType};
pub use server::*;
pub use server_device::ADBServerDevice;
pub use transports::*;
Loading

0 comments on commit 9002ecc

Please sign in to comment.