ios_core/services/debugserver/
mod.rs1use semver::Version;
6use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
7
8pub const LEGACY_SERVICE_NAME: &str = "com.apple.debugserver";
9pub const SECURE_SERVICE_NAME: &str = "com.apple.debugserver.DVTSecureSocketProxy";
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct ParsedPacket {
13 pub payload: String,
14 pub consumed: usize,
15}
16
17#[derive(Debug, thiserror::Error)]
18pub enum DebugserverError {
19 #[error("IO error: {0}")]
20 Io(#[from] std::io::Error),
21 #[error("invalid debugserver payload")]
22 InvalidPayload,
23 #[error("invalid UTF-8 payload: {0}")]
24 Utf8(#[from] std::string::FromUtf8Error),
25}
26
27pub fn select_service_name(version: &Version) -> &'static str {
28 if version.major >= 15 {
29 SECURE_SERVICE_NAME
30 } else {
31 LEGACY_SERVICE_NAME
32 }
33}
34
35pub fn checksum(payload: &str) -> String {
36 format!(
37 "{:02x}",
38 payload
39 .bytes()
40 .fold(0u8, |acc, byte| acc.wrapping_add(byte))
41 )
42}
43
44pub fn format_packet(payload: &str) -> String {
45 format!("+${payload}#{}", checksum(payload))
46}
47
48pub fn parse_packet(data: &[u8]) -> Option<ParsedPacket> {
49 const PACKET_SUFFIX_LEN: usize = 3; let start = data.iter().position(|&b| b == b'$')?;
52 let end = data.iter().position(|&b| b == b'#')?;
53 if end < start {
54 return None;
55 }
56 if data.len() < end + PACKET_SUFFIX_LEN {
57 return None;
58 }
59
60 let payload = String::from_utf8(data[start + 1..end].to_vec()).ok()?;
61 Some(ParsedPacket {
62 payload,
63 consumed: end + PACKET_SUFFIX_LEN,
64 })
65}
66
67pub struct GdbRemoteClient<S> {
68 stream: S,
69 read_buf: Vec<u8>,
70}
71
72impl<S> GdbRemoteClient<S>
73where
74 S: AsyncRead + AsyncWrite + Unpin,
75{
76 pub fn new(stream: S) -> Self {
77 Self {
78 stream,
79 read_buf: Vec::with_capacity(4096),
80 }
81 }
82
83 pub fn into_inner(self) -> S {
84 self.stream
85 }
86
87 pub async fn send(&mut self, payload: &str) -> Result<(), DebugserverError> {
88 self.stream
89 .write_all(format_packet(payload).as_bytes())
90 .await?;
91 self.stream.flush().await?;
92 Ok(())
93 }
94
95 pub async fn recv(&mut self) -> Result<String, DebugserverError> {
96 let mut scratch = [0u8; 1024];
97 loop {
98 if let Some(packet) = parse_packet(&self.read_buf) {
99 self.read_buf.drain(..packet.consumed);
100 return Ok(packet.payload);
101 }
102
103 let read = self.stream.read(&mut scratch).await?;
104 if read == 0 {
105 return Err(DebugserverError::InvalidPayload);
106 }
107 self.read_buf.extend_from_slice(&scratch[..read]);
108 }
109 }
110
111 pub async fn request(&mut self, payload: &str) -> Result<String, DebugserverError> {
112 self.send(payload).await?;
113 self.recv().await
114 }
115}