rust_adb/adb_host/
mod.rs

1use crate::error::adb::AdbError;
2use std::io::{Read, Write};
3use std::net::TcpStream;
4use std::time::Duration;
5
6pub mod host_device_path;
7pub mod host_device_status;
8pub mod host_disconnect;
9pub mod host_kill;
10pub mod host_list_device;
11pub mod host_list_device_l;
12pub mod host_start;
13pub mod host_track_devices;
14pub mod host_transport;
15pub mod host_version;
16
17pub trait SyncHostCommand {
18    fn execute(&mut self) -> Result<SyncHostResponse, AdbError>;
19}
20
21pub trait AsyncHostCommand {
22    fn execute(&mut self) -> Result<AsyncHostResponse, AdbError>;
23}
24
25#[derive(Debug)]
26pub struct SyncHostResponse {
27    pub length: usize,
28    pub content: String,
29}
30
31pub struct AsyncHostResponse {
32    pub tcp_stream: TcpStream,
33}
34
35#[derive(Debug)]
36pub struct HostConnectionInfo {
37    pub host: String,
38    pub port: i32,
39    pub read_timeout: Option<Duration>,
40    pub write_timeout: Option<Duration>,
41}
42
43impl HostConnectionInfo {
44    pub fn new(host: &String, port: &i32) -> HostConnectionInfo {
45        HostConnectionInfo {
46            host: host.clone(),
47            port: port.clone(),
48            read_timeout: Option::from(Duration::from_millis(1000)),
49            write_timeout: Option::from(Duration::from_millis(1000)),
50        }
51    }
52}
53
54impl Clone for HostConnectionInfo {
55    fn clone(&self) -> Self {
56        HostConnectionInfo {
57            host: self.host.clone(),
58            port: self.port.clone(),
59            read_timeout: self.read_timeout.clone(),
60            write_timeout: self.write_timeout.clone(),
61        }
62    }
63}
64
65pub fn connect(connection_info: &HostConnectionInfo) -> Result<TcpStream, AdbError> {
66    let connection_str = format!("{}:{}", connection_info.host, connection_info.port);
67    let tcp_stream = match TcpStream::connect(connection_str.clone()) {
68        Ok(tcp_stream) => tcp_stream,
69        Err(error) => {
70            return Err(AdbError::TcpConnectError {
71                source: Box::new(error),
72            });
73        }
74    };
75    match tcp_stream.set_read_timeout(connection_info.read_timeout) {
76        Ok(_) => {}
77        Err(error) => {
78            return Err(AdbError::TcpReadError {
79                source: Box::new(error),
80            });
81        }
82    };
83    match tcp_stream.set_write_timeout(connection_info.write_timeout) {
84        Ok(_) => {}
85        Err(error) => {
86            return Err(AdbError::TcpReadError {
87                source: Box::new(error),
88            });
89        }
90    };
91    Ok(tcp_stream)
92}
93
94pub fn exec_command_sync(
95    mut tcp_stream: TcpStream, command: String,
96) -> Result<AsyncHostResponse, AdbError> {
97    write_command(&mut tcp_stream, &command)?;
98
99    let status = read_response_status(&mut tcp_stream)?;
100
101    if status == "OKAY" {
102        return Ok(AsyncHostResponse { tcp_stream });
103    }
104
105    if status == "FAIL" {
106        let length = read_response_length(&mut tcp_stream)?;
107
108        let content = read_response_content(&mut tcp_stream, length)?;
109        return Err(AdbError::ResponseStatusError { content });
110    }
111
112    Err(AdbError::ResponseStatusError {
113        content: String::from("unknown response status ") + &*status,
114    })
115}
116
117pub fn exec_command(
118    tcp_stream: &mut TcpStream, command: String,
119) -> Result<SyncHostResponse, AdbError> {
120    write_command(tcp_stream, &command)?;
121
122    let status = read_response_status(tcp_stream)?;
123
124    let length = read_response_length(tcp_stream)?;
125
126    let content = read_response_content(tcp_stream, length)?;
127
128    if status == "OKAY" {
129        return Ok(SyncHostResponse { length, content });
130    }
131    if status == "FAIL" {
132        return Err(AdbError::ResponseStatusError { content });
133    }
134    Err(AdbError::ResponseStatusError {
135        content: String::from("unknown response status ") + &*status,
136    })
137}
138
139pub fn write_command(tcp_stream: &mut TcpStream, command: &String) -> Result<(), AdbError> {
140    let full_command = add_command_length_prefix(command.clone());
141    match tcp_stream.write_all(full_command.as_ref()) {
142        Ok(_) => Ok(()),
143        Err(error) => Err(AdbError::TcpWriteError {
144            source: Box::new(error),
145        }),
146    }
147}
148
149pub fn read_response_content(
150    tcp_stream: &mut TcpStream, length: usize,
151) -> Result<String, AdbError> {
152    let mut response_content = vec![0; length];
153    match tcp_stream.read_exact(&mut response_content) {
154        Ok(_) => {}
155        Err(error) => {
156            return Err(AdbError::TcpReadError {
157                source: Box::new(error),
158            });
159        }
160    };
161
162    match String::from_utf8(Vec::from(response_content)) {
163        Ok(content_string) => Ok(content_string),
164        Err(error) => {
165            return Err(AdbError::ParseResponseError {
166                source: Box::new(error),
167            });
168        }
169    }
170}
171
172pub fn read_response_length(tcp_stream: &mut TcpStream) -> Result<usize, AdbError> {
173    let mut content_length = [0; 4];
174    match tcp_stream.read_exact(&mut content_length) {
175        Ok(_) => {}
176        Err(error) => {
177            return Err(AdbError::TcpReadError {
178                source: Box::new(error),
179            });
180        }
181    }
182    match String::from_utf8(Vec::from(content_length)) {
183        Ok(response) => match usize::from_str_radix(&*response, 16) {
184            Ok(size) => Ok(size),
185            Err(error) => Err(AdbError::ParseResponseError {
186                source: Box::new(error),
187            }),
188        },
189        Err(error) => {
190            return Err(AdbError::ParseResponseError {
191                source: Box::new(error),
192            });
193        }
194    }
195}
196
197pub fn read_response_status(tcp_stream: &mut TcpStream) -> Result<String, AdbError> {
198    let mut is_ok_buffer = [0; 4];
199    match tcp_stream.read_exact(&mut is_ok_buffer) {
200        Ok(_) => {}
201        Err(error) => {
202            return Err(AdbError::TcpReadError {
203                source: Box::new(error),
204            });
205        }
206    }
207    match String::from_utf8(Vec::from(is_ok_buffer)) {
208        Ok(response_status) => Ok(response_status),
209        Err(error) => Err(AdbError::ParseResponseError {
210            source: Box::new(error),
211        }),
212    }
213}
214
215pub fn add_command_length_prefix(command_body: String) -> String {
216    let trim_command = command_body.trim();
217    let trim_command_length = format!("{:04X}", trim_command.len());
218    trim_command_length + trim_command
219}