1pub mod proto;
12mod reads;
13
14use crate::{
15 errors::{APIError, CatBridgeError, NetworkError},
16 fsemul::{
17 atapi::{proto::ChunkATAPIEmulatorCodec, reads::handle_read_dlf},
18 HostFilesystem,
19 },
20};
21use bytes::{BufMut, Bytes, BytesMut};
22use futures::{SinkExt, StreamExt};
23use local_ip_address::local_ip;
24use std::net::{IpAddr, Ipv4Addr, SocketAddrV4};
25use tokio::{
26 net::{TcpListener, TcpStream},
27 task::Builder as TaskBuilder,
28};
29use tokio_util::codec::Framed;
30use tracing::{debug, error, error_span, Instrument};
31
32pub const DEFAULT_ATAPI_PORT: u16 = 7974_u16;
34
35#[derive(Debug)]
37pub struct AtapiServer<'fs> {
38 bound_address: SocketAddrV4,
40 host_filesystem: &'fs HostFilesystem,
44 server: TcpListener,
46}
47
48impl<'fs> AtapiServer<'fs> {
49 pub async fn new(
55 host_filesystem: &'fs HostFilesystem,
56 address: Option<Ipv4Addr>,
57 port: Option<u16>,
58 ) -> Result<Self, CatBridgeError> {
59 let Some(ip) = address.or_else(|| {
60 local_ip().ok().map(|ip| match ip {
63 IpAddr::V4(v4) => v4,
64 IpAddr::V6(_v6) => unreachable!(),
65 })
66 }) else {
67 return Err(APIError::NoHostIpFound.into());
68 };
69
70 let bound_address = SocketAddrV4::new(ip, port.unwrap_or(DEFAULT_ATAPI_PORT));
71 let server = TcpListener::bind(bound_address)
72 .await
73 .map_err(NetworkError::IO)?;
74
75 Ok(Self {
76 bound_address,
77 host_filesystem,
78 server,
79 })
80 }
81
82 pub async fn serve(self) {
94 let host_filesystem = self.host_filesystem;
95
96 loop {
97 match self.server.accept().await {
98 Ok((stream, address)) => {
99 let client = address;
100 let bound = self.bound_address;
101
102 let result = Self::serve_connection(host_filesystem, stream)
103 .instrument(error_span!(
104 "cat_dev::fsemul::atapi::serve_connection",
105 server.address = %bound,
106 client.address = %client,
107 ))
108 .await;
109
110 if let Err(cause) = result {
111 error!(
112 ?cause,
113 server.address = %bound,
114 client.address = %client,
115 "Failed to actually handle packets from client connection",
116 );
117 }
118 }
119 Err(cause) => {
120 error!(
121 ?cause,
122 server.address = %self.bound_address,
123 "Failed to accept ATAPI Connection from client, cannot serve itself.",
124 );
125 }
126 }
127 }
128 }
129
130 async fn serve_connection(
133 host_filesystem: &'fs HostFilesystem,
134 connection: TcpStream,
135 ) -> Result<(), CatBridgeError> {
136 connection.set_nodelay(true).map_err(NetworkError::IO)?;
137 let (mut sink, mut stream) = Framed::new(connection, ChunkATAPIEmulatorCodec).split();
138
139 loop {
140 while let Some(result) = stream.next().await {
141 let packet = result.map_err(NetworkError::IO)?.freeze();
142
143 match &packet[..2] {
144 [0x3, _] => {
145 debug!("Would have sent 32 bytes of various descriptions back... not sure which...");
146 }
147 [0x12, _] => {
148 debug!("Would have sent 96 bytes of various descriptions back... not sure which...");
149 }
150 [0xCF, 0x80] => {
151 debug!("ATAPI Event packet sent!");
152 }
153 [0xF0, _] => {
154 debug!("ATAPI 0xF0 called");
155 sink.send(Bytes::from(vec![0x0; 4]))
156 .await
157 .map_err(NetworkError::IO)?;
158 }
159 [0xF1, 0x00 | 0x02] => {
160 debug!("ATAPI 0xF1, 0x0 | 0x02 random data called");
161 sink.send(Bytes::from(vec![0x69; 32]))
163 .await
164 .map_err(NetworkError::IO)?;
165 }
166 [0xF1, 0x01 | 0x03] => {
167 debug!("Unknown 0xF1 packet, doesn't do anything on the network...");
168 }
169 [0xF2, _] => {
170 debug!("Got unknown 0xF2 packet: [{packet:02X?}]");
171 }
172 [0xF3, 0x00] => {
173 handle_read_dlf(packet, host_filesystem, &mut sink).await?;
174 }
175 [0xF3, 0x01] => {
176 let mut data = BytesMut::with_capacity(32);
177 data.extend_from_slice(b"PC SATA EMUL");
178 data.extend_from_slice(&[0_u8; 20]);
179 sink.send(data.freeze()).await.map_err(NetworkError::IO)?;
180 debug!("Sent `PC SATA EMUL` header!");
181 }
182 [0xF3, 0x02 | 0x03] | [0xF5 | 0xF7, _] => {
183 sink.send(Bytes::from(vec![0x0; 32]))
184 .await
185 .map_err(NetworkError::IO)?;
186 debug!("Sent empty 32 bytes!");
187 }
188 [0xF6, _] => {
189 if packet[1] & 3 != 0 {
190 debug!("F6 second byte & 3 != 0, not sending reply!");
191 } else {
192 let mut data = BytesMut::with_capacity(4);
193 data.put_u32_le(1);
194 sink.send(data.freeze()).await.map_err(NetworkError::IO)?;
195 debug!("Sent F6 reply!");
196 }
197 }
198 _ => {
199 debug!("Blackhole-ing: [{packet:02X?}]");
200 }
201 }
202 }
203 }
204 }
205}
206
207impl AtapiServer<'static> {
208 pub async fn serve_concurrently(self) {
215 let host_filesystem: &'static HostFilesystem = self.host_filesystem;
216
217 loop {
218 match self.server.accept().await {
219 Ok((stream, address)) => {
220 let client = address;
221 let bound = self.bound_address;
222 let spawn_result = TaskBuilder::new()
223 .name("cat_dev::fsemul::atapi::serve_client_connection_concurrently")
224 .spawn(async move {
225 let result =
226 Self::serve_connection_concurrently(host_filesystem, stream)
227 .instrument(error_span!(
228 "cat_dev::fsemul::atapi::serve_connection_concurrently",
229 server.address = %bound,
230 client.address = %client,
231 ))
232 .await;
233
234 if let Err(cause) = result {
235 error!(
236 ?cause,
237 server.address = %bound,
238 client.address = %client,
239 "Failed to actually handle packets from client connection",
240 );
241 }
242 });
243
244 if let Err(cause) = spawn_result {
245 error!(
246 ?cause,
247 server.address = %self.bound_address,
248 client.address = %address,
249 "Failed to spawn handler for ATAPI Connection, cannot serve task.",
250 );
251 }
252 }
253 Err(cause) => {
254 error!(
255 ?cause,
256 server.address = %self.bound_address,
257 "Failed to accept ATAPI Connection from client, cannot serve itself.",
258 );
259 }
260 }
261 }
262 }
263
264 async fn serve_connection_concurrently(
265 host_filesystem: &'static HostFilesystem,
266 connection: TcpStream,
267 ) -> Result<(), CatBridgeError> {
268 connection.set_nodelay(true).map_err(NetworkError::IO)?;
269 let (mut sink, mut stream) = Framed::new(connection, ChunkATAPIEmulatorCodec).split();
270
271 loop {
272 while let Some(result) = stream.next().await {
273 let packet = result.map_err(NetworkError::IO)?.freeze();
274
275 match &packet[..2] {
276 [0x3, _] => {
277 debug!("Would have sent 32 bytes of various descriptions back... not sure which...");
278 }
279 [0x12, _] => {
280 debug!("Would have sent 96 bytes of various descriptions back... not sure which...");
281 }
282 [0xCF, 0x80] => {
283 debug!("ATAPI Event packet sent!");
284 }
285 [0xF0, _] => {
286 sink.send(Bytes::from(vec![0x0; 4]))
287 .await
288 .map_err(NetworkError::IO)?;
289 }
290 [0xF1, 0x00 | 0x02] => {
291 sink.send(Bytes::from(vec![0x69; 32]))
293 .await
294 .map_err(NetworkError::IO)?;
295 }
296 [0xF1, 0x01 | 0x03] => {
297 debug!("Unknown 0xF1 packet, doesn't do anything on the network...");
298 }
299 [0xF2, _] => {
300 debug!("Got unknown 0xF2 packet: [{packet:02X?}]");
301 }
302 [0xF3, 0x00] => {
303 handle_read_dlf(packet, host_filesystem, &mut sink).await?;
304 }
305 [0xF3, 0x01] => {
306 let mut data = BytesMut::with_capacity(32);
307 data.extend_from_slice(b"PC SATA EMUL");
308 data.extend_from_slice(&[0_u8; 20]);
309 sink.send(data.freeze()).await.map_err(NetworkError::IO)?;
310 debug!("Sent `PC SATA EMUL` header!");
311 }
312 [0xF3, 0x02 | 0x03] | [0xF5 | 0xF7, _] => {
313 sink.send(Bytes::from(vec![0x0; 32]))
314 .await
315 .map_err(NetworkError::IO)?;
316 debug!("Sent empty 32 bytes!");
317 }
318 [0xF6, _] => {
319 if packet[1] & 3 != 0 {
320 debug!("F6 second byte & 3 != 0, not sending reply!");
321 } else {
322 let mut data = BytesMut::with_capacity(4);
323 data.put_u32_le(1);
324 sink.send(data.freeze()).await.map_err(NetworkError::IO)?;
325 debug!("Sent F6 reply!");
326 }
327 }
328 _ => {}
329 }
330 }
331 }
332 }
333}