1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use core::convert::TryInto;

use super::DataService;
use super::{
    socket::{Error as SocketError, SocketHandle, UdpSocket},
    Error, EGRESS_CHUNK_SIZE,
};
use crate::command::ip_transport_layer::{
    types::SocketProtocol, CloseSocket, CreateSocket, PrepareUDPSendToDataBinary,
    UDPSendToDataBinary,
};
use embedded_nal::{SocketAddr, UdpClientStack};
use embedded_time::{
    duration::{Generic, Milliseconds},
    Clock,
};

impl<'a, C, CLK, const N: usize, const L: usize> UdpClientStack for DataService<'a, C, CLK, N, L>
where
    C: atat::AtatClient,
    CLK: Clock,
    Generic<CLK::T>: TryInto<Milliseconds>,
{
    type Error = Error;

    // Only return a SocketHandle to reference into the SocketSet owned by the GsmClient,
    // as the Socket object itself provides no value without accessing it though the client.
    type UdpSocket = SocketHandle;

    /// Open a new UDP socket to the given address and port. UDP is connectionless,
    /// so unlike `TcpStack` no `connect()` is required.
    fn socket(&mut self) -> Result<Self::UdpSocket, Self::Error> {
        if self.sockets.len() >= self.sockets.capacity() {
            if let Ok(ts) = self.network.status.timer.try_now() {
                // Check if there are any sockets closed by remote, and close it
                // if it has exceeded its timeout, in order to recycle it.
                if self.sockets.recycle(&ts) {
                    return Err(Error::Socket(SocketError::SocketSetFull));
                }
            } else {
                return Err(Error::Socket(SocketError::SocketSetFull));
            }
        }

        let socket_resp = self.network.send_internal(
            &CreateSocket {
                protocol: SocketProtocol::UDP,
                local_port: None,
            },
            false,
        )?;

        Ok(self.sockets.add(UdpSocket::new(socket_resp.socket.0))?)
    }

    fn connect(
        &mut self,
        socket: &mut Self::UdpSocket,
        remote: SocketAddr,
    ) -> Result<(), Self::Error> {
        let mut udp = self
            .sockets
            .get::<UdpSocket<CLK, L>>(*socket)
            .map_err(Self::Error::from)?;
        udp.bind(remote).map_err(Self::Error::from)?;
        Ok(())
    }

    /// Send a datagram to the remote host.
    fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
        let udp = self
            .sockets
            .get::<UdpSocket<CLK, L>>(*socket)
            .map_err(Self::Error::from)?;

        if !udp.is_open() {
            return Err(Error::SocketClosed.into());
        }

        for chunk in buffer.chunks(EGRESS_CHUNK_SIZE) {
            defmt::trace!("Sending: {} bytes", chunk.len());
            self.network
                .send_internal(
                    &PrepareUDPSendToDataBinary {
                        socket: *socket,
                        remote_addr: udp.endpoint.ip(),
                        remote_port: udp.endpoint.port(),
                        length: chunk.len(),
                    },
                    false,
                )
                .map_err(Self::Error::from)?;

            let response = self
                .network
                .send_internal(
                    &UDPSendToDataBinary {
                        data: serde_bytes::Bytes::new(chunk),
                    },
                    false,
                )
                .map_err(Self::Error::from)?;

            if response.length != chunk.len() {
                return Err(Error::BadLength.into());
            }
            if &response.socket != socket {
                return Err(Error::WrongSocketType.into());
            }
        }

        Ok(())
    }

    /// Read a datagram the remote host has sent to us. Returns `Ok(n)`, which
    /// means a datagram of size `n` has been received and it has been placed
    /// in `&buffer[0..n]`, or an error.
    fn receive(
        &mut self,
        socket: &mut Self::UdpSocket,
        buffer: &mut [u8],
    ) -> nb::Result<(usize, SocketAddr), Self::Error> {
        let mut udp = self
            .sockets
            .get::<UdpSocket<CLK, L>>(*socket)
            .map_err(Self::Error::from)?;

        let response = udp
            .recv_slice(buffer)
            .map(|n| (n, udp.endpoint()))
            .map_err(Self::Error::from)?;
        Ok(response)
    }

    /// Close an existing UDP socket.
    fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error> {
        self.network.send_internal(&CloseSocket { socket }, false)?;
        self.sockets.remove(socket)?;
        Ok(())
    }
}