openthread/ot/
srp.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// for now, we allow this for this module because we can't apply it
6// specifically to the type `ChangedFlags`, due to a bug in `bitflags!`.
7#![allow(missing_docs)]
8
9use crate::ot::DnsTxtEntryIterator;
10use crate::prelude_internal::*;
11
12/// Represents the SRP server state.
13///
14/// Functional equivalent of [`otsys::otSrpServerState`](crate::otsys::otSrpServerState).
15#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
16#[allow(missing_docs)]
17pub enum SrpServerState {
18    /// Functional equivalent of
19    /// [`otsys::otSrpServerState_OT_SRP_SERVER_STATE_DISABLED`](crate::otsys::otSrpServerState_OT_SRP_SERVER_STATE_DISABLED).
20    Disabled = OT_SRP_SERVER_STATE_DISABLED as isize,
21
22    /// Functional equivalent of
23    /// [`otsys::otSrpServerState_OT_SRP_SERVER_STATE_RUNNING`](crate::otsys::otSrpServerState_OT_SRP_SERVER_STATE_RUNNING).
24    Running = OT_SRP_SERVER_STATE_RUNNING as isize,
25
26    /// Functional equivalent of
27    /// [`otsys::otSrpServerState_OT_SRP_SERVER_STATE_STOPPED`](crate::otsys::otSrpServerState_OT_SRP_SERVER_STATE_STOPPED).
28    Stopped = OT_SRP_SERVER_STATE_STOPPED as isize,
29}
30
31/// Represents the SRP server address mode.
32///
33/// Functional equivalent of
34/// [`otsys::otSrpServerAddressMode`](crate::otsys::otSrpServerAddressMode).
35#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
36#[allow(missing_docs)]
37pub enum SrpServerAddressMode {
38    /// Functional equivalent of
39    /// [`otsys::otSrpServerAddressMode_OT_SRP_SERVER_ADDRESS_MODE_UNICAST`](crate::otsys::otSrpServerAddressMode_OT_SRP_SERVER_ADDRESS_MODE_UNICAST).
40    Unicast = OT_SRP_SERVER_ADDRESS_MODE_UNICAST as isize,
41
42    /// Functional equivalent of
43    /// [`otsys::otSrpServerAddressMode_OT_SRP_SERVER_ADDRESS_MODE_ANYCAST`](crate::otsys::otSrpServerAddressMode_OT_SRP_SERVER_ADDRESS_MODE_ANYCAST).
44    Anycast = OT_SRP_SERVER_ADDRESS_MODE_ANYCAST as isize,
45}
46
47/// Iterates over the available SRP server hosts. See [`SrpServer::srp_server_get_hosts`].
48pub struct SrpServerHostIterator<'a, T: SrpServer> {
49    prev: Option<&'a SrpServerHost>,
50    ot_instance: &'a T,
51}
52
53// This cannot be easily derived because T doesn't implement `Clone`,
54// so we must implement it manually.
55impl<T: SrpServer> Clone for SrpServerHostIterator<'_, T> {
56    fn clone(&self) -> Self {
57        SrpServerHostIterator { prev: self.prev, ot_instance: self.ot_instance }
58    }
59}
60
61impl<T: SrpServer> std::fmt::Debug for SrpServerHostIterator<'_, T> {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        write!(f, "[")?;
64        for item in self.clone() {
65            item.fmt(f)?;
66            write!(f, ",")?;
67        }
68        write!(f, "]")
69    }
70}
71
72impl<'a, T: SrpServer> Iterator for SrpServerHostIterator<'a, T> {
73    type Item = &'a SrpServerHost;
74
75    fn next(&mut self) -> Option<Self::Item> {
76        self.prev = self.ot_instance.srp_server_next_host(self.prev);
77        self.prev
78    }
79}
80
81/// Iterates over all the available SRP services.
82#[derive(Clone)]
83pub struct SrpServerServiceIterator<'a> {
84    prev: Option<&'a SrpServerService>,
85    host: &'a SrpServerHost,
86}
87
88impl std::fmt::Debug for SrpServerServiceIterator<'_> {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        write!(f, "[")?;
91        for item in self.clone() {
92            item.fmt(f)?;
93            write!(f, ",")?;
94        }
95        write!(f, "]")
96    }
97}
98
99impl<'a> Iterator for SrpServerServiceIterator<'a> {
100    type Item = &'a SrpServerService;
101
102    fn next(&mut self) -> Option<Self::Item> {
103        self.prev = self.host.next_service(self.prev);
104        self.prev
105    }
106}
107
108/// This opaque type (only used by reference) represents a SRP host.
109///
110/// Functional equivalent of [`otsys::otSrpServerHost`](crate::otsys::otSrpServerHost).
111#[repr(transparent)]
112pub struct SrpServerHost(otSrpServerHost);
113impl_ot_castable!(opaque SrpServerHost, otSrpServerHost);
114
115impl std::fmt::Debug for SrpServerHost {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        f.debug_struct("otSrpServerHost")
118            .field("full_name", &self.full_name_cstr())
119            .field("addresses", &self.addresses())
120            .field("is_deleted", &self.is_deleted())
121            .field("services", &self.services())
122            .finish()
123    }
124}
125
126impl SrpServerHost {
127    /// Functional equivalent of
128    /// [`otsys::otSrpServerHostGetAddresses`](crate::otsys::otSrpServerHostGetAddresses).
129    pub fn addresses(&self) -> &[Ip6Address] {
130        let mut addresses_len = 0u8;
131        unsafe {
132            let addresses_ptr =
133                otSrpServerHostGetAddresses(self.as_ot_ptr(), &mut addresses_len as *mut u8);
134
135            std::slice::from_raw_parts(addresses_ptr as *const Ip6Address, addresses_len as usize)
136        }
137    }
138
139    /// Functional equivalent of
140    /// [`otsys::otSrpServerHostMatchesFullName`](crate::otsys::otSrpServerHostMatchesFullName).
141    pub fn matches_full_name_cstr(&self, full_name: &CStr) -> bool {
142        unsafe { otSrpServerHostMatchesFullName(self.as_ot_ptr(), full_name.as_ptr()) }
143    }
144
145    /// Functional equivalent of
146    /// [`otsys::otSrpServerHostGetFullName`](crate::otsys::otSrpServerHostGetFullName).
147    pub fn full_name_cstr(&self) -> &CStr {
148        unsafe { CStr::from_ptr(otSrpServerHostGetFullName(self.as_ot_ptr())) }
149    }
150
151    /// Functional equivalent of
152    /// [`otsys::otSrpServerHostIsDeleted`](crate::otsys::otSrpServerHostIsDeleted).
153    pub fn is_deleted(&self) -> bool {
154        unsafe { otSrpServerHostIsDeleted(self.as_ot_ptr()) }
155    }
156
157    /// Functional equivalent of
158    /// [`otsys::otSrpServerHostGetLeaseInfo`](crate::otsys::otSrpServerHostGetLeaseInfo).
159    pub fn get_lease_info(&self, lease_info: &mut SrpServerLeaseInfo) {
160        unsafe { otSrpServerHostGetLeaseInfo(self.as_ot_ptr(), lease_info.as_ot_mut_ptr()) }
161    }
162
163    /// Functional equivalent of
164    /// [`otsys::otSrpServerHostGetNextService`](crate::otsys::otSrpServerHostGetNextService).
165    pub fn next_service<'a>(
166        &'a self,
167        prev: Option<&'a SrpServerService>,
168    ) -> Option<&'a SrpServerService> {
169        let prev = prev.map(|x| x.as_ot_ptr()).unwrap_or(null());
170        unsafe {
171            SrpServerService::ref_from_ot_ptr(otSrpServerHostGetNextService(self.as_ot_ptr(), prev))
172        }
173    }
174
175    /// Returns an iterator over all of the services for this host.
176    pub fn services(&self) -> SrpServerServiceIterator<'_> {
177        SrpServerServiceIterator { prev: None, host: self }
178    }
179}
180
181/// Iterates over all the available SRP services subtypes.
182#[derive(Clone)]
183pub struct SrpServerServiceSubtypeIterator<'a> {
184    service: &'a SrpServerService,
185    next_i: u16,
186}
187
188impl std::fmt::Debug for SrpServerServiceSubtypeIterator<'_> {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        write!(f, "[")?;
191        for item in self.clone() {
192            item.fmt(f)?;
193            write!(f, ",")?;
194        }
195        write!(f, "]")
196    }
197}
198
199impl<'a> Iterator for SrpServerServiceSubtypeIterator<'a> {
200    type Item = &'a CStr;
201
202    fn next(&mut self) -> Option<Self::Item> {
203        let ret = self.service.subtype_service_name_at(self.next_i);
204        if ret.is_some() {
205            self.next_i += 1;
206        }
207        ret
208    }
209}
210
211/// This opaque type (only used by reference) represents a SRP service.
212///
213/// Functional equivalent of [`otsys::otSrpServerService`](crate::otsys::otSrpServerService).
214#[repr(transparent)]
215pub struct SrpServerService(otSrpServerService);
216impl_ot_castable!(opaque SrpServerService, otSrpServerService);
217
218impl std::fmt::Debug for SrpServerService {
219    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220        if self.is_deleted() {
221            f.debug_struct("otSrpServerService")
222                .field("service_name", &self.service_name_cstr())
223                .field("instance_name", &self.instance_name_cstr())
224                .field("is_deleted", &self.is_deleted())
225                .finish()
226        } else {
227            f.debug_struct("otSrpServerService")
228                .field("service_name", &self.service_name_cstr())
229                .field("instance_name", &self.instance_name_cstr())
230                .field("is_deleted", &self.is_deleted())
231                .field("txt_data", &ascii_dump(self.txt_data()))
232                .field("txt_entries", &self.txt_entries().collect::<Vec<_>>())
233                .field("port", &self.port())
234                .field("priority", &self.priority())
235                .field("weight", &self.weight())
236                .field("subtypes", &self.subtypes())
237                .finish()
238        }
239    }
240}
241
242impl SrpServerService {
243    /// Functional equivalent of
244    /// [`otsys::otSrpServerServiceGetPort`](crate::otsys::otSrpServerServiceGetPort).
245    pub fn port(&self) -> u16 {
246        unsafe { otSrpServerServiceGetPort(self.as_ot_ptr()) }
247    }
248
249    /// Functional equivalent of
250    /// [`otsys::otSrpServerServiceGetPriority`](crate::otsys::otSrpServerServiceGetPriority).
251    pub fn priority(&self) -> u16 {
252        unsafe { otSrpServerServiceGetPriority(self.as_ot_ptr()) }
253    }
254
255    /// Functional equivalent of
256    /// [`otsys::otSrpServerServiceIsDeleted`](crate::otsys::otSrpServerServiceIsDeleted).
257    pub fn is_deleted(&self) -> bool {
258        unsafe { otSrpServerServiceIsDeleted(self.as_ot_ptr()) }
259    }
260
261    /// Functional equivalent of
262    /// [`otsys::otSrpServerServiceGetLeaseInfo`](crate::otsys::otSrpServerServiceGetLeaseInfo).
263    pub fn get_lease_info(&self, lease_info: &mut SrpServerLeaseInfo) {
264        unsafe { otSrpServerServiceGetLeaseInfo(self.as_ot_ptr(), lease_info.as_ot_mut_ptr()) }
265    }
266
267    /// Returns an iterator over all of the subtypes.
268    pub fn subtypes(&self) -> SrpServerServiceSubtypeIterator<'_> {
269        SrpServerServiceSubtypeIterator { service: self, next_i: 0 }
270    }
271
272    /// Functional equivalent of
273    /// [`otsys::otSrpServerServiceGetNumberOfSubTypes`](crate::otsys::otSrpServerServiceGetNumberOfSubTypes).
274    pub fn number_of_subtypes(&self) -> u16 {
275        unsafe { otSrpServerServiceGetNumberOfSubTypes(self.as_ot_ptr()) }
276    }
277
278    /// Functional equivalent of
279    /// [`otsys::otSrpServerServiceGetSubTypeServiceNameAt`](crate::otsys::otSrpServerServiceGetSubTypeServiceNameAt).
280    pub fn subtype_service_name_at(&self, i: u16) -> Option<&CStr> {
281        unsafe {
282            let ptr = otSrpServerServiceGetSubTypeServiceNameAt(self.as_ot_ptr(), i);
283            if ptr.is_null() { None } else { Some(CStr::from_ptr(ptr)) }
284        }
285    }
286
287    /// Functional equivalent of
288    /// [`otsys::otSrpServerServiceGetTxtData`](crate::otsys::otSrpServerServiceGetTxtData).
289    pub fn txt_data(&self) -> &[u8] {
290        let mut txt_data_len = 0u16;
291        unsafe {
292            let txt_data_ptr =
293                otSrpServerServiceGetTxtData(self.as_ot_ptr(), &mut txt_data_len as *mut u16);
294
295            std::slice::from_raw_parts(txt_data_ptr, txt_data_len as usize)
296        }
297    }
298
299    /// Returns iterator over all the DNS TXT entries.
300    pub fn txt_entries(&self) -> DnsTxtEntryIterator<'_> {
301        DnsTxtEntryIterator::try_new(self.txt_data()).unwrap()
302    }
303
304    /// Functional equivalent of
305    /// [`otsys::otSrpServerServiceGetWeight`](crate::otsys::otSrpServerServiceGetWeight).
306    pub fn weight(&self) -> u16 {
307        unsafe { otSrpServerServiceGetWeight(self.as_ot_ptr()) }
308    }
309
310    /// Functional equivalent of
311    /// [`otsys::otSrpServerServiceGetServiceName`](crate::otsys::otSrpServerServiceGetServiceName).
312    pub fn service_name_cstr(&self) -> &CStr {
313        unsafe { CStr::from_ptr(otSrpServerServiceGetServiceName(self.as_ot_ptr())) }
314    }
315
316    /// Functional equivalent of
317    /// [`otsys::otSrpServerServiceGetInstanceName`](crate::otsys::otSrpServerServiceGetInstanceName).
318    pub fn instance_name_cstr(&self) -> &CStr {
319        unsafe { CStr::from_ptr(otSrpServerServiceGetInstanceName(self.as_ot_ptr())) }
320    }
321
322    /// Functional equivalent of
323    /// [`otsys::otSrpServerServiceGetInstanceLabel`](crate::otsys::otSrpServerServiceGetInstanceLabel).
324    pub fn instance_label_cstr(&self) -> &CStr {
325        unsafe { CStr::from_ptr(otSrpServerServiceGetInstanceLabel(self.as_ot_ptr())) }
326    }
327}
328
329/// Functional equivalent of
330/// [`otsys::otSrpServerParseSubTypeServiceName`](crate::otsys::otSrpServerParseSubTypeServiceName).
331pub fn parse_label_from_subtype_service_name(
332    subtype_service_name: &CStr,
333) -> Result<CString, Error> {
334    let mut bytes = [0 as c_char; 256];
335
336    // SAFETY: We are passing in valid pointers with a length one less than the array size.
337    Error::from(unsafe {
338        otSrpServerParseSubTypeServiceName(
339            subtype_service_name.as_ptr(),
340            (&mut bytes) as *mut c_char,
341            255,
342        )
343    })
344    .into_result()?;
345
346    // SAFETY: `bytes` is guaranteed to be zero terminated because of the size of the array.
347    Ok(unsafe { CStr::from_ptr(&bytes as *const c_char) }.to_owned())
348}
349
350/// The ID of a SRP service update transaction on the SRP Server.
351///
352/// Functional equivalent of
353/// [`otsys::otSrpServerServiceUpdateId`](crate::otsys::otSrpServerServiceUpdateId).
354#[derive(Debug, Hash, PartialEq, Eq, Clone)]
355pub struct SrpServerServiceUpdateId(otSrpServerServiceUpdateId);
356
357impl SrpServerServiceUpdateId {
358    fn new(x: otSrpServerServiceUpdateId) -> Self {
359        Self(x)
360    }
361
362    fn take(self) -> otSrpServerServiceUpdateId {
363        self.0
364    }
365}
366
367/// Server Methods from the [OpenThread SRP Module][1].
368///
369/// [1]: https://openthread.io/reference/group/api-srp
370pub trait SrpServer {
371    /// Functional equivalent of
372    /// [`otsys::otSrpServerGetAddressMode`](crate::otsys::otSrpServerGetAddressMode).
373    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode;
374
375    /// Functional equivalent of
376    /// [`otsys::otSrpServerGetState`](crate::otsys::otSrpServerGetState).
377    fn srp_server_get_state(&self) -> SrpServerState;
378
379    /// Functional equivalent of
380    /// [`otsys::otSrpServerGetPort`](crate::otsys::otSrpServerGetPort).
381    fn srp_server_get_port(&self) -> u16;
382
383    /// Functional equivalent of
384    /// [`otsys::otSrpServerSetEnabled`](crate::otsys::otSrpServerSetEnabled).
385    fn srp_server_set_enabled(&self, enabled: bool);
386
387    /// Functional equivalent of
388    /// [`otsys::otSrpServerSetEnabled`](crate::otsys::otSrpServerSetAutoEnableMode).
389    fn srp_server_set_auto_enable_mode(&self, enabled: bool);
390
391    /// Returns true if the SRP server is enabled.
392    fn srp_server_is_enabled(&self) -> bool;
393
394    /// Returns true if SRP server auto-enable mode is enabled.
395    fn srp_server_is_auto_enable_mode(&self) -> bool;
396
397    /// Returns true if the SRP server is running, false if it is stopped or disabled.
398    fn srp_server_is_running(&self) -> bool;
399
400    /// Functional equivalent of
401    /// [`otsys::otSrpServerSetDomain`](crate::otsys::otSrpServerSetDomain).
402    fn srp_server_set_domain(&self, domain: &CStr) -> Result;
403
404    /// Functional equivalent of
405    /// [`otsys::otSrpServerGetDomain`](crate::otsys::otSrpServerGetDomain).
406    fn srp_server_get_domain(&self) -> &CStr;
407
408    /// Functional equivalent of
409    /// [`otsys::otSrpServerGetResponseCounters`](crate::otsys::otSrpServerGetResponseCounters).
410    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters;
411
412    /// Functional equivalent of
413    /// [`otsys::otSrpServerGetNextHost`](crate::otsys::otSrpServerGetNextHost).
414    fn srp_server_next_host<'a>(
415        &'a self,
416        prev: Option<&'a SrpServerHost>,
417    ) -> Option<&'a SrpServerHost>;
418
419    /// Returns an iterator over the SRP hosts.
420    fn srp_server_hosts(&self) -> SrpServerHostIterator<'_, Self>
421    where
422        Self: Sized,
423    {
424        SrpServerHostIterator { prev: None, ot_instance: self }
425    }
426
427    /// Functional equivalent of
428    /// [`otsys::otSrpServerHandleServiceUpdateResult`](crate::otsys::otSrpServerHandleServiceUpdateResult).
429    fn srp_server_handle_service_update_result(&self, id: SrpServerServiceUpdateId, result: Result);
430
431    /// Functional equivalent of
432    /// [`otsys::otSrpServerSetServiceUpdateHandler`](crate::otsys::otSrpServerSetServiceUpdateHandler).
433    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
434    where
435        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a;
436}
437
438impl<T: SrpServer + Boxable> SrpServer for ot::Box<T> {
439    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode {
440        self.as_ref().srp_server_get_address_mode()
441    }
442
443    fn srp_server_get_state(&self) -> SrpServerState {
444        self.as_ref().srp_server_get_state()
445    }
446
447    fn srp_server_get_port(&self) -> u16 {
448        self.as_ref().srp_server_get_port()
449    }
450
451    fn srp_server_set_auto_enable_mode(&self, enabled: bool) {
452        self.as_ref().srp_server_set_auto_enable_mode(enabled)
453    }
454
455    fn srp_server_set_enabled(&self, enabled: bool) {
456        self.as_ref().srp_server_set_enabled(enabled)
457    }
458
459    fn srp_server_is_enabled(&self) -> bool {
460        self.as_ref().srp_server_is_enabled()
461    }
462
463    fn srp_server_is_auto_enable_mode(&self) -> bool {
464        self.as_ref().srp_server_is_auto_enable_mode()
465    }
466
467    fn srp_server_is_running(&self) -> bool {
468        self.as_ref().srp_server_is_running()
469    }
470
471    fn srp_server_set_domain(&self, domain: &CStr) -> Result {
472        self.as_ref().srp_server_set_domain(domain)
473    }
474
475    fn srp_server_get_domain(&self) -> &CStr {
476        self.as_ref().srp_server_get_domain()
477    }
478
479    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters {
480        self.as_ref().srp_server_get_response_counters()
481    }
482
483    fn srp_server_next_host<'a>(
484        &'a self,
485        prev: Option<&'a SrpServerHost>,
486    ) -> Option<&'a SrpServerHost> {
487        self.as_ref().srp_server_next_host(prev)
488    }
489
490    fn srp_server_handle_service_update_result(
491        &self,
492        id: SrpServerServiceUpdateId,
493        result: Result,
494    ) {
495        self.as_ref().srp_server_handle_service_update_result(id, result)
496    }
497
498    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
499    where
500        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
501    {
502        self.as_ref().srp_server_set_service_update_fn(f)
503    }
504}
505
506impl SrpServer for Instance {
507    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode {
508        unsafe {
509            SrpServerAddressMode::from_u32(otSrpServerGetAddressMode(self.as_ot_ptr())).unwrap()
510        }
511    }
512
513    fn srp_server_get_state(&self) -> SrpServerState {
514        unsafe { SrpServerState::from_u32(otSrpServerGetState(self.as_ot_ptr())).unwrap() }
515    }
516
517    fn srp_server_get_port(&self) -> u16 {
518        unsafe { otSrpServerGetPort(self.as_ot_ptr()) }
519    }
520
521    fn srp_server_set_auto_enable_mode(&self, enabled: bool) {
522        unsafe { otSrpServerSetAutoEnableMode(self.as_ot_ptr(), enabled) }
523    }
524
525    fn srp_server_set_enabled(&self, enabled: bool) {
526        unsafe { otSrpServerSetEnabled(self.as_ot_ptr(), enabled) }
527    }
528
529    fn srp_server_is_enabled(&self) -> bool {
530        #[allow(non_upper_case_globals)]
531        match unsafe { otSrpServerGetState(self.as_ot_ptr()) } {
532            OT_SRP_SERVER_STATE_DISABLED => false,
533            OT_SRP_SERVER_STATE_RUNNING => true,
534            OT_SRP_SERVER_STATE_STOPPED => true,
535            _ => panic!("Unexpected value from otSrpServerGetState"),
536        }
537    }
538
539    fn srp_server_is_auto_enable_mode(&self) -> bool {
540        unsafe { otSrpServerIsAutoEnableMode(self.as_ot_ptr()) }
541    }
542
543    fn srp_server_is_running(&self) -> bool {
544        #[allow(non_upper_case_globals)]
545        match unsafe { otSrpServerGetState(self.as_ot_ptr()) } {
546            OT_SRP_SERVER_STATE_DISABLED => false,
547            OT_SRP_SERVER_STATE_RUNNING => true,
548            OT_SRP_SERVER_STATE_STOPPED => false,
549            _ => panic!("Unexpected value from otSrpServerGetState"),
550        }
551    }
552
553    fn srp_server_set_domain(&self, domain: &CStr) -> Result {
554        Error::from(unsafe { otSrpServerSetDomain(self.as_ot_ptr(), domain.as_ptr()) }).into()
555    }
556
557    fn srp_server_get_domain(&self) -> &CStr {
558        unsafe { CStr::from_ptr(otSrpServerGetDomain(self.as_ot_ptr())) }
559    }
560
561    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters {
562        unsafe {
563            SrpServerResponseCounters::ref_from_ot_ptr(otSrpServerGetResponseCounters(
564                self.as_ot_ptr(),
565            ))
566            .unwrap()
567        }
568    }
569
570    fn srp_server_next_host<'a>(
571        &'a self,
572        prev: Option<&'a SrpServerHost>,
573    ) -> Option<&'a SrpServerHost> {
574        let prev = prev.map(|x| x.as_ot_ptr()).unwrap_or(null());
575        unsafe { SrpServerHost::ref_from_ot_ptr(otSrpServerGetNextHost(self.as_ot_ptr(), prev)) }
576    }
577
578    fn srp_server_handle_service_update_result(
579        &self,
580        id: SrpServerServiceUpdateId,
581        result: Result,
582    ) {
583        unsafe {
584            otSrpServerHandleServiceUpdateResult(
585                self.as_ot_ptr(),
586                id.take(),
587                Error::from(result).into(),
588            )
589        }
590    }
591
592    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
593    where
594        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
595    {
596        unsafe extern "C" fn _ot_srp_server_service_update_handler<'a, F>(
597            id: otSrpServerServiceUpdateId,
598            host: *const otSrpServerHost,
599            timeout: u32,
600            context: *mut ::std::os::raw::c_void,
601        ) where
602            F: FnMut(SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
603        {
604            // Reconstitute a reference to our closure.
605            let sender = &mut *(context as *mut F);
606
607            sender(
608                SrpServerServiceUpdateId::new(id),
609                SrpServerHost::ref_from_ot_ptr(host).unwrap(),
610                timeout,
611            )
612        }
613
614        // This helper func is just to allow us to get the type of the
615        // wrapper closure (`f_wrapped`) so we can pass that type
616        // as a type argument to `_ot_srp_server_service_update_handler`.
617        fn get_service_update_handler<'a, X>(_: &X) -> otSrpServerServiceUpdateHandler
618        where
619            X: FnMut(SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
620        {
621            Some(_ot_srp_server_service_update_handler::<X>)
622        }
623
624        let (fn_ptr, fn_box, cb): (_, _, otSrpServerServiceUpdateHandler) = if let Some(mut f) = f {
625            // Grab a pointer to our ot::Instance for use below in the wrapper closure.
626            let ot_instance_ptr = self.as_ot_ptr();
627
628            // Wrap around `f` with a closure that fills in the `ot_instance` field, which we
629            // won't have access to inside of `_ot_srp_server_service_update_handler::<_>`.
630            let f_wrapped =
631                move |id: SrpServerServiceUpdateId, host: &'a SrpServerHost, timeout: u32| {
632                    // SAFETY: This ot::Instance will be passed to the original closure as
633                    //         an argument. We know that it is valid because:
634                    //         1. It is being called by the instance, so it must still be around.
635                    //         2. By design there are no mutable references to the `ot::Instance`
636                    //            in existence.
637                    let ot_instance =
638                        unsafe { ot::Instance::ref_from_ot_ptr(ot_instance_ptr) }.unwrap();
639                    f(ot_instance, id, host, timeout)
640                };
641
642            // Since we don't have a way to directly refer to the type of the closure `f_wrapped`,
643            // we need to use a helper function that can pass the type as a generic argument to
644            // `_ot_srp_server_service_update_handler::<X>` as `X`.
645            let service_update_handler = get_service_update_handler(&f_wrapped);
646
647            let mut x = Box::new(f_wrapped);
648
649            (
650                x.as_mut() as *mut _ as *mut ::std::os::raw::c_void,
651                Some(
652                    x as Box<
653                        dyn FnMut(ot::SrpServerServiceUpdateId, &'a ot::SrpServerHost, u32) + 'a,
654                    >,
655                ),
656                service_update_handler,
657            )
658        } else {
659            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
660        };
661
662        unsafe {
663            otSrpServerSetServiceUpdateHandler(self.as_ot_ptr(), cb, fn_ptr);
664
665            // Make sure our object eventually gets cleaned up.
666            // Here we must also transmute our closure to have a 'static lifetime.
667            // We need to do this because the borrow checker cannot infer the
668            // proper lifetime for the singleton instance backing, but
669            // this is guaranteed by the API.
670            self.borrow_backing().srp_server_service_update_fn.set(std::mem::transmute::<
671                Option<Box<dyn FnMut(SrpServerServiceUpdateId, &'a ot::SrpServerHost, u32) + 'a>>,
672                Option<Box<dyn FnMut(SrpServerServiceUpdateId, &ot::SrpServerHost, u32) + 'static>>,
673            >(fn_box));
674        }
675    }
676}