1use crate::prelude_internal::*;
6
7#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
11pub enum JoinerState {
12 Idle = OT_JOINER_STATE_IDLE as isize,
14
15 Discover = OT_JOINER_STATE_DISCOVER as isize,
17
18 Connect = OT_JOINER_STATE_CONNECT as isize,
20
21 Connected = OT_JOINER_STATE_CONNECTED as isize,
23
24 Entrust = OT_JOINER_STATE_ENTRUST as isize,
26
27 Joined = OT_JOINER_STATE_JOINED as isize,
29}
30
31impl From<otJoinerState> for JoinerState {
32 fn from(x: otJoinerState) -> Self {
33 use num::FromPrimitive;
34 Self::from_u32(x).unwrap_or_else(|| panic!("Unknown otJoinerState value: {x}"))
35 }
36}
37
38impl From<JoinerState> for otJoinerState {
39 fn from(x: JoinerState) -> Self {
40 x as otJoinerState
41 }
42}
43
44pub trait Joiner {
48 #[allow(clippy::too_many_arguments)]
51 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
52 &self,
53 pskd: &str,
54 provisioning_url: Option<&str>,
55 vendor_name: Option<&str>,
56 vendor_model: Option<&str>,
57 vendor_sw_version: Option<&str>,
58 vendor_data: Option<&str>,
59 callback: F,
60 ) -> Result;
61
62 fn joiner_stop(&self);
65
66 fn joiner_get_state(&self) -> JoinerState;
69
70 fn joiner_start_async(
75 &self,
76 pskd: &str,
77 provisioning_url: Option<&str>,
78 vendor_name: Option<&str>,
79 vendor_model: Option<&str>,
80 vendor_sw_version: Option<&str>,
81 vendor_data: Option<&str>,
82 ) -> futures::channel::oneshot::Receiver<Result> {
83 use futures::channel::oneshot::*;
84 let (sender, receiver) = channel();
85 let sender = std::sync::Arc::new(fuchsia_sync::Mutex::new(Some(sender)));
86 let sender_clone = sender.clone();
87 if let Err(err) = self.joiner_start(
88 pskd,
89 provisioning_url,
90 vendor_name,
91 vendor_model,
92 vendor_sw_version,
93 vendor_data,
94 move |result| {
95 let _ = sender_clone
96 .lock()
97 .take()
98 .and_then(move |x: Sender<Result>| x.send(result).ok());
99 },
100 ) {
101 sender.lock().take().and_then(move |x: Sender<Result>| x.send(Err(err)).ok());
102 }
103 receiver
104 }
105}
106
107impl<T: Joiner + Boxable> Joiner for ot::Box<T> {
108 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
109 &self,
110 pskd: &str,
111 provisioning_url: Option<&str>,
112 vendor_name: Option<&str>,
113 vendor_model: Option<&str>,
114 vendor_sw_version: Option<&str>,
115 vendor_data: Option<&str>,
116 callback: F,
117 ) -> Result {
118 self.as_ref().joiner_start(
119 pskd,
120 provisioning_url,
121 vendor_name,
122 vendor_model,
123 vendor_sw_version,
124 vendor_data,
125 callback,
126 )
127 }
128
129 fn joiner_stop(&self) {
130 self.as_ref().joiner_stop()
131 }
132
133 fn joiner_get_state(&self) -> JoinerState {
134 self.as_ref().joiner_get_state()
135 }
136}
137
138impl Joiner for Instance {
139 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
140 &self,
141 pskd: &str,
142 provisioning_url: Option<&str>,
143 vendor_name: Option<&str>,
144 vendor_model: Option<&str>,
145 vendor_sw_version: Option<&str>,
146 vendor_data: Option<&str>,
147 callback: F,
148 ) -> Result {
149 unsafe extern "C" fn _ot_joiner_callback(
150 error: otError,
151 context: *mut ::std::os::raw::c_void,
152 ) {
153 trace!("_ot_joiner_callback");
154
155 let instance =
157 unsafe { Instance::ref_from_ot_ptr(context as *mut otInstance).unwrap() };
158
159 if let Some(func) = instance.borrow_backing().joiner_fn.take() {
160 func(Error::from(error).into_result());
161 }
162 }
163
164 let pskd = CString::new(pskd).map_err(|_| Error::InvalidArgs)?;
165 let provisioning_url =
166 provisioning_url.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
167 let vendor_name =
168 vendor_name.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
169 let vendor_model =
170 vendor_model.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
171 let vendor_sw_version =
172 vendor_sw_version.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
173 let vendor_data =
174 vendor_data.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
175
176 let pskd_ptr = pskd.as_bytes_with_nul().as_ptr() as *const ::std::os::raw::c_char;
177 let provisioning_url_ptr =
178 provisioning_url.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
179 as *const ::std::os::raw::c_char;
180 let vendor_name_ptr =
181 vendor_name.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
182 as *const ::std::os::raw::c_char;
183 let vendor_model_ptr =
184 vendor_model.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
185 as *const ::std::os::raw::c_char;
186 let vendor_sw_version_ptr =
187 vendor_sw_version.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
188 as *const ::std::os::raw::c_char;
189 let vendor_data_ptr =
190 vendor_data.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
191 as *const ::std::os::raw::c_char;
192
193 let fn_box = Some(Box::new(callback) as Box<dyn FnOnce(Result) + 'a>);
194
195 let ret = Error::from(unsafe {
196 self.borrow_backing().joiner_fn.set(std::mem::transmute::<
202 Option<Box<dyn FnOnce(Result) + 'a>>,
203 Option<Box<dyn FnOnce(Result) + 'static>>,
204 >(fn_box));
205
206 otJoinerStart(
207 self.as_ot_ptr(),
208 pskd_ptr,
209 provisioning_url_ptr,
210 vendor_name_ptr,
211 vendor_model_ptr,
212 vendor_sw_version_ptr,
213 vendor_data_ptr,
214 Some(_ot_joiner_callback),
215 self.as_ot_ptr() as *mut ::std::os::raw::c_void,
216 )
217 })
218 .into_result();
219
220 if ret.is_err() {
221 self.borrow_backing().joiner_fn.take();
224 }
225
226 ret
227 }
228
229 fn joiner_stop(&self) {
230 unsafe { otJoinerStop(self.as_ot_ptr()) }
231
232 self.borrow_backing().joiner_fn.take();
234 }
235
236 fn joiner_get_state(&self) -> JoinerState {
237 unsafe { otJoinerGetState(self.as_ot_ptr()) }.into()
238 }
239}