@@ -4,15 +4,16 @@ use core::marker::PhantomData;
44use core:: net:: { Ipv6Addr , SocketAddrV6 } ;
55use core:: ptr:: addr_of_mut;
66
7- use :: log:: { debug, info, trace} ;
7+ use :: log:: { debug, info, trace, warn } ;
88
99use crate :: sys:: {
10- esp, esp_openthread_get_instance, otDnsTxtEntry, otError, otError_OT_ERROR_INVALID_ARGS,
11- otError_OT_ERROR_NO_BUFS, otIp6Address, otIp6Address__bindgen_ty_1, otSrpClientAddService,
12- otSrpClientClearHostAndServices, otSrpClientClearService, otSrpClientEnableAutoStartMode,
13- otSrpClientGetHostInfo, otSrpClientGetServerAddress, otSrpClientGetServices,
14- otSrpClientHostInfo, otSrpClientIsAutoStartModeEnabled, otSrpClientIsRunning,
15- otSrpClientItemState, otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_ADDING,
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,
1617 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REFRESHING,
1718 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REGISTERED,
1819 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_REMOVED,
@@ -21,7 +22,8 @@ use crate::sys::{
2122 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH,
2223 otSrpClientItemState_OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE, otSrpClientRemoveHostAndServices,
2324 otSrpClientRemoveService, otSrpClientService, otSrpClientSetHostAddresses,
24- otSrpClientSetHostName, otSrpClientStart, otSrpClientStop, EspError , ESP_ERR_INVALID_STATE ,
25+ otSrpClientSetHostName, otSrpClientStart, otSrpClientStop, otThreadErrorToString, EspError ,
26+ ESP_ERR_INVALID_STATE ,
2527} ;
2628
2729#[ cfg( not( esp_idf_version_major = "4" ) ) ]
@@ -31,7 +33,7 @@ use crate::sys::{
3133 otSrpClientSetTtl,
3234} ;
3335
34- use crate :: thread:: { ot_esp, EspThread , Mode , NetifMode , ThreadDriver } ;
36+ use crate :: thread:: { ot_esp, ot_esp_err , EspThread , Mode , NetifMode , ThreadDriver } ;
3537
3638/// The unique ID of a registered SRP service
3739pub type SrpServiceSlot = usize ;
@@ -634,9 +636,7 @@ where
634636 let slot = inner. srp . services . iter ( ) . position ( |service| !service. taken ) ;
635637
636638 let Some ( slot) = slot else {
637- //return ot_esp!(otError_OT_ERROR_NO_BUFS);
638- ot_esp ! ( otError_OT_ERROR_NO_BUFS) . unwrap ( ) ; // TODO
639- panic ! ( ) ;
639+ return Err ( ot_esp_err ( otError_OT_ERROR_NO_BUFS) ) ;
640640 } ;
641641
642642 let our_service = & mut inner. srp . services [ slot] ;
@@ -667,7 +667,7 @@ where
667667 ) -> Result < ( ) , EspError > {
668668 let mut inner = self . inner ( ) ;
669669
670- if slot > inner. srp . services . len ( ) || !inner. srp . services [ slot] . taken {
670+ if slot >= inner. srp . services . len ( ) || !inner. srp . services [ slot] . taken {
671671 ot_esp ! ( otError_OT_ERROR_INVALID_ARGS) ?;
672672 }
673673
@@ -879,7 +879,12 @@ where
879879}
880880
881881// TODO: Make these configurable with a feature
882- const SRP_SVCS : usize = 3 ;
882+ //
883+ // NOTE: A slot stays taken until the SRP client has propagated the service removal to
884+ // the SRP server, so the pool needs headroom over the number of services concurrently
885+ // published (a Matter node publishes one operational record per commissioned fabric,
886+ // plus a commissionable one while its commissioning window is open).
887+ const SRP_SVCS : usize = 6 ;
883888const SRP_SVC_BUF_SIZE : usize = 300 ;
884889const SRP_HOST_BUF_SIZE : usize = 300 ;
885890
@@ -930,12 +935,39 @@ impl OtSrp {
930935
931936 fn plat_srp_changed (
932937 & mut self ,
938+ error : otError ,
933939 host_info : & otSrpClientHostInfo ,
934940 _services : Option < & otSrpClientService > ,
935941 removed_services : Option < & otSrpClientService > ,
936942 ) {
937943 trace ! ( "Plat SRP changed callback" ) ;
938944
945+ if error != otError_OT_ERROR_NONE {
946+ // The SRP client keeps retrying on its own, but without this the failure
947+ // is completely invisible (i.e. services silently never get published)
948+ 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+ // The SRP server maps this from a `YXDOMAIN` response, which it returns
959+ // when the host name - or one of the service instance names - is already
960+ // registered there under a *different* ECDSA key. The client cannot
961+ // recover on its own: it will keep retrying until the stale registration
962+ // reaches the end of its key lease (14 days by default) or the server is
963+ // told to drop it.
964+ 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+
939971 self . cleanup ( host_info, removed_services) ;
940972 }
941973
@@ -944,7 +976,7 @@ impl OtSrp {
944976 }
945977
946978 pub ( crate ) unsafe extern "C" fn plat_c_srp_state_change_callback (
947- _error : otError ,
979+ error : otError ,
948980 host_info : * const crate :: sys:: otSrpClientHostInfo ,
949981 services : * const crate :: sys:: otSrpClientService ,
950982 removed_services : * const crate :: sys:: otSrpClientService ,
@@ -954,6 +986,7 @@ impl OtSrp {
954986 let srp = unsafe { srp. as_mut ( ) } . unwrap ( ) ;
955987
956988 srp. plat_srp_changed (
989+ error,
957990 unsafe { & * host_info } ,
958991 unsafe { services. as_ref ( ) } ,
959992 unsafe { removed_services. as_ref ( ) } ,
0 commit comments