psp_net/socket/
udp.rs

1#![allow(clippy::module_name_repetitions)]
2
3use alloc::{borrow::ToOwned, vec::Vec};
4use core::net::{IpAddr, Ipv4Addr, SocketAddr};
5use embedded_io::{ErrorType, Read, Write};
6use psp::sys::{self, sockaddr, socklen_t};
7
8use core::ffi::c_void;
9
10use crate::{
11    traits::{
12        io::{EasySocket, Open, OptionType},
13        SocketBuffer,
14    },
15    types::{SocketOptions, SocketRecvFlags, SocketSendFlags},
16};
17
18use super::{
19    super::netc,
20    error::SocketError,
21    sce::SocketFileDescriptor,
22    state::{Bound, Connected, SocketState, Unbound},
23    ToSockaddr, ToSocketAddr,
24};
25
26/// A UDP socket
27///
28/// # Notes
29/// - Remote host ([`Self::remote`]) is set when the socket is bound calling [`bind()`](UdpSocket::bind)
30/// - In addition to supporting the creation (with [`new`](Self::new)) and manual management of the socket,
31///   this struct implements [`EasySocket`] trait, which allows for an easier management of the socket,
32///   providing the [`open`](Self::open) method as an alternative to [`new`](Self::new).
33///   This method return a [`UdpSocket`] already connected, and ready to send/receive data (using the
34///   [`write`](embedded_io::Write::write) and [`read`](embedded_io::Read::read) methods).
35/// - The socket is closed when the struct is dropped. Closing via drop is best-effort.
36#[repr(C)]
37#[derive(Clone)]
38pub struct UdpSocket<S: SocketState = Unbound, B: SocketBuffer = Vec<u8>> {
39    /// The socket file descriptor
40    fd: SocketFileDescriptor,
41    /// The remote host to connect to
42    remote: Option<sockaddr>,
43    /// The buffer to store data to send
44    buffer: B,
45    /// flags for send calls
46    send_flags: SocketSendFlags,
47    /// flags for recv calls
48    recv_flags: SocketRecvFlags,
49    /// marker for the socket state
50    _marker: core::marker::PhantomData<S>,
51}
52
53impl UdpSocket {
54    /// Create a socket
55    ///
56    /// # Notes
57    /// - Creating a new socket is not sufficient to start sending/receiving data.
58    ///   You must call [`Self::open()`] (if you're using it in [`EasySocket`] mode), or
59    ///   [`Self::bind()`] and/or [`Self::connect()`].
60    ///
61    /// # Errors
62    /// - [`SocketError::Errno`] if the socket could not be created
63    #[allow(dead_code)]
64    pub fn new() -> Result<UdpSocket<Unbound>, SocketError> {
65        let fd = unsafe { sys::sceNetInetSocket(i32::from(netc::AF_INET), netc::SOCK_DGRAM, 0) };
66        if fd < 0 {
67            Err(SocketError::Errno(unsafe { sys::sceNetInetGetErrno() }))
68        } else {
69            let fd = SocketFileDescriptor::new(fd);
70            Ok(UdpSocket {
71                fd,
72                remote: None,
73                buffer: Vec::with_capacity(0),
74                send_flags: SocketSendFlags::empty(),
75                recv_flags: SocketRecvFlags::empty(),
76                _marker: core::marker::PhantomData,
77            })
78        }
79    }
80}
81
82impl<S: SocketState> UdpSocket<S> {
83    fn socket_len() -> socklen_t {
84        core::mem::size_of::<netc::sockaddr>() as u32
85    }
86
87    /// Get the file descriptor of the socket
88    #[must_use]
89    pub fn fd(&self) -> i32 {
90        *self.fd
91    }
92
93    /// Get the remote address of the socket
94    #[must_use]
95    pub fn remote(&self) -> Option<SocketAddr> {
96        self.remote.map(|sockaddr| sockaddr.to_socket_addr())
97    }
98
99    /// Flags used when sending data
100    #[must_use]
101    pub fn send_flags(&self) -> SocketSendFlags {
102        self.send_flags
103    }
104
105    /// Set the flags used when sending data
106    pub fn set_send_flags(&mut self, send_flags: SocketSendFlags) {
107        self.send_flags = send_flags;
108    }
109
110    /// Flags used when receiving data
111    #[must_use]
112    pub fn recv_flags(&self) -> SocketRecvFlags {
113        self.recv_flags
114    }
115
116    /// Set the flags used when receiving data
117    pub fn set_recv_flags(&mut self, recv_flags: SocketRecvFlags) {
118        self.recv_flags = recv_flags;
119    }
120}
121
122impl UdpSocket<Unbound> {
123    /// Transition the socket to `Bound` state
124    fn transition(self, remote: Option<sockaddr>) -> UdpSocket<Bound> {
125        UdpSocket {
126            fd: self.fd,
127            remote,
128            buffer: Vec::with_capacity(0),
129            send_flags: self.send_flags,
130            recv_flags: self.recv_flags,
131            _marker: core::marker::PhantomData,
132        }
133    }
134
135    /// Bind the socket
136    ///
137    /// # Parameters
138    /// - `addr`: The address to bind to, if `None` binds to `0.0.0.0:0`
139    ///
140    /// # Returns
141    /// - `Ok(UdpSocket<Bound>)` if the binding was successful
142    /// - `Err(SocketError)` if the binding was unsuccessful.
143    ///
144    /// # Errors
145    /// - [`SocketError::Errno`] if the binding was unsuccessful
146    #[allow(unused)]
147    pub fn bind(mut self, addr: Option<SocketAddr>) -> Result<UdpSocket<Bound>, SocketError> {
148        let default_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
149        let addr = addr.unwrap_or(default_addr);
150        match addr {
151            SocketAddr::V4(v4) => {
152                let sockaddr = v4.to_sockaddr();
153
154                if unsafe {
155                    sys::sceNetInetBind(
156                        *self.fd,
157                        &sockaddr,
158                        core::mem::size_of::<netc::sockaddr>() as u32,
159                    )
160                } != 0
161                {
162                    let errno = unsafe { sys::sceNetInetGetErrno() };
163                    Err(SocketError::Errno(errno))
164                } else {
165                    Ok(self.transition(Some(sockaddr)))
166                }
167            }
168            SocketAddr::V6(_) => Err(SocketError::UnsupportedAddressFamily),
169        }
170    }
171}
172
173impl UdpSocket<Bound> {
174    /// Transition the socket to `Connected` state
175    fn transition(self, remote: sockaddr, buf: Option<Vec<u8>>) -> UdpSocket<Connected> {
176        UdpSocket {
177            fd: self.fd,
178            remote: Some(remote),
179            buffer: buf.unwrap_or_default(),
180            send_flags: self.send_flags,
181            recv_flags: self.recv_flags,
182            _marker: core::marker::PhantomData,
183        }
184    }
185
186    /// Connect to a remote host
187    ///
188    /// # Notes
189    /// The socket must be in state [`UdpSocketState::Bound`] to connect to a remote host.
190    /// To bind the socket use [`bind()`](UdpSocket::bind).
191    ///
192    /// # Returns
193    /// - `Ok(UdpSocket<Connected>)` if the connection was successful
194    /// - `Err(SocketError)` if the connection was unsuccessful
195    ///
196    /// # Errors
197    /// - Any [`SocketError`] if the connection was unsuccessful
198    #[allow(unused)]
199    pub fn connect(mut self, addr: SocketAddr) -> Result<UdpSocket<Connected>, SocketError> {
200        match addr {
201            SocketAddr::V4(v4) => {
202                let sockaddr = v4.to_sockaddr();
203
204                if unsafe { sys::sceNetInetConnect(*self.fd, &sockaddr, Self::socket_len()) } != 0 {
205                    let errno = unsafe { sys::sceNetInetGetErrno() };
206                    Err(SocketError::Errno(errno))
207                } else {
208                    Ok(self.transition(sockaddr, None))
209                }
210            }
211            SocketAddr::V6(_) => Err(SocketError::UnsupportedAddressFamily),
212        }
213    }
214
215    /// Read from a bound socket
216    ///
217    /// # Parameters
218    /// - `buf`: The buffer where to store the received data
219    ///
220    /// # Returns
221    /// - `Ok((usize, UdpSocket<Connected>))` if the write was successful. The number of bytes read
222    /// - `Err(SocketError)` if the read was unsuccessful.
223    ///
224    /// # Errors
225    /// - Any [`SocketError`] if the read was unsuccessful
226    #[allow(unused)]
227    pub fn _read_from(
228        mut self,
229        buf: &mut [u8],
230    ) -> Result<(usize, UdpSocket<Connected>), SocketError> {
231        let mut sockaddr = self
232            .remote
233            .ok_or(SocketError::Other("Remote not set".to_owned()))?;
234        let result = unsafe {
235            sys::sceNetInetRecvfrom(
236                *self.fd,
237                buf.as_mut_ptr().cast::<c_void>(),
238                buf.len(),
239                self.recv_flags.as_i32(),
240                &mut sockaddr,
241                &mut Self::socket_len(),
242            )
243        };
244        if result < 0 {
245            Err(SocketError::Errno(unsafe { sys::sceNetInetGetErrno() }))
246        } else {
247            Ok((result as usize, self.transition(sockaddr, None)))
248        }
249    }
250
251    /// Write to a bound socket
252    ///
253    /// # Parameters
254    /// - `buf`: The buffer containing the data to send
255    ///
256    ///
257    /// # Returns
258    /// - `Ok((usize, UdpSocket<Connected>))` if the send was successful. The number of bytes sent
259    /// - `Err(SocketError)` if the send was unsuccessful.
260    ///
261    /// # Errors
262    /// - Any [`SocketError`] if the send was unsuccessful
263    #[allow(unused)]
264    pub fn _write_to(
265        self,
266        buf: &[u8],
267        len: usize,
268        to: SocketAddr,
269    ) -> Result<(usize, UdpSocket<Connected>), SocketError> {
270        let sockaddr = match to {
271            SocketAddr::V4(v4) => Ok(super::socket_addr_v4_to_sockaddr(v4)),
272            SocketAddr::V6(_) => Err(SocketError::UnsupportedAddressFamily),
273        }?;
274        let socklen = core::mem::size_of::<netc::sockaddr>() as u32;
275
276        let mut buffer = Vec::with_capacity(buf.len());
277        buffer.append_buffer(buf);
278
279        let result = unsafe {
280            sys::sceNetInetSendto(
281                *self.fd,
282                buf.as_ptr().cast::<c_void>(),
283                len,
284                self.send_flags.as_i32(),
285                &sockaddr,
286                socklen,
287            )
288        };
289        if result < 0 {
290            Err(SocketError::Errno(unsafe { sys::sceNetInetGetErrno() }))
291        } else {
292            buffer.shift_left_buffer(result as usize);
293            Ok((result as usize, self.transition(sockaddr, Some(buffer))))
294        }
295    }
296}
297
298impl UdpSocket<Connected> {
299    /// Read from a socket
300    ///
301    /// # Parameters
302    /// - `buf`: The buffer where to store the received data
303    ///
304    /// # Returns
305    /// - `Ok(usize)` if the read was successful. The number of bytes read
306    /// - `Err(SocketError)` if the read was unsuccessful.
307    ///
308    /// # Errors
309    /// - Any [`SocketError`] if the read was unsuccessful
310    #[allow(unused)]
311    pub fn internal_read(&mut self, buf: &mut [u8]) -> Result<usize, SocketError> {
312        let result = unsafe {
313            sys::sceNetInetRecv(
314                *self.fd,
315                buf.as_mut_ptr().cast::<c_void>(),
316                buf.len(),
317                self.recv_flags.as_i32(),
318            )
319        };
320        if result < 0 {
321            Err(SocketError::Errno(unsafe { sys::sceNetInetGetErrno() }))
322        } else {
323            Ok(result as usize)
324        }
325    }
326
327    /// Write to a socket
328    ///
329    /// # Returns
330    /// - `Ok(usize)` if the send was successful. The number of bytes sent
331    /// - `Err(SocketError)` if the send was unsuccessful.
332    ///
333    /// # Errors
334    /// - Any [`SocketError`] if the send was unsuccessful
335    #[allow(unused)]
336    pub fn internal_write(&mut self, buf: &[u8]) -> Result<usize, SocketError> {
337        self.buffer.append_buffer(buf);
338        self.send()
339    }
340
341    /// Flush the send buffer
342    ///
343    /// # Errors
344    /// - Any [`SocketError`] if the flush was unsuccessful.
345    pub fn internal_flush(&mut self) -> Result<(), SocketError> {
346        while !self.buffer.is_empty() {
347            self.send()?;
348        }
349        Ok(())
350    }
351
352    fn send(&mut self) -> Result<usize, SocketError> {
353        let result = unsafe {
354            sys::sceNetInetSend(
355                *self.fd,
356                self.buffer.as_slice().as_ptr().cast::<c_void>(),
357                self.buffer.len(),
358                self.send_flags.as_i32(),
359            )
360        };
361        if result < 0 {
362            Err(SocketError::Errno(unsafe { sys::sceNetInetGetErrno() }))
363        } else {
364            self.buffer.shift_left_buffer(result as usize);
365            Ok(result as usize)
366        }
367    }
368}
369
370impl<S: SocketState> OptionType for UdpSocket<S> {
371    type Options<'a> = SocketOptions;
372}
373
374impl<S: SocketState> ErrorType for UdpSocket<S> {
375    type Error = SocketError;
376}
377
378impl Open<'_, '_> for UdpSocket<Unbound> {
379    type Return = UdpSocket<Connected>;
380    /// Open the socket
381    ///
382    /// # Parameters
383    /// - `options`: The options to use when opening the socket.
384    ///
385    /// # Returns
386    /// - `Ok(UdpSocket<Connected>)` if the socket was opened successfully
387    /// - `Err(SocketError)` if the socket failed to open.
388    ///
389    /// # Examples
390    /// ```no_run
391    /// let socket = UdpSocket::new()?;
392    /// let socket = socket.open(&SocketOptions::default())?;
393    /// ```
394    fn open(self, options: &'_ Self::Options<'_>) -> Result<Self::Return, Self::Error> {
395        let sock = self.bind(None)?;
396        let sock = sock.connect(options.remote())?;
397        Ok(sock)
398    }
399}
400
401impl Read for UdpSocket<Connected> {
402    /// Read from the socket
403    ///
404    /// # Parameters
405    /// - `buf`: The buffer where the read data will be stored
406    ///
407    /// # Returns
408    /// - `Ok(usize)` if the read was successful. The number of bytes read
409    /// - `Err(SocketError)` if the read was unsuccessful.
410    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
411        self.internal_read(buf)
412    }
413}
414
415impl Write for UdpSocket<Connected> {
416    /// Write to the socket
417    ///
418    /// # Parameters
419    /// - `buf`: The data to write
420    ///
421    /// # Returns
422    /// - `Ok(usize)` if the write was successful. The number of bytes written
423    /// - `Err(SocketError)` if the write was unsuccessful.
424    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
425        self.internal_write(buf)
426    }
427
428    /// Flush the socket
429    ///
430    /// # Errors
431    /// - Any [`SocketError`] if the flush was unsuccessful.
432    fn flush(&mut self) -> Result<(), Self::Error> {
433        self.internal_flush()
434    }
435}
436
437impl EasySocket for UdpSocket<Connected> {}