1#![recursion_limit = "256"]
9
10mod debugger;
11mod host_bridge;
12mod protocol;
13
14use std::io::{self, BufRead, Read, Write};
15use std::sync::atomic::AtomicI64;
16use std::sync::mpsc::{channel, Sender};
17use std::sync::{Arc, Mutex};
18use std::thread;
19
20use debugger::Debugger;
21use host_bridge::{deliver_reply, pending_map_new, DapHostBridge, DapHostCallReply, PendingMap};
22use protocol::{DapMessage, DapResponse};
23
24const MAX_DAP_FRAME_BYTES: usize = 16 * 1024 * 1024;
25
26pub fn run() {
31 harn_vm::stdlib::force_link();
34 harn_parser::install_builtin_signatures(harn_vm::stdlib::all_builtin_signatures());
38
39 let seq = Arc::new(AtomicI64::new(1_000_000));
43
44 let stdout: Arc<Mutex<Box<dyn Write + Send>>> = Arc::new(Mutex::new(Box::new(io::stdout())));
47 let pending: PendingMap = pending_map_new();
48
49 let (request_tx, request_rx) = channel::<DapMessage>();
52 let pending_for_reader = Arc::clone(&pending);
53 thread::spawn(move || stdin_reader(request_tx, pending_for_reader));
54
55 let bridge = Arc::new(DapHostBridge::new(
56 Arc::clone(&seq),
57 Arc::clone(&stdout),
58 Arc::clone(&pending),
59 ));
60
61 let mut debugger = Debugger::new();
62 debugger.attach_host_bridge(Arc::clone(&bridge));
63
64 use std::sync::mpsc::TryRecvError;
79 loop {
80 loop {
82 match request_rx.try_recv() {
83 Ok(msg) => {
84 let responses = debugger.handle_message(msg);
85 for response in responses {
86 send_response(&stdout, &response);
87 }
88 }
89 Err(TryRecvError::Empty) => break,
90 Err(TryRecvError::Disconnected) => return,
91 }
92 }
93 if debugger.is_running() {
95 let responses = debugger.step_running_vm();
96 for response in responses {
97 send_response(&stdout, &response);
98 }
99 } else {
100 match request_rx.recv() {
101 Ok(msg) => {
102 let responses = debugger.handle_message(msg);
103 for response in responses {
104 send_response(&stdout, &response);
105 }
106 }
107 Err(_) => return,
108 }
109 }
110 }
111}
112
113fn stdin_reader(request_tx: Sender<DapMessage>, pending: PendingMap) {
118 let stdin = io::stdin();
119 let mut reader = io::BufReader::new(stdin.lock());
120
121 loop {
122 let content_length = match read_content_length(&mut reader) {
123 Ok(Some(content_length)) => content_length,
124 Ok(None) => break,
125 Err(error) => {
126 eprintln!("Failed to read DAP frame header: {error}");
127 break;
128 }
129 };
130 if content_length == 0 {
131 continue;
132 }
133 let mut body_bytes = vec![0u8; content_length];
134 if reader.read_exact(&mut body_bytes).is_err() {
135 break;
136 }
137 let body = String::from_utf8_lossy(&body_bytes);
138
139 match serde_json::from_str::<DapMessage>(&body) {
140 Ok(msg) => {
141 if msg.msg_type == "response" {
142 if let Some(request_seq) = msg.request_seq {
143 deliver_reply(
144 &pending,
145 request_seq,
146 DapHostCallReply {
147 success: msg.success.unwrap_or(false),
148 body: msg.body,
149 message: msg.message,
150 },
151 );
152 continue;
153 }
154 }
155 if request_tx.send(msg).is_err() {
156 break;
157 }
158 }
159 Err(e) => {
160 eprintln!("Failed to parse DAP message: {e}");
161 eprintln!("Body: {body}");
162 }
163 }
164 }
165}
166
167fn read_content_length<R: BufRead>(reader: &mut R) -> io::Result<Option<usize>> {
168 let mut content_length = 0usize;
169 loop {
170 let mut line = String::new();
171 match reader.read_line(&mut line) {
172 Ok(0) => return Ok(None),
173 Ok(_) => {
174 let trimmed = line.trim();
175 if trimmed.is_empty() {
176 if content_length > 0 {
177 return Ok(Some(content_length));
178 }
179 continue;
180 }
181 if let Some((name, val)) = trimmed.split_once(':') {
182 if !name.eq_ignore_ascii_case("Content-Length") {
183 continue;
184 }
185 if let Ok(len) = val.trim().parse::<usize>() {
186 content_length = bounded_dap_content_length(len)?;
187 }
188 }
189 }
190 Err(error) => return Err(error),
191 }
192 }
193}
194
195fn bounded_dap_content_length(content_length: usize) -> io::Result<usize> {
196 if content_length > MAX_DAP_FRAME_BYTES {
197 Err(io::Error::new(
198 io::ErrorKind::InvalidData,
199 format!(
200 "DAP Content-Length {content_length} exceeds limit {MAX_DAP_FRAME_BYTES} bytes"
201 ),
202 ))
203 } else {
204 Ok(content_length)
205 }
206}
207
208fn send_response(stdout: &Arc<Mutex<Box<dyn Write + Send>>>, response: &DapResponse) {
209 let body = match serde_json::to_string(response) {
210 Ok(b) => b,
211 Err(_) => return,
212 };
213 let header = format!("Content-Length: {}\r\n\r\n", body.len());
214 let mut guard = match stdout.lock() {
215 Ok(g) => g,
216 Err(_) => return,
217 };
218 let _ = guard.write_all(header.as_bytes());
219 let _ = guard.write_all(body.as_bytes());
220 let _ = guard.flush();
221}
222
223#[cfg(test)]
224mod tests {
225 use super::*;
226
227 #[test]
228 fn read_content_length_accepts_case_insensitive_header() {
229 let mut reader = io::BufReader::new(b"content-length: 12\r\n\r\n".as_slice());
230 assert_eq!(
231 read_content_length(&mut reader).expect("content length"),
232 Some(12)
233 );
234 }
235
236 #[test]
237 fn read_content_length_rejects_oversized_frame() {
238 let header = format!("Content-Length: {}\r\n\r\n", MAX_DAP_FRAME_BYTES + 1);
239 let mut reader = io::BufReader::new(header.as_bytes());
240 let error = read_content_length(&mut reader).expect_err("oversized frame");
241 assert_eq!(error.kind(), io::ErrorKind::InvalidData);
242 }
243}