1use core::ffi::{c_void, CStr};
2use core::fmt::{self, Display};
3use core::marker::PhantomData;
4use core::net::{Ipv6Addr, SocketAddrV6};
5use core::ptr::addr_of_mut;
6
7use ::log::{debug, info, trace, warn};
8
9use crate::sys::{
10 esp, esp_openthread_get_instance, otDnsTxtEntry, otError, otError_OT_ERROR_DUPLICATED,
11 otError_OT_ERROR_INVALID_ARGS, otError_OT_ERROR_NONE, otError_OT_ERROR_NO_BUFS, otIp6Address,
12 otIp6Address__bindgen_ty_1, otSrpClientAddService, otSrpClientClearHostAndServices,
13 otSrpClientClearService, otSrpClientEnableAutoStartMode, otSrpClientGetHostInfo,
14 otSrpClientGetServerAddress, otSrpClientGetServices, otSrpClientHostInfo,
15 otSrpClientIsAutoStartModeEnabled, otSrpClientIsRunning, otSrpClientItemState,
16 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_ADDING,
17 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REFRESHING,
18 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REGISTERED,
19 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVED,
20 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVING,
21 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_ADD,
22 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH,
23 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE, otSrpClientRemoveHostAndServices,
24 otSrpClientRemoveService, otSrpClientService, otSrpClientSetHostAddresses,
25 otSrpClientSetHostName, otSrpClientStart, otSrpClientStop, otThreadErrorToString, EspError,
26 ESP_ERR_INVALID_STATE,
27};
28
29#[cfg(not(esp_idf_version_major = "4"))]
30use crate::sys::{
31 otSrpClientEnableAutoHostAddress, otSrpClientGetKeyLeaseInterval, otSrpClientGetLeaseInterval,
32 otSrpClientGetTtl, otSrpClientSetKeyLeaseInterval, otSrpClientSetLeaseInterval,
33 otSrpClientSetTtl,
34};
35
36use crate::thread::{ot_esp, ot_esp_err, EspThread, Mode, NetifMode, ThreadDriver};
37
38pub type SrpServiceSlot = usize;
40
41#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
43pub enum SrpState {
44 ToAdd,
46 Adding,
48 ToRefresh,
50 Refreshing,
52 ToRemove,
54 Removing,
56 Removed,
58 Registered,
60 Other(otSrpClientItemState),
62}
63
64impl Display for SrpState {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 Self::ToAdd => write!(f, "To add"),
68 Self::Adding => write!(f, "Adding"),
69 Self::ToRefresh => write!(f, "To refresh"),
70 Self::Refreshing => write!(f, "Refreshing"),
71 Self::ToRemove => write!(f, "To remove"),
72 Self::Removing => write!(f, "Removing"),
73 Self::Removed => write!(f, "Removed"),
74 Self::Registered => write!(f, "Registered"),
75 Self::Other(state) => write!(f, "Other ({state})"),
76 }
77 }
78}
79
80#[allow(non_upper_case_globals)]
81#[allow(non_snake_case)]
82impl From<otSrpClientItemState> for SrpState {
83 fn from(value: otSrpClientItemState) -> Self {
84 match value {
85 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_ADD => Self::ToAdd,
86 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_ADDING => Self::Adding,
87 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH => Self::ToRefresh,
88 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REFRESHING => Self::Refreshing,
89 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE => Self::ToRemove,
90 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVING => Self::Removing,
91 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVED => Self::Removed,
92 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REGISTERED => Self::Registered,
93 other => Self::Other(other),
94 }
95 }
96}
97
98#[derive(Debug, Clone, Eq, PartialEq, Hash)]
100pub struct SrpConf<'a> {
101 pub host_name: &'a str,
103 pub host_addrs: &'a [Ipv6Addr],
107 pub ttl: u32,
109 pub default_lease_secs: u32,
112 pub default_key_lease_secs: u32,
115}
116
117impl SrpConf<'_> {
118 pub const fn new() -> Self {
121 Self {
122 host_name: "ot-device",
123 host_addrs: &[],
124 ttl: 60,
125 default_lease_secs: 0,
126 default_key_lease_secs: 0,
127 }
128 }
129
130 fn store(&self, ot_srp: &mut otSrpClientHostInfo, buf: &mut [u8]) -> Result<(), EspError> {
131 let (addrs, buf) = align_min::<otIp6Address>(buf, self.host_addrs.len())?;
132
133 ot_srp.mName = store_str(self.host_name, buf)?.0.as_ptr();
134
135 for (index, ip) in self.host_addrs.iter().enumerate() {
136 let addr = &mut addrs[index];
137 addr.mFields.m8 = ip.octets();
138 }
139
140 ot_srp.mAddresses = if addrs.is_empty() {
141 core::ptr::null_mut()
142 } else {
143 addrs.as_ptr()
144 };
145 ot_srp.mNumAddresses = addrs.len() as _;
146
147 #[cfg(not(esp_idf_version_major = "4"))]
148 {
149 ot_srp.mAutoAddress = addrs.is_empty();
150 }
151
152 Ok(())
153 }
154}
155
156impl Default for SrpConf<'_> {
157 fn default() -> Self {
158 Self::new()
159 }
160}
161
162#[derive(Debug, Clone, Eq, PartialEq, Hash)]
164pub struct SrpService<'a, SI, TI> {
165 pub name: &'a str,
167 pub instance_name: &'a str,
169 pub subtype_labels: SI,
171 pub txt_entries: TI,
173 pub port: u16,
175 pub priority: u16,
177 pub weight: u16,
179 pub lease_secs: u32,
182 pub key_lease_secs: u32,
185}
186
187impl<'a, SI, TI> SrpService<'a, SI, TI>
188where
189 SI: Iterator<Item = &'a str> + Clone + 'a,
190 TI: Iterator<Item = (&'a str, &'a [u8])> + Clone + 'a,
191{
192 fn store(&self, ot_srp: &mut otSrpClientService, buf: &mut [u8]) -> Result<(), EspError> {
193 let subtype_labels_len = self.subtype_labels.clone().count();
194 let txt_entries_len = self.txt_entries.clone().count();
195
196 let (txt_entries, buf) = align_min::<otDnsTxtEntry>(buf, txt_entries_len)?;
197 let (subtype_labels, buf) = align_min::<*const char>(buf, subtype_labels_len + 1)?;
198
199 let (name, buf) = store_str(self.name, buf)?;
200 let (instance_name, buf) = store_str(self.instance_name, buf)?;
201
202 ot_srp.mName = name.as_ptr();
203 ot_srp.mInstanceName = instance_name.as_ptr();
204
205 let mut index = 0;
206 let mut buf = buf;
207
208 for subtype_label in self.subtype_labels.clone() {
209 let (subtype_label, rem_buf) = store_str(subtype_label, buf)?;
210
211 subtype_labels[index] = subtype_label.as_ptr() as *const _;
212
213 buf = rem_buf;
214 index += 1;
215 }
216
217 subtype_labels[index] = core::ptr::null();
218
219 index = 0;
220
221 for (key, value) in self.txt_entries.clone() {
222 let txt_entry = &mut txt_entries[index];
223
224 let (key, rem_buf) = store_str(key, buf)?;
225 let (value, rem_buf) = store_data(value, rem_buf)?;
226
227 txt_entry.mKey = key.as_ptr();
228 txt_entry.mValue = value.as_ptr();
229 txt_entry.mValueLength = value.len() as _;
230
231 buf = rem_buf;
232 index += 1;
233 }
234
235 ot_srp.mSubTypeLabels = subtype_labels.as_ptr() as *const _;
236 ot_srp.mTxtEntries = txt_entries.as_ptr();
237 ot_srp.mNumTxtEntries = txt_entries_len as _;
238 ot_srp.mPort = self.port;
239 ot_srp.mPriority = self.priority;
240 ot_srp.mWeight = self.weight;
241 #[cfg(not(esp_idf_version_major = "4"))]
242 {
243 ot_srp.mLease = self.lease_secs;
244 ot_srp.mKeyLease = self.key_lease_secs;
245 }
246 ot_srp.mState = 0;
247 ot_srp.mNext = core::ptr::null_mut();
248
249 Ok(())
250 }
251}
252
253impl<'a, SI, TI> Display for SrpService<'a, SI, TI>
254where
255 SI: Iterator<Item = &'a str> + Clone,
256 TI: Iterator<Item = (&'a str, &'a [u8])> + Clone,
257{
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 write!(
260 f,
261 "SRP Service {{name: {}, instance: {}, port: {}, priority: {}, weight: {}, lease: {}, keylease: {}, labels: [",
262 self.name,
263 self.instance_name,
264 self.port,
265 self.priority,
266 self.weight,
267 self.lease_secs,
268 self.key_lease_secs
269 )?;
270
271 for (index, label) in self.subtype_labels.clone().enumerate() {
272 if index > 0 {
273 write!(f, ", {label}")?;
274 } else {
275 write!(f, "{label}")?;
276 }
277 }
278
279 write!(f, "], txt: [")?;
280
281 for (index, value) in self.txt_entries.clone().enumerate() {
282 if index > 0 {
283 write!(f, ", {}: {:?}", value.0, value.1)?;
284 } else {
285 write!(f, "{}: {:?}", value.0, value.1)?;
286 }
287 }
288
289 write!(f, "]}}")
290 }
291}
292
293pub type OutSrpService<'a> = SrpService<'a, OutSrpSubtypeLabelsIter<'a>, OutSrpTxtEntriesIter<'a>>;
296
297#[derive(Clone)]
300pub struct OutSrpSubtypeLabelsIter<'a> {
301 ptr: *const *const u8,
302 index: usize,
303 _phantom: PhantomData<&'a ()>,
304}
305
306impl<'a> Iterator for OutSrpSubtypeLabelsIter<'a> {
307 type Item = &'a str;
308
309 fn next(&mut self) -> Option<Self::Item> {
310 if self.ptr.is_null() {
311 return None;
312 }
313
314 let label = unsafe { *self.ptr.add(self.index) };
315
316 if label.is_null() {
317 None
318 } else {
319 self.index += 1;
320 Some(unsafe { CStr::from_ptr(label as _) }.to_str().unwrap())
321 }
322 }
323}
324
325#[derive(Clone)]
328pub struct OutSrpTxtEntriesIter<'a> {
329 ptr: *const otDnsTxtEntry,
330 size: usize,
331 index: usize,
332 _phantom: PhantomData<&'a ()>,
333}
334
335impl<'a> Iterator for OutSrpTxtEntriesIter<'a> {
336 type Item = (&'a str, &'a [u8]);
337
338 fn next(&mut self) -> Option<Self::Item> {
339 if self.ptr.is_null() || self.index == self.size {
340 return None;
341 }
342
343 let entry = unsafe { self.ptr.add(self.index) };
344
345 self.index += 1;
346
347 let entry = unsafe { &*entry };
348
349 Some((
350 unsafe { CStr::from_ptr(entry.mKey) }.to_str().unwrap(),
351 unsafe { core::slice::from_raw_parts(entry.mValue, entry.mValueLength as _) },
352 ))
353 }
354}
355
356impl<'a> From<&'a otSrpClientService> for OutSrpService<'a> {
357 fn from(ot_srp: &'a otSrpClientService) -> Self {
358 #[allow(unused_mut)]
359 let mut this = Self {
360 name: if !ot_srp.mName.is_null() {
361 unsafe { CStr::from_ptr(ot_srp.mName) }.to_str().unwrap()
362 } else {
363 ""
364 },
365 instance_name: if !ot_srp.mInstanceName.is_null() {
366 unsafe { CStr::from_ptr(ot_srp.mInstanceName) }
367 .to_str()
368 .unwrap()
369 } else {
370 ""
371 },
372 subtype_labels: OutSrpSubtypeLabelsIter {
373 ptr: ot_srp.mSubTypeLabels as _,
374 index: 0,
375 _phantom: PhantomData,
376 },
377 txt_entries: OutSrpTxtEntriesIter {
378 ptr: ot_srp.mTxtEntries,
379 size: ot_srp.mNumTxtEntries as _,
380 index: 0,
381 _phantom: PhantomData,
382 },
383 port: ot_srp.mPort,
384 priority: ot_srp.mPriority,
385 weight: ot_srp.mWeight,
386 lease_secs: 0,
387 key_lease_secs: 0,
388 };
389
390 #[cfg(not(esp_idf_version_major = "4"))]
391 {
392 this.lease_secs = ot_srp.mLease;
393 this.key_lease_secs = ot_srp.mKeyLease;
394 }
395
396 this
397 }
398}
399
400impl<T> ThreadDriver<'_, T>
401where
402 T: Mode,
403{
404 pub fn srp_conf<F, R>(&self, f: F) -> Result<R, EspError>
409 where
410 F: FnOnce(&SrpConf, SrpState, bool) -> Result<R, EspError>,
411 {
412 let inner = self.inner();
413
414 let instance = unsafe { esp_openthread_get_instance() };
415
416 let info = unsafe { otSrpClientGetHostInfo(instance).as_ref() }.unwrap();
417
418 #[allow(unused_mut)]
419 let mut conf = SrpConf {
420 host_name: if !info.mName.is_null() {
421 unsafe { CStr::from_ptr(info.mName) }.to_str().unwrap()
422 } else {
423 ""
424 },
425 host_addrs: if info.mNumAddresses > 0 && !info.mAddresses.is_null() {
426 unsafe {
427 core::slice::from_raw_parts(
428 info.mAddresses as *const _,
429 info.mNumAddresses as _,
430 )
431 }
432 } else {
433 &[]
434 },
435 ttl: 0,
436 default_lease_secs: 0,
437 default_key_lease_secs: 0,
438 };
439
440 #[cfg(not(esp_idf_version_major = "4"))]
441 {
442 unsafe {
443 conf.ttl = otSrpClientGetTtl(instance);
444 conf.default_lease_secs = otSrpClientGetLeaseInterval(instance);
445 conf.default_key_lease_secs = otSrpClientGetKeyLeaseInterval(instance);
446 }
447 }
448
449 f(&conf, info.mState.into(), !inner.srp.conf_taken)
450 }
451
452 pub fn srp_is_empty(&self) -> Result<bool, EspError> {
454 let inner = self.inner();
455
456 Ok(!inner.srp.conf_taken && inner.srp.services.iter().all(|service| !service.taken))
457 }
458
459 pub fn srp_set_conf(&self, conf: &SrpConf) -> Result<(), EspError> {
469 let mut inner = self.inner();
470
471 let instance = unsafe { esp_openthread_get_instance() };
472
473 if inner.srp.conf_taken {
474 esp!(ESP_ERR_INVALID_STATE)?;
475 }
476
477 #[cfg(not(esp_idf_version_major = "4"))]
478 unsafe {
479 otSrpClientSetLeaseInterval(instance, conf.default_lease_secs);
480 otSrpClientSetKeyLeaseInterval(instance, conf.default_key_lease_secs);
481 otSrpClientSetTtl(instance, conf.ttl);
482 }
483
484 let mut srp_conf = otSrpClientHostInfo {
485 mName: core::ptr::null(),
486 mAddresses: core::ptr::null(),
487 mNumAddresses: 0,
488 #[cfg(not(esp_idf_version_major = "4"))]
489 mAutoAddress: true,
490 mState: 0,
491 };
492
493 conf.store(&mut srp_conf, &mut inner.srp.conf_buf)?;
494 inner.srp.conf_taken = true;
495
496 ot_esp!(unsafe { otSrpClientSetHostName(instance, srp_conf.mName) })?;
497
498 if !conf.host_addrs.is_empty() {
499 ot_esp!(unsafe {
500 otSrpClientSetHostAddresses(instance, srp_conf.mAddresses, srp_conf.mNumAddresses)
501 })?;
502 } else {
503 #[cfg(not(esp_idf_version_major = "4"))]
504 {
505 ot_esp!(unsafe { otSrpClientEnableAutoHostAddress(instance) })?;
506 }
507 }
508
509 Ok(())
510 }
511
512 pub fn srp_running(&self) -> Result<bool, EspError> {
514 let _lock = self.inner();
515
516 Ok(unsafe { otSrpClientIsRunning(esp_openthread_get_instance()) })
517 }
518
519 pub fn srp_autostart_enabled(&self) -> Result<bool, EspError> {
521 let _lock = self.inner();
522
523 Ok(unsafe { otSrpClientIsAutoStartModeEnabled(esp_openthread_get_instance()) })
524 }
525
526 pub fn srp_autostart(&self) -> Result<(), EspError> {
528 let mut inner = self.inner();
529
530 let instance = unsafe { esp_openthread_get_instance() };
531
532 let srp = &mut inner.srp;
533
534 unsafe {
535 otSrpClientEnableAutoStartMode(
536 instance,
537 Some(OtSrp::plat_c_srp_auto_start_callback),
538 srp as *mut _ as *mut _,
539 );
540 }
541
542 Ok(())
543 }
544
545 pub fn srp_start(&self, server_addr: SocketAddrV6) -> Result<(), EspError> {
550 let _lock = self.inner();
551
552 ot_esp!(unsafe {
553 otSrpClientStart(esp_openthread_get_instance(), &to_ot_addr(&server_addr))
554 })
555 }
556
557 pub fn srp_stop(&self) -> Result<(), EspError> {
559 let _lock = self.inner();
560
561 unsafe {
562 otSrpClientStop(esp_openthread_get_instance());
563 }
564
565 Ok(())
566 }
567
568 pub fn srp_server_addr(&self) -> Result<Option<SocketAddrV6>, EspError> {
571 let _lock = self.inner();
572
573 let addr =
574 unsafe { otSrpClientGetServerAddress(esp_openthread_get_instance()).as_ref() }.unwrap();
575 let addr = to_sock_addr(&addr.mAddress, addr.mPort, 0);
576
577 Ok((!addr.ip().is_unspecified()).then_some(addr))
580 }
581
582 pub fn srp_services<F>(&self, mut f: F) -> Result<(), EspError>
588 where
589 F: FnMut(Option<(&OutSrpService<'_>, SrpState, SrpServiceSlot)>),
590 {
591 let inner = self.inner();
592
593 let mut service_ptr: *const otSrpClientService =
594 unsafe { otSrpClientGetServices(esp_openthread_get_instance()) };
595
596 while !service_ptr.is_null() {
597 let service = unsafe { &*service_ptr };
598
599 let slot = inner
600 .srp
601 .services
602 .iter()
603 .position(|s| core::ptr::eq(&s.service, service))
604 .unwrap();
605
606 f(Some((&service.into(), service.mState.into(), slot)));
607
608 service_ptr = service.mNext;
609 }
610
611 f(None);
612
613 Ok(())
614 }
615
616 pub fn srp_add_service<'a, SI, TI>(
627 &self,
628 service: &'a SrpService<'a, SI, TI>,
629 ) -> Result<SrpServiceSlot, EspError>
630 where
631 SI: Iterator<Item = &'a str> + Clone + 'a,
632 TI: Iterator<Item = (&'a str, &'a [u8])> + Clone + 'a,
633 {
634 let mut inner = self.inner();
635
636 let slot = inner.srp.services.iter().position(|service| !service.taken);
637
638 let Some(slot) = slot else {
639 return Err(ot_esp_err(otError_OT_ERROR_NO_BUFS));
640 };
641
642 let our_service = &mut inner.srp.services[slot];
643
644 service.store(&mut our_service.service, &mut our_service.buf)?;
645
646 ot_esp!(unsafe {
647 otSrpClientAddService(esp_openthread_get_instance(), &mut our_service.service)
648 })?;
649
650 debug!("Service added");
651
652 our_service.taken = true;
653
654 Ok(slot)
655 }
656
657 pub fn srp_remove_service(
664 &self,
665 slot: SrpServiceSlot,
666 immediate: bool,
667 ) -> Result<(), EspError> {
668 let mut inner = self.inner();
669
670 if slot >= inner.srp.services.len() || !inner.srp.services[slot].taken {
671 ot_esp!(otError_OT_ERROR_INVALID_ARGS)?;
672 }
673
674 let service = &mut inner.srp.services[slot];
675
676 if immediate {
677 ot_esp!(unsafe {
678 otSrpClientClearService(esp_openthread_get_instance(), &mut service.service)
679 })?;
680 service.taken = false;
681 debug!("Service {slot} cleared immeidately");
682 } else {
683 ot_esp!(unsafe {
684 otSrpClientRemoveService(esp_openthread_get_instance(), &mut service.service)
685 })?;
686 debug!("Service {slot} scheduled for removal");
687 }
688
689 Ok(())
690 }
691
692 pub fn srp_remove_all(&self, immediate: bool) -> Result<(), EspError> {
698 let mut inner = self.inner();
699
700 let instance = unsafe { esp_openthread_get_instance() };
701
702 if immediate {
703 unsafe {
704 otSrpClientClearHostAndServices(instance);
705 }
706
707 inner.srp.conf_taken = false;
708 for service in &mut inner.srp.services {
709 service.taken = false;
710 }
711
712 debug!("Hostname and all services cleared immediately");
713 } else {
714 ot_esp!(unsafe { otSrpClientRemoveHostAndServices(instance, false, true) })?;
715 debug!("Hostname and all services scheduled for removal");
716 }
717
718 Ok(())
719 }
720
721 }
743
744impl<T> EspThread<'_, T>
745where
746 T: NetifMode,
747{
748 pub fn srp_conf<F, R>(&self, f: F) -> Result<R, EspError>
753 where
754 F: FnOnce(&SrpConf, SrpState, bool) -> Result<R, EspError>,
755 {
756 self.driver().srp_conf(f)
757 }
758
759 pub fn srp_is_empty(&self) -> Result<bool, EspError> {
761 self.driver().srp_is_empty()
762 }
763
764 pub fn srp_set_conf(&self, conf: &SrpConf) -> Result<(), EspError> {
774 self.driver().srp_set_conf(conf)
775 }
776
777 pub fn srp_running(&self) -> Result<bool, EspError> {
779 self.driver().srp_running()
780 }
781
782 pub fn srp_autostart_enabled(&self) -> Result<bool, EspError> {
784 self.driver().srp_autostart_enabled()
785 }
786
787 pub fn srp_autostart(&self) -> Result<(), EspError> {
789 self.driver().srp_autostart()
790 }
791
792 pub fn srp_start(&self, server_addr: SocketAddrV6) -> Result<(), EspError> {
797 self.driver().srp_start(server_addr)
798 }
799
800 pub fn srp_stop(&self) -> Result<(), EspError> {
802 self.driver().srp_stop()
803 }
804
805 pub fn srp_server_addr(&self) -> Result<Option<SocketAddrV6>, EspError> {
808 self.driver().srp_server_addr()
809 }
810
811 pub fn srp_services<F>(&self, f: F) -> Result<(), EspError>
817 where
818 F: FnMut(Option<(&OutSrpService<'_>, SrpState, SrpServiceSlot)>),
819 {
820 self.driver().srp_services(f)
821 }
822
823 pub fn srp_add_service<'a, SI, TI>(
834 &self,
835 service: &'a SrpService<'a, SI, TI>,
836 ) -> Result<SrpServiceSlot, EspError>
837 where
838 SI: Iterator<Item = &'a str> + Clone + 'a,
839 TI: Iterator<Item = (&'a str, &'a [u8])> + Clone + 'a,
840 {
841 self.driver().srp_add_service(service)
842 }
843
844 pub fn srp_remove_service(
851 &self,
852 slot: SrpServiceSlot,
853 immediate: bool,
854 ) -> Result<(), EspError> {
855 self.driver().srp_remove_service(slot, immediate)
856 }
857
858 pub fn srp_remove_all(&self, immediate: bool) -> Result<(), EspError> {
864 self.driver().srp_remove_all(immediate)
865 }
866
867 }
880
881const SRP_SVCS: usize = 6;
888const SRP_SVC_BUF_SIZE: usize = 300;
889const SRP_HOST_BUF_SIZE: usize = 300;
890
891pub(crate) struct OtSrp {
892 conf_taken: bool,
893 conf_buf: [u8; SRP_HOST_BUF_SIZE],
894 services: [OtSrpService; SRP_SVCS],
895}
896
897impl OtSrp {
898 pub(crate) unsafe fn init(this: *mut Self) {
899 unsafe {
900 addr_of_mut!((*this).conf_taken).write(false);
901 addr_of_mut!((*this).conf_buf).write_bytes(0, 1);
902
903 for index in 0..SRP_SVCS {
904 let service = addr_of_mut!((*this).services[index]);
905 OtSrpService::init(service);
906 }
907 }
908 }
909
910 fn cleanup(
912 &mut self,
913 host_info: &otSrpClientHostInfo,
914 mut removed_services: Option<&otSrpClientService>,
915 ) {
916 if host_info.mState == otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVED {
917 self.conf_taken = false;
918 info!("SRP host removed");
919 }
920
921 while let Some(service) = removed_services {
922 let (slot, our_service) = self
923 .services
924 .iter_mut()
925 .enumerate()
926 .find(|(_, s)| core::ptr::eq(&s.service, service))
927 .unwrap();
928
929 removed_services = unsafe { service.mNext.as_ref() };
930
931 our_service.taken = false;
932 info!("SRP service at slot {slot} removed");
933 }
934 }
935
936 fn plat_srp_changed(
937 &mut self,
938 error: otError,
939 host_info: &otSrpClientHostInfo,
940 _services: Option<&otSrpClientService>,
941 removed_services: Option<&otSrpClientService>,
942 ) {
943 trace!("Plat SRP changed callback");
944
945 if error != otError_OT_ERROR_NONE {
946 let reason = unsafe { CStr::from_ptr(otThreadErrorToString(error)) }
949 .to_str()
950 .unwrap_or("Unknown");
951
952 warn!(
953 "SRP update failed: {reason} ({error}); host is {}",
954 SrpState::from(host_info.mState)
955 );
956
957 if error == otError_OT_ERROR_DUPLICATED {
958 warn!(
965 "SRP name is registered on the server under a different key; \
966 the SRP key of this device changed, or another device claimed the name"
967 );
968 }
969 }
970
971 self.cleanup(host_info, removed_services);
972 }
973
974 fn plat_srp_auto_started(&mut self) {
975 }
977
978 pub(crate) unsafe extern "C" fn plat_c_srp_state_change_callback(
979 error: otError,
980 host_info: *const crate::sys::otSrpClientHostInfo,
981 services: *const crate::sys::otSrpClientService,
982 removed_services: *const crate::sys::otSrpClientService,
983 context: *mut c_void,
984 ) {
985 let srp = context as *mut OtSrp;
986 let srp = unsafe { srp.as_mut() }.unwrap();
987
988 srp.plat_srp_changed(
989 error,
990 unsafe { &*host_info },
991 unsafe { services.as_ref() },
992 unsafe { removed_services.as_ref() },
993 );
994 }
995
996 pub(crate) unsafe extern "C" fn plat_c_srp_auto_start_callback(
997 _server_sock_addr: *const crate::sys::otSockAddr,
998 context: *mut c_void,
999 ) {
1000 let srp = context as *mut OtSrp;
1001 let srp = unsafe { srp.as_mut() }.unwrap();
1002
1003 srp.plat_srp_auto_started();
1004 }
1005}
1006
1007struct OtSrpService {
1008 taken: bool,
1009 service: otSrpClientService,
1010 buf: [u8; SRP_SVC_BUF_SIZE],
1011}
1012
1013impl OtSrpService {
1014 pub(crate) unsafe fn init(this: *mut Self) {
1015 unsafe {
1016 addr_of_mut!((*this).taken).write(false);
1017 addr_of_mut!((*this).buf).write_bytes(0, 1);
1018 addr_of_mut!((*this).service).write_bytes(0, 1);
1019 }
1020 }
1021}
1022
1023fn align_min<T>(buf: &mut [u8], count: usize) -> Result<(&mut [T], &mut [u8]), EspError> {
1024 if count == 0 || core::mem::size_of::<T>() == 0 {
1025 return Ok((&mut [], buf));
1026 }
1027
1028 let (t_leading_buf0, t_buf, _) = unsafe { buf.align_to_mut::<T>() };
1029 if t_buf.len() < count {
1030 ot_esp!(otError_OT_ERROR_NO_BUFS)?;
1031 }
1032
1033 let t_buf = &mut t_buf[..count];
1035 let t_leading_buf0_len = t_leading_buf0.len();
1036 let t_buf_size = core::mem::size_of_val(t_buf);
1037
1038 let (buf0, remaining_buf) = buf.split_at_mut(t_leading_buf0_len + t_buf_size);
1039
1040 let (t_leading_buf, t_buf, t_remaining_buf) = unsafe { buf0.align_to_mut::<T>() };
1041 assert_eq!(t_leading_buf0_len, t_leading_buf.len());
1042 assert_eq!(t_buf.len(), count);
1043 assert!(t_remaining_buf.is_empty());
1044
1045 Ok((t_buf, remaining_buf))
1046}
1047
1048fn store_str<'t>(str: &str, buf: &'t mut [u8]) -> Result<(&'t CStr, &'t mut [u8]), EspError> {
1049 let data_len = str.len() + 1;
1050
1051 if data_len > buf.len() {
1052 ot_esp!(otError_OT_ERROR_NO_BUFS)?;
1053 }
1054
1055 let (str_buf, rem_buf) = buf.split_at_mut(data_len);
1056
1057 str_buf[..str.len()].copy_from_slice(str.as_bytes());
1058 str_buf[str.len()] = 0;
1059
1060 Ok((
1061 CStr::from_bytes_with_nul(&str_buf[..data_len]).unwrap(),
1062 rem_buf,
1063 ))
1064}
1065
1066fn store_data<'t>(data: &[u8], buf: &'t mut [u8]) -> Result<(&'t [u8], &'t mut [u8]), EspError> {
1067 if data.len() > buf.len() {
1068 ot_esp!(otError_OT_ERROR_NO_BUFS)?;
1069 }
1070
1071 let (data_buf, rem_buf) = buf.split_at_mut(data.len());
1072
1073 data_buf[..data.len()].copy_from_slice(data);
1074
1075 Ok((data_buf, rem_buf))
1076}
1077
1078fn to_sock_addr(addr: &otIp6Address, port: u16, netif: u32) -> SocketAddrV6 {
1080 SocketAddrV6::new(Ipv6Addr::from(unsafe { addr.mFields.m8 }), port, 0, netif)
1081}
1082
1083fn to_ot_addr(addr: &SocketAddrV6) -> crate::sys::otSockAddr {
1085 crate::sys::otSockAddr {
1086 mAddress: otIp6Address {
1087 mFields: otIp6Address__bindgen_ty_1 {
1088 m8: addr.ip().octets(),
1089 },
1090 },
1091 mPort: addr.port(),
1092 }
1093}