torrust_tracker/servers/udp/server/
receiver.rs

1use std::cell::RefCell;
2use std::net::SocketAddr;
3use std::pin::Pin;
4use std::sync::Arc;
5use std::task::{Context, Poll};
6
7use futures::Stream;
8
9use super::bound_socket::BoundSocket;
10use super::RawRequest;
11use crate::shared::bit_torrent::tracker::udp::MAX_PACKET_SIZE;
12
13pub struct Receiver {
14    pub socket: Arc<BoundSocket>,
15    data: RefCell<[u8; MAX_PACKET_SIZE]>,
16}
17
18impl Receiver {
19    #[must_use]
20    pub fn new(bound_socket: Arc<BoundSocket>) -> Self {
21        Receiver {
22            socket: bound_socket,
23            data: RefCell::new([0; MAX_PACKET_SIZE]),
24        }
25    }
26
27    pub fn bound_socket_address(&self) -> SocketAddr {
28        self.socket.address()
29    }
30}
31
32impl Stream for Receiver {
33    type Item = std::io::Result<RawRequest>;
34
35    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
36        let mut buf = *self.data.borrow_mut();
37        let mut buf = tokio::io::ReadBuf::new(&mut buf);
38
39        let Poll::Ready(ready) = self.socket.poll_recv_from(cx, &mut buf) else {
40            return Poll::Pending;
41        };
42
43        let res = match ready {
44            Ok(from) => {
45                let payload = buf.filled().to_vec();
46                let request = RawRequest { payload, from };
47                Some(Ok(request))
48            }
49            Err(err) => Some(Err(err)),
50        };
51
52        Poll::Ready(res)
53    }
54}