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                .field("ttl", &self.ttl())
238                .finish()
239        }
240    }
241}
242
243impl SrpServerService {
244    /// Functional equivalent of
245    /// [`otsys::otSrpServerServiceGetPort`](crate::otsys::otSrpServerServiceGetPort).
246    pub fn port(&self) -> u16 {
247        unsafe { otSrpServerServiceGetPort(self.as_ot_ptr()) }
248    }
249
250    /// Functional equivalent of
251    /// [`otsys::otSrpServerServiceGetPriority`](crate::otsys::otSrpServerServiceGetPriority).
252    pub fn priority(&self) -> u16 {
253        unsafe { otSrpServerServiceGetPriority(self.as_ot_ptr()) }
254    }
255
256    /// Functional equivalent of
257    /// [`otsys::otSrpServerServiceIsDeleted`](crate::otsys::otSrpServerServiceIsDeleted).
258    pub fn is_deleted(&self) -> bool {
259        unsafe { otSrpServerServiceIsDeleted(self.as_ot_ptr()) }
260    }
261
262    /// Functional equivalent of
263    /// [`otsys::otSrpServerServiceGetLeaseInfo`](crate::otsys::otSrpServerServiceGetLeaseInfo).
264    pub fn get_lease_info(&self, lease_info: &mut SrpServerLeaseInfo) {
265        unsafe { otSrpServerServiceGetLeaseInfo(self.as_ot_ptr(), lease_info.as_ot_mut_ptr()) }
266    }
267
268    /// Returns an iterator over all of the subtypes.
269    pub fn subtypes(&self) -> SrpServerServiceSubtypeIterator<'_> {
270        SrpServerServiceSubtypeIterator { service: self, next_i: 0 }
271    }
272
273    /// Functional equivalent of
274    /// [`otsys::otSrpServerServiceGetNumberOfSubTypes`](crate::otsys::otSrpServerServiceGetNumberOfSubTypes).
275    pub fn number_of_subtypes(&self) -> u16 {
276        unsafe { otSrpServerServiceGetNumberOfSubTypes(self.as_ot_ptr()) }
277    }
278
279    /// Functional equivalent of
280    /// [`otsys::otSrpServerServiceGetSubTypeServiceNameAt`](crate::otsys::otSrpServerServiceGetSubTypeServiceNameAt).
281    pub fn subtype_service_name_at(&self, i: u16) -> Option<&CStr> {
282        unsafe {
283            let ptr = otSrpServerServiceGetSubTypeServiceNameAt(self.as_ot_ptr(), i);
284            if ptr.is_null() { None } else { Some(CStr::from_ptr(ptr)) }
285        }
286    }
287
288    /// Functional equivalent of
289    /// [`otsys::otSrpServerServiceGetTxtData`](crate::otsys::otSrpServerServiceGetTxtData).
290    pub fn txt_data(&self) -> &[u8] {
291        let mut txt_data_len = 0u16;
292        unsafe {
293            let txt_data_ptr =
294                otSrpServerServiceGetTxtData(self.as_ot_ptr(), &mut txt_data_len as *mut u16);
295
296            std::slice::from_raw_parts(txt_data_ptr, txt_data_len as usize)
297        }
298    }
299
300    /// Returns iterator over all the DNS TXT entries.
301    pub fn txt_entries(&self) -> DnsTxtEntryIterator<'_> {
302        DnsTxtEntryIterator::try_new(self.txt_data()).unwrap()
303    }
304
305    /// Functional equivalent of
306    /// [`otsys::otSrpServerServiceGetWeight`](crate::otsys::otSrpServerServiceGetWeight).
307    pub fn weight(&self) -> u16 {
308        unsafe { otSrpServerServiceGetWeight(self.as_ot_ptr()) }
309    }
310
311    /// Functional equivalent of
312    /// [`otsys::otSrpServerServiceGetServiceName`](crate::otsys::otSrpServerServiceGetServiceName).
313    pub fn service_name_cstr(&self) -> &CStr {
314        unsafe { CStr::from_ptr(otSrpServerServiceGetServiceName(self.as_ot_ptr())) }
315    }
316
317    /// Functional equivalent of
318    /// [`otsys::otSrpServerServiceGetInstanceName`](crate::otsys::otSrpServerServiceGetInstanceName).
319    pub fn instance_name_cstr(&self) -> &CStr {
320        unsafe { CStr::from_ptr(otSrpServerServiceGetInstanceName(self.as_ot_ptr())) }
321    }
322
323    /// Functional equivalent of
324    /// [`otsys::otSrpServerServiceGetInstanceLabel`](crate::otsys::otSrpServerServiceGetInstanceLabel).
325    pub fn instance_label_cstr(&self) -> &CStr {
326        unsafe { CStr::from_ptr(otSrpServerServiceGetInstanceLabel(self.as_ot_ptr())) }
327    }
328
329    /// Functional equivalent of
330    /// [`otsys::otSrpServerServiceGetTtl`](crate::otsys::otSrpServerServiceGetTtl).
331    pub fn ttl(&self) -> zx::MonotonicDuration {
332        unsafe {
333            zx::MonotonicDuration::from_seconds(otSrpServerServiceGetTtl(self.as_ot_ptr()).into())
334        }
335    }
336}
337
338/// The ID of a SRP service update transaction on the SRP Server.
339///
340/// Functional equivalent of
341/// [`otsys::otSrpServerServiceUpdateId`](crate::otsys::otSrpServerServiceUpdateId).
342#[derive(Debug, Hash, PartialEq, Eq, Clone)]
343pub struct SrpServerServiceUpdateId(otSrpServerServiceUpdateId);
344
345impl SrpServerServiceUpdateId {
346    fn new(x: otSrpServerServiceUpdateId) -> Self {
347        Self(x)
348    }
349
350    fn take(self) -> otSrpServerServiceUpdateId {
351        self.0
352    }
353}
354
355/// Server Methods from the [OpenThread SRP Module][1].
356///
357/// [1]: https://openthread.io/reference/group/api-srp
358pub trait SrpServer {
359    /// Functional equivalent of
360    /// [`otsys::otSrpServerGetAddressMode`](crate::otsys::otSrpServerGetAddressMode).
361    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode;
362
363    /// Functional equivalent of
364    /// [`otsys::otSrpServerGetState`](crate::otsys::otSrpServerGetState).
365    fn srp_server_get_state(&self) -> SrpServerState;
366
367    /// Functional equivalent of
368    /// [`otsys::otSrpServerGetPort`](crate::otsys::otSrpServerGetPort).
369    fn srp_server_get_port(&self) -> u16;
370
371    /// Functional equivalent of
372    /// [`otsys::otSrpServerSetEnabled`](crate::otsys::otSrpServerSetEnabled).
373    fn srp_server_set_enabled(&self, enabled: bool);
374
375    /// Functional equivalent of
376    /// [`otsys::otSrpServerSetEnabled`](crate::otsys::otSrpServerSetAutoEnableMode).
377    fn srp_server_set_auto_enable_mode(&self, enabled: bool);
378
379    /// Returns true if the SRP server is enabled.
380    fn srp_server_is_enabled(&self) -> bool;
381
382    /// Returns true if SRP server auto-enable mode is enabled.
383    fn srp_server_is_auto_enable_mode(&self) -> bool;
384
385    /// Returns true if the SRP server is running, false if it is stopped or disabled.
386    fn srp_server_is_running(&self) -> bool;
387
388    /// Functional equivalent of
389    /// [`otsys::otSrpServerSetDomain`](crate::otsys::otSrpServerSetDomain).
390    fn srp_server_set_domain(&self, domain: &CStr) -> Result;
391
392    /// Functional equivalent of
393    /// [`otsys::otSrpServerGetDomain`](crate::otsys::otSrpServerGetDomain).
394    fn srp_server_get_domain(&self) -> &CStr;
395
396    /// Functional equivalent of
397    /// [`otsys::otSrpServerGetResponseCounters`](crate::otsys::otSrpServerGetResponseCounters).
398    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters;
399
400    /// Functional equivalent of
401    /// [`otsys::otSrpServerGetNextHost`](crate::otsys::otSrpServerGetNextHost).
402    fn srp_server_next_host<'a>(
403        &'a self,
404        prev: Option<&'a SrpServerHost>,
405    ) -> Option<&'a SrpServerHost>;
406
407    /// Returns an iterator over the SRP hosts.
408    fn srp_server_hosts(&self) -> SrpServerHostIterator<'_, Self>
409    where
410        Self: Sized,
411    {
412        SrpServerHostIterator { prev: None, ot_instance: self }
413    }
414
415    /// Functional equivalent of
416    /// [`otsys::otSrpServerHandleServiceUpdateResult`](crate::otsys::otSrpServerHandleServiceUpdateResult).
417    fn srp_server_handle_service_update_result(&self, id: SrpServerServiceUpdateId, result: Result);
418
419    /// Functional equivalent of
420    /// [`otsys::otSrpServerSetServiceUpdateHandler`](crate::otsys::otSrpServerSetServiceUpdateHandler).
421    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
422    where
423        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a;
424
425    /// Functional equivalent of
426    /// [`otsys::otSrpServerParseSubTypeServiceName`](crate::otsys::otSrpServerParseSubTypeServiceName).
427    fn parse_label_from_subtype_service_name(
428        &self,
429        subtype_service_name: &CStr,
430    ) -> Result<CString, Error>;
431}
432
433impl<T: SrpServer + Boxable> SrpServer for ot::Box<T> {
434    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode {
435        self.as_ref().srp_server_get_address_mode()
436    }
437
438    fn srp_server_get_state(&self) -> SrpServerState {
439        self.as_ref().srp_server_get_state()
440    }
441
442    fn srp_server_get_port(&self) -> u16 {
443        self.as_ref().srp_server_get_port()
444    }
445
446    fn srp_server_set_auto_enable_mode(&self, enabled: bool) {
447        self.as_ref().srp_server_set_auto_enable_mode(enabled)
448    }
449
450    fn srp_server_set_enabled(&self, enabled: bool) {
451        self.as_ref().srp_server_set_enabled(enabled)
452    }
453
454    fn srp_server_is_enabled(&self) -> bool {
455        self.as_ref().srp_server_is_enabled()
456    }
457
458    fn srp_server_is_auto_enable_mode(&self) -> bool {
459        self.as_ref().srp_server_is_auto_enable_mode()
460    }
461
462    fn srp_server_is_running(&self) -> bool {
463        self.as_ref().srp_server_is_running()
464    }
465
466    fn srp_server_set_domain(&self, domain: &CStr) -> Result {
467        self.as_ref().srp_server_set_domain(domain)
468    }
469
470    fn srp_server_get_domain(&self) -> &CStr {
471        self.as_ref().srp_server_get_domain()
472    }
473
474    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters {
475        self.as_ref().srp_server_get_response_counters()
476    }
477
478    fn srp_server_next_host<'a>(
479        &'a self,
480        prev: Option<&'a SrpServerHost>,
481    ) -> Option<&'a SrpServerHost> {
482        self.as_ref().srp_server_next_host(prev)
483    }
484
485    fn srp_server_handle_service_update_result(
486        &self,
487        id: SrpServerServiceUpdateId,
488        result: Result,
489    ) {
490        self.as_ref().srp_server_handle_service_update_result(id, result)
491    }
492
493    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
494    where
495        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
496    {
497        self.as_ref().srp_server_set_service_update_fn(f)
498    }
499
500    fn parse_label_from_subtype_service_name(
501        &self,
502        subtype_service_name: &CStr,
503    ) -> Result<CString, Error> {
504        self.as_ref().parse_label_from_subtype_service_name(subtype_service_name)
505    }
506}
507
508impl SrpServer for Instance {
509    fn srp_server_get_address_mode(&self) -> SrpServerAddressMode {
510        unsafe {
511            SrpServerAddressMode::from_u32(otSrpServerGetAddressMode(self.as_ot_ptr())).unwrap()
512        }
513    }
514
515    fn srp_server_get_state(&self) -> SrpServerState {
516        unsafe { SrpServerState::from_u32(otSrpServerGetState(self.as_ot_ptr())).unwrap() }
517    }
518
519    fn srp_server_get_port(&self) -> u16 {
520        unsafe { otSrpServerGetPort(self.as_ot_ptr()) }
521    }
522
523    fn srp_server_set_auto_enable_mode(&self, enabled: bool) {
524        unsafe { otSrpServerSetAutoEnableMode(self.as_ot_ptr(), enabled) }
525    }
526
527    fn srp_server_set_enabled(&self, enabled: bool) {
528        unsafe { otSrpServerSetEnabled(self.as_ot_ptr(), enabled) }
529    }
530
531    fn srp_server_is_enabled(&self) -> bool {
532        #[allow(non_upper_case_globals)]
533        match unsafe { otSrpServerGetState(self.as_ot_ptr()) } {
534            OT_SRP_SERVER_STATE_DISABLED => false,
535            OT_SRP_SERVER_STATE_RUNNING => true,
536            OT_SRP_SERVER_STATE_STOPPED => true,
537            _ => panic!("Unexpected value from otSrpServerGetState"),
538        }
539    }
540
541    fn srp_server_is_auto_enable_mode(&self) -> bool {
542        unsafe { otSrpServerIsAutoEnableMode(self.as_ot_ptr()) }
543    }
544
545    fn srp_server_is_running(&self) -> bool {
546        #[allow(non_upper_case_globals)]
547        match unsafe { otSrpServerGetState(self.as_ot_ptr()) } {
548            OT_SRP_SERVER_STATE_DISABLED => false,
549            OT_SRP_SERVER_STATE_RUNNING => true,
550            OT_SRP_SERVER_STATE_STOPPED => false,
551            _ => panic!("Unexpected value from otSrpServerGetState"),
552        }
553    }
554
555    fn srp_server_set_domain(&self, domain: &CStr) -> Result {
556        Error::from(unsafe { otSrpServerSetDomain(self.as_ot_ptr(), domain.as_ptr()) }).into()
557    }
558
559    fn srp_server_get_domain(&self) -> &CStr {
560        unsafe { CStr::from_ptr(otSrpServerGetDomain(self.as_ot_ptr())) }
561    }
562
563    fn srp_server_get_response_counters(&self) -> &SrpServerResponseCounters {
564        unsafe {
565            SrpServerResponseCounters::ref_from_ot_ptr(otSrpServerGetResponseCounters(
566                self.as_ot_ptr(),
567            ))
568            .unwrap()
569        }
570    }
571
572    fn srp_server_next_host<'a>(
573        &'a self,
574        prev: Option<&'a SrpServerHost>,
575    ) -> Option<&'a SrpServerHost> {
576        let prev = prev.map(|x| x.as_ot_ptr()).unwrap_or(null());
577        unsafe { SrpServerHost::ref_from_ot_ptr(otSrpServerGetNextHost(self.as_ot_ptr(), prev)) }
578    }
579
580    fn srp_server_handle_service_update_result(
581        &self,
582        id: SrpServerServiceUpdateId,
583        result: Result,
584    ) {
585        unsafe {
586            otSrpServerHandleServiceUpdateResult(
587                self.as_ot_ptr(),
588                id.take(),
589                Error::from(result).into(),
590            )
591        }
592    }
593
594    fn srp_server_set_service_update_fn<'a, F>(&'a self, f: Option<F>)
595    where
596        F: FnMut(&'a ot::Instance, SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
597    {
598        unsafe extern "C" fn _ot_srp_server_service_update_handler<'a, F>(
599            id: otSrpServerServiceUpdateId,
600            host: *const otSrpServerHost,
601            timeout: u32,
602            context: *mut ::std::os::raw::c_void,
603        ) where
604            F: FnMut(SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
605        {
606            // Reconstitute a reference to our closure.
607            let sender = unsafe { &mut *(context as *mut F) };
608
609            sender(
610                SrpServerServiceUpdateId::new(id),
611                unsafe { SrpServerHost::ref_from_ot_ptr(host) }.unwrap(),
612                timeout,
613            )
614        }
615
616        // This helper func is just to allow us to get the type of the
617        // wrapper closure (`f_wrapped`) so we can pass that type
618        // as a type argument to `_ot_srp_server_service_update_handler`.
619        fn get_service_update_handler<'a, X>(_: &X) -> otSrpServerServiceUpdateHandler
620        where
621            X: FnMut(SrpServerServiceUpdateId, &'a SrpServerHost, u32) + 'a,
622        {
623            Some(_ot_srp_server_service_update_handler::<X>)
624        }
625
626        let (fn_ptr, fn_box, cb): (_, _, otSrpServerServiceUpdateHandler) = if let Some(mut f) = f {
627            // Grab a pointer to our ot::Instance for use below in the wrapper closure.
628            let ot_instance_ptr = self.as_ot_ptr();
629
630            // Wrap around `f` with a closure that fills in the `ot_instance` field, which we
631            // won't have access to inside of `_ot_srp_server_service_update_handler::<_>`.
632            let f_wrapped =
633                move |id: SrpServerServiceUpdateId, host: &'a SrpServerHost, timeout: u32| {
634                    // SAFETY: This ot::Instance will be passed to the original closure as
635                    //         an argument. We know that it is valid because:
636                    //         1. It is being called by the instance, so it must still be around.
637                    //         2. By design there are no mutable references to the `ot::Instance`
638                    //            in existence.
639                    let ot_instance =
640                        unsafe { ot::Instance::ref_from_ot_ptr(ot_instance_ptr) }.unwrap();
641                    f(ot_instance, id, host, timeout)
642                };
643
644            // Since we don't have a way to directly refer to the type of the closure `f_wrapped`,
645            // we need to use a helper function that can pass the type as a generic argument to
646            // `_ot_srp_server_service_update_handler::<X>` as `X`.
647            let service_update_handler = get_service_update_handler(&f_wrapped);
648
649            let mut x = Box::new(f_wrapped);
650
651            (
652                x.as_mut() as *mut _ as *mut ::std::os::raw::c_void,
653                Some(
654                    x as Box<
655                        dyn FnMut(ot::SrpServerServiceUpdateId, &'a ot::SrpServerHost, u32) + 'a,
656                    >,
657                ),
658                service_update_handler,
659            )
660        } else {
661            (std::ptr::null_mut() as *mut ::std::os::raw::c_void, None, None)
662        };
663
664        unsafe {
665            otSrpServerSetServiceUpdateHandler(self.as_ot_ptr(), cb, fn_ptr);
666
667            // Make sure our object eventually gets cleaned up.
668            // Here we must also transmute our closure to have a 'static lifetime.
669            // We need to do this because the borrow checker cannot infer the
670            // proper lifetime for the singleton instance backing, but
671            // this is guaranteed by the API.
672            self.borrow_backing().srp_server_service_update_fn.set(std::mem::transmute::<
673                Option<Box<dyn FnMut(SrpServerServiceUpdateId, &'a ot::SrpServerHost, u32) + 'a>>,
674                Option<Box<dyn FnMut(SrpServerServiceUpdateId, &ot::SrpServerHost, u32) + 'static>>,
675            >(fn_box));
676        }
677    }
678
679    fn parse_label_from_subtype_service_name(
680        &self,
681        subtype_service_name: &CStr,
682    ) -> Result<CString, Error> {
683        let mut bytes = [0 as c_char; 256];
684
685        // SAFETY: We are passing in valid pointers with a length one less than the array size.
686        Error::from(unsafe {
687            otSrpServerParseSubTypeServiceName(
688                subtype_service_name.as_ptr(),
689                (&mut bytes) as *mut c_char,
690                255,
691            )
692        })
693        .into_result()?;
694
695        // SAFETY: `bytes` is guaranteed to be zero terminated because of the size of the array.
696        Ok(unsafe { CStr::from_ptr(&bytes as *const c_char) }.to_owned())
697    }
698}