openthread/ot/
udp.rs

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
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::prelude_internal::*;
use std::ptr::{null_mut, NonNull};

/// Functional equivalent of [`otsys::otUdpSocket`](crate::otsys::otUdpSocket).
#[repr(transparent)]
pub struct UdpSocket<'a>(pub otUdpSocket, PhantomData<*mut otUdpSocket>, PhantomData<&'a ()>);

impl_ot_castable!(opaque lifetime UdpSocket<'_>, otUdpSocket, Default::default(), Default::default());

impl std::fmt::Debug for UdpSocket<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("otUdpSocket")
            .field("peer_name", &self.peer_name())
            .field("sock_name", &self.sock_name())
            .field("handle", &self.get_handle())
            .finish()
    }
}

impl<'a> UdpSocket<'a> {
    /// The peer IPv6 socket address.
    pub fn peer_name(&self) -> SockAddr {
        self.0.mPeerName.into()
    }

    /// The local IPv6 socket address.
    pub fn sock_name(&self) -> SockAddr {
        self.0.mSockName.into()
    }

    /// A handle to platform's UDP.
    pub fn get_handle(&self) -> Option<NonNull<::std::os::raw::c_void>> {
        NonNull::new(self.0.mHandle)
    }

    /// Change the UDP handle.
    pub fn set_handle(&mut self, handle: Option<NonNull<::std::os::raw::c_void>>) {
        self.0.mHandle = handle.map(NonNull::as_ptr).unwrap_or(null_mut());
    }

    /// Platform callback for handling received data.
    pub fn handle_receive(&self, msg: &ot::Message<'a>, info: &ot::message::Info) {
        if let Some(handler) = self.0.mHandler {
            unsafe {
                // SAFETY: The safety of this call is predicated on the underlying
                //         handler not taking ownership of the ot::Message instance.
                //         This is guaranteed as a part of the API contract.
                handler(self.0.mContext, msg.as_ot_ptr(), info.as_ot_ptr());
            }
        }
    }
}

/// Iterates over the available UDP sockets. See [`Udp::udp_get_sockets`].
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct UdpSocketIterator<'a>(*mut otUdpSocket, PhantomData<&'a ()>);

impl<'a> Iterator for UdpSocketIterator<'a> {
    type Item = &'a UdpSocket<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let ret = unsafe { UdpSocket::ref_from_ot_ptr(self.0) };
        if ret.is_some() {
            self.0 = unsafe { (*self.0).mNext };
        }
        ret
    }
}

/// Methods from the [OpenThread "UDP" Module](https://openthread.io/reference/group/api-udp).
pub trait Udp {
    /// Functional equivalent of [`otsys::otUdpGetSockets`](crate::otsys::otUdpGetSockets).
    fn udp_get_sockets(&self) -> UdpSocketIterator<'_>;
}

impl<T: Udp + ot::Boxable> Udp for ot::Box<T> {
    fn udp_get_sockets(&self) -> UdpSocketIterator<'_> {
        self.as_ref().udp_get_sockets()
    }
}

impl Udp for Instance {
    fn udp_get_sockets(&self) -> UdpSocketIterator<'_> {
        UdpSocketIterator(unsafe { otUdpGetSockets(self.as_ot_ptr()) }, PhantomData)
    }
}