1use crate::{
2 packet::{CheckedPacket, Kind},
3 parser::Parser,
4 Error,
5};
6
7use std::{
8 io::{prelude::*, BufReader},
9 mem,
10 net::{TcpListener, TcpStream, ToSocketAddrs},
11};
12
13pub const BUF_SIZE: usize = 8 * 1024;
14
15pub struct GdbServer<R, W>
16where
17 R: BufRead,
18 W: Write,
19{
20 pub reader: R,
21 pub writer: W,
22 parser: Parser,
23}
24
25impl GdbServer<BufReader<TcpStream>, TcpStream> {
26 pub fn listen<A>(addr: A) -> Result<Self, Error>
27 where
28 A: ToSocketAddrs,
29 {
30 let listener = TcpListener::bind(addr)?;
31
32 let (writer, _addr) = listener.accept()?;
33 let reader = BufReader::new(writer.try_clone()?);
34
35 Ok(Self::new(reader, writer))
36 }
37}
38impl<'a> GdbServer<&'a mut &'a [u8], Vec<u8>> {
39 pub fn tester(input: &'a mut &'a [u8]) -> Self {
40 Self::new(input, Vec::new())
41 }
42 pub fn response(&mut self) -> Vec<u8> {
43 mem::replace(&mut self.writer, Vec::new())
44 }
45}
46impl<R, W> GdbServer<R, W>
47where
48 R: BufRead,
49 W: Write,
50{
51 pub fn new(reader: R, writer: W) -> Self {
52 Self {
53 reader,
54 writer,
55 parser: Parser::default(),
56 }
57 }
58
59 pub fn next_packet(&mut self) -> Result<Option<CheckedPacket>, Error> {
60 loop {
61 let buf = self.reader.fill_buf()?;
62 if buf.is_empty() {
63 break Ok(None);
64 }
65
66 let (read, packet) = self.parser.feed(buf)?;
68 self.reader.consume(read);
69
70 if let Some(packet) = packet {
71 break Ok(match packet.kind {
72 Kind::Packet => match packet.check() {
73 Some(checked) => {
74 self.writer.write_all(&[b'+'])?;
75 Some(checked)
76 }
77 None => {
78 self.writer.write_all(&[b'-'])?;
79 continue; }
81 },
82 Kind::Notification => packet.check(),
84 });
85 }
86 }
87 }
88 pub fn dispatch(&mut self, packet: &CheckedPacket) -> Result<(), Error> {
91 loop {
92 packet.encode(&mut self.writer)?;
93 self.writer.flush()?;
94
95 let buf = self.reader.fill_buf()?;
99 match buf.first() {
100 Some(b'+') => {
101 self.reader.consume(1);
102 break;
103 },
104 Some(b'-') => {
105 self.reader.consume(1);
106 if packet.is_valid() {
107 continue;
110 } else {
111 return Err(Error::InvalidChecksum);
118 }
119 },
120 _ => break,
122 }
123 }
124 Ok(())
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::packet::UncheckedPacket;
132
133 #[test]
134 fn it_acknowledges_valid_packets() {
135 let mut input: &[u8] = b"$packet#78";
136 let mut tester = GdbServer::tester(&mut input);
137 assert_eq!(
138 tester.next_packet().unwrap(),
139 Some(CheckedPacket::from_data(Kind::Packet, b"packet".to_vec()))
140 );
141 assert_eq!(tester.response(), b"+");
142 }
143 #[test]
144 fn it_acknowledges_invalid_packets() {
145 let mut input: &[u8] = b"$packet#99";
146 let mut tester = GdbServer::tester(&mut input);
147 assert_eq!(tester.next_packet().unwrap(), None);
148 assert_eq!(tester.response(), b"-");
149 }
150 #[test]
151 fn it_ignores_garbage() {
152 let mut input: &[u8] =
153 b"<garbage here yada yaya> $packet#13 $packet#37 more garbage $GARBA#GE-- $packet#78";
154 let mut tester = GdbServer::tester(&mut input);
155 assert_eq!(
156 tester.next_packet().unwrap(),
157 Some(CheckedPacket::from_data(Kind::Packet, b"packet".to_vec()))
158 );
159 assert_eq!(tester.response(), b"---+");
160 }
161 #[test]
162 fn it_dispatches() {
163 let mut input: &[u8] = b"";
164 let mut tester = GdbServer::tester(&mut input);
165 tester.dispatch(&CheckedPacket::from_data(Kind::Packet, b"hOi!!".to_vec())).unwrap();
166 assert_eq!(tester.response(), b"$hOi!!#62");
167 }
168 #[test]
169 fn it_resends() {
170 let mut input: &[u8] = b"-+";
171 let mut tester = GdbServer::tester(&mut input);
172 tester.dispatch(&CheckedPacket::from_data(Kind::Packet, b"IMBATMAN".to_vec())).unwrap();
173 assert_eq!(tester.response(), b"$IMBATMAN#49$IMBATMAN#49");
174 }
175 #[test]
176 fn it_complains_when_the_user_lies() {
177 let mut input: &[u8] = b"-";
178 let mut tester = GdbServer::tester(&mut input);
179 let result = tester.dispatch(&CheckedPacket::assume_checked(UncheckedPacket {
180 kind: Kind::Packet,
181 data: b"This sentence is false. (dontthinkaboutitdontthinkaboutit)".to_vec(),
182 checksum: *b"FF",
183 }));
184 if let Err(Error::InvalidChecksum) = result {
185 } else {
186 panic!("Expected error InvalidChecksum, got {:?}", result);
187 }
188 assert_eq!(tester.response(), b"$This sentence is false. (dontthinkaboutitdontthinkaboutit)#FF".to_vec());
190 }
191}