Skip to main content

dap/
server.rs

1use std::{
2    fmt::Debug,
3    io::{BufRead, BufReader, BufWriter, Read, Write},
4    sync::{Arc, Mutex},
5};
6
7use serde_json;
8
9use crate::{
10    base_message::{BaseMessage, Sendable},
11    errors::{DeserializationError, ServerError},
12    events::Event,
13    requests::Request,
14    responses::Response,
15    reverse_requests::ReverseRequest,
16};
17
18#[derive(Debug)]
19enum ServerState {
20    /// Expecting a header
21    Header,
22    /// Expecting content
23    Content,
24}
25
26/// Handles message encoding and decoding of messages.
27///
28/// The `Server` is responsible for reading the incoming bytestream and constructing deserialized
29/// requests from it, as well as constructing and serializing outgoing messages.
30pub struct Server<R: Read, W: Write> {
31    input_buffer: BufReader<R>,
32
33    /// A sharable `ServerOutput` object for sending messages and events from
34    /// other threads.
35    pub output: Arc<Mutex<ServerOutput<W>>>,
36}
37
38/// Handles emission of messages through the connection.
39///
40/// `ServerOutput` is responsible for sending messages to the connection.
41/// It's only accessible through a mutex that can be shared with other
42/// threads. This makes it possible to send e.g. events while the server is
43/// blocked polling requests.
44pub struct ServerOutput<W: Write> {
45    output_buffer: BufWriter<W>,
46    sequence_number: i64,
47}
48
49/// The largest `Content-Length` this server will act on.
50///
51/// The header is attacker-controlled and feeds two allocations directly, so an unbounded value
52/// ends the process rather than the request. DAP payloads carry source text and variable dumps,
53/// not bulk data, so this ceiling is far above any legitimate message.
54pub const MAX_CONTENT_LENGTH: usize = 16 * 1024 * 1024;
55
56impl<R: Read, W: Write> Server<R, W> {
57    /// Construct a new Server using the given input and output streams.
58    pub fn new(input: BufReader<R>, output: BufWriter<W>) -> Self {
59        let server_output = Arc::new(Mutex::new(ServerOutput {
60            output_buffer: output,
61            sequence_number: 0,
62        }));
63
64        Self {
65            input_buffer: input,
66            output: server_output,
67        }
68    }
69
70    /// Wait for a request from the development tool
71    ///
72    /// This will start reading the `input` buffer that is passed to it and will try to interpret
73    /// the incoming bytes according to the DAP protocol.
74    pub fn poll_request(&mut self) -> Result<Option<Request>, ServerError> {
75        let mut state = ServerState::Header;
76        let mut buffer = String::new();
77        let mut content_length: usize = 0;
78
79        loop {
80            match self.input_buffer.read_line(&mut buffer) {
81                Ok(read_size) => {
82                    if read_size == 0 {
83                        break Ok(None);
84                    }
85                    match state {
86                        ServerState::Header => {
87                            let parts: Vec<&str> = buffer.trim_end().split(':').collect();
88                            if parts.len() == 2 {
89                                match parts[0] {
90                                    "Content-Length" => {
91                                        content_length = match parts[1].trim().parse() {
92                                            Ok(val) if val <= MAX_CONTENT_LENGTH => val,
93                                            Ok(val) => {
94                                                return Err(ServerError::ProtocolError {
95                                                    reason: format!(
96                                                        "content length {val} exceeds the maximum \
97                                                         of {MAX_CONTENT_LENGTH}"
98                                                    ),
99                                                    line: buffer,
100                                                });
101                                            }
102                                            Err(_) => {
103                                                return Err(ServerError::HeaderParseError {
104                                                    line: buffer,
105                                                });
106                                            }
107                                        };
108                                        buffer.clear();
109                                        buffer.reserve(content_length);
110                                        state = ServerState::Content;
111                                    }
112                                    other => {
113                                        return Err(ServerError::UnknownHeader {
114                                            header: other.to_string(),
115                                        });
116                                    }
117                                }
118                            } else {
119                                return Err(ServerError::HeaderParseError { line: buffer });
120                            }
121                        }
122                        ServerState::Content => {
123                            buffer.clear();
124                            let mut content = vec![0; content_length];
125                            self.input_buffer
126                                .read_exact(content.as_mut_slice())
127                                .map_err(ServerError::IoError)?;
128
129                            let content = std::str::from_utf8(content.as_slice()).map_err(|e| {
130                                ServerError::ParseError(DeserializationError::DecodingError(e))
131                            })?;
132                            eprintln!(
133                                "[DAP-RS] Received content ({content_length} bytes): {content}"
134                            );
135                            // Deserialize seq and command separately to avoid serde
136                            // #[serde(flatten)] issues with newer serde versions (>=1.0.171)
137                            // where flatten + adjacently-tagged enums can fail.
138                            let raw: serde_json::Value =
139                                serde_json::from_str(content).map_err(|e| {
140                                    eprintln!("[DAP-RS] JSON parse error: {e}");
141                                    ServerError::ParseError(DeserializationError::SerdeError(e))
142                                })?;
143                            let seq = raw.get("seq").and_then(|v| v.as_i64()).ok_or_else(|| {
144                                eprintln!("[DAP-RS] Missing seq field");
145                                ServerError::ParseError(DeserializationError::SerdeError(
146                                    serde_json::from_str::<()>("\"missing seq field\"")
147                                        .unwrap_err(),
148                                ))
149                            })?;
150                            // Handle the conflict between unit variants (e.g. ConfigurationDone)
151                            // and struct variants with all-optional fields (e.g. Launch):
152                            // - Unit variants fail with "arguments": {} ("invalid type: map, expected unit variant")
153                            // - Struct variants fail without "arguments" ("missing field `arguments`")
154                            // When arguments is an empty object, try without it first (unit variant),
155                            // then fall back to keeping it (struct variant with optional fields).
156                            let command: crate::requests::Command = if raw
157                                .get("arguments")
158                                .and_then(|v| v.as_object())
159                                .is_some_and(|m| m.is_empty())
160                            {
161                                let mut without_args = raw.clone();
162                                without_args.as_object_mut().unwrap().remove("arguments");
163                                match serde_json::from_value::<crate::requests::Command>(
164                                    without_args,
165                                ) {
166                                    Ok(cmd) => cmd,
167                                    Err(_) => serde_json::from_value(raw.clone()).map_err(|e| {
168                                        eprintln!("[DAP-RS] Command deserialize error: {e}");
169                                        ServerError::ParseError(DeserializationError::SerdeError(e))
170                                    })?,
171                                }
172                            } else {
173                                serde_json::from_value(raw.clone()).map_err(|e| {
174                                    eprintln!("[DAP-RS] Command deserialize error: {e}");
175                                    ServerError::ParseError(DeserializationError::SerdeError(e))
176                                })?
177                            };
178                            eprintln!("[DAP-RS] Successfully parsed request seq={seq}");
179                            let request = Request { seq, command };
180                            return Ok(Some(request));
181                        }
182                    }
183                }
184                Err(e) => return Err(ServerError::IoError(e)),
185            }
186        }
187    }
188
189    pub fn send(&mut self, body: Sendable) -> Result<(), ServerError> {
190        let mut output = self.output.lock().map_err(|_| ServerError::OutputLockError)?;
191        output.send(body)
192    }
193
194    pub fn respond(&mut self, response: Response) -> Result<(), ServerError> {
195        self.send(Sendable::Response(response))
196    }
197
198    pub fn send_event(&mut self, event: Event) -> Result<(), ServerError> {
199        self.send(Sendable::Event(event))
200    }
201
202    pub fn send_reverse_request(&mut self, request: ReverseRequest) -> Result<(), ServerError> {
203        self.send(Sendable::ReverseRequest(request))
204    }
205}
206
207impl<W: Write> ServerOutput<W> {
208    pub fn send(&mut self, body: Sendable) -> Result<(), ServerError> {
209        self.sequence_number += 1;
210
211        let message = BaseMessage {
212            seq: self.sequence_number,
213            message: body,
214        };
215
216        let resp_json = serde_json::to_string(&message).map_err(ServerError::SerializationError)?;
217        write!(self.output_buffer, "Content-Length: {}\r\n\r\n", resp_json.len())
218            .map_err(ServerError::IoError)?;
219
220        write!(self.output_buffer, "{}\r\n", resp_json).map_err(ServerError::IoError)?;
221        self.output_buffer.flush().map_err(ServerError::IoError)?;
222        Ok(())
223    }
224
225    pub fn respond(&mut self, response: Response) -> Result<(), ServerError> {
226        self.send(Sendable::Response(response))
227    }
228
229    pub fn send_event(&mut self, event: Event) -> Result<(), ServerError> {
230        self.send(Sendable::Event(event))
231    }
232
233    pub fn send_reverse_request(&mut self, request: ReverseRequest) -> Result<(), ServerError> {
234        self.send(Sendable::ReverseRequest(request))
235    }
236}
237
238#[cfg(test)]
239mod tests {
240
241    use std::io::Cursor;
242
243    use serde_json::Value;
244
245    use super::*;
246    use crate::requests::{AttachOrLaunchArguments, Command, RestartArguments};
247
248    fn simulate_poll_request(input: &str) -> Request {
249        let mut server_in = Cursor::new(input.as_bytes().to_vec());
250        let server_out = Vec::new();
251        let mut server = Server::new(BufReader::new(&mut server_in), BufWriter::new(server_out));
252
253        server.poll_request().unwrap().unwrap()
254    }
255
256    #[test]
257    fn test_server_init_request() {
258        let req = simulate_poll_request(
259            "Content-Length: 155\r\n\r\n{\"seq\": 152,\"type\": \"request\",\"command\": \
260             \"initialize\",\"arguments\": {\"adapterID\": \
261             \"0001e357-72c7-4f03-ae8f-c5b54bd8dabf\", \"clientName\": \"Some Cool Editor\"}}",
262        );
263
264        assert_eq!(req.seq, 152);
265        assert!(matches!(req.command, Command::Initialize { .. }));
266    }
267
268    #[test]
269    fn test_server_restart_request() {
270        let req = simulate_poll_request(
271            "Content-Length: 67\r\n\r\n{\"seq\": 152,\"type\": \"request\",\"command\": \
272             \"restart\",\"arguments\": {}}",
273        );
274
275        assert!(matches!(
276            req.command,
277            Command::Restart(None) | Command::Restart(Some(RestartArguments { arguments: None }))
278        ));
279
280        // Restarting a launch request
281        let req = simulate_poll_request(
282            "Content-Length: 96\r\n\r\n{\"seq\": 152,\"type\": \"request\",\"command\": \
283             \"restart\",\"arguments\": {\"arguments\": {\"noDebug\":true}}}",
284        );
285        assert!(matches!(
286            req.command,
287            Command::Restart(Some(RestartArguments {
288                arguments: Some(AttachOrLaunchArguments {
289                    no_debug: Some(_),
290                    ..
291                })
292            }))
293        ));
294
295        // Restarting a launch or attach request
296        let req = simulate_poll_request(
297            "Content-Length: 98\r\n\r\n{\"seq\": 152,\"type\": \"request\",\"command\": \
298             \"restart\",\"arguments\": {\"arguments\": {\"__restart\":true}}}",
299        );
300        assert!(matches!(
301            req.command,
302            Command::Restart(Some(RestartArguments {
303                arguments: Some(AttachOrLaunchArguments {
304                    restart_data: Some(Value::Bool(true)),
305                    ..
306                })
307            }))
308        ));
309    }
310}