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}