1use crate::{candidate::TransportType, mut_override, stream::Stream};
14
15use sans_io_time::Instant;
16
17#[derive(Debug)]
19pub struct Agent {
20 ffi: *mut crate::ffi::RiceAgent,
21}
22
23unsafe impl Send for Agent {}
24unsafe impl Sync for Agent {}
25
26impl Clone for Agent {
27 fn clone(&self) -> Self {
28 Self {
29 ffi: unsafe { crate::ffi::rice_agent_ref(self.ffi) },
30 }
31 }
32}
33
34impl Drop for Agent {
35 fn drop(&mut self) {
36 unsafe { crate::ffi::rice_agent_unref(self.ffi) }
37 }
38}
39
40impl Default for Agent {
41 fn default() -> Self {
42 Agent::builder().build()
43 }
44}
45
46impl Agent {
47 pub(crate) fn from_c_full(ffi: *mut crate::ffi::RiceAgent) -> Self {
48 Self { ffi }
49 }
50
51 pub fn builder() -> AgentBuilder {
53 AgentBuilder::default()
54 }
55
56 pub fn id(&self) -> u64 {
58 unsafe { crate::ffi::rice_agent_id(self.ffi) }
59 }
60
61 pub fn add_stream(&self) -> crate::stream::Stream {
73 unsafe { Stream::from_c_full(crate::ffi::rice_agent_add_stream(self.ffi)) }
74 }
75
76 pub fn stream(&self, id: usize) -> Option<crate::stream::Stream> {
78 let ret = unsafe { crate::ffi::rice_agent_get_stream(self.ffi, id) };
79 if ret.is_null() {
80 None
81 } else {
82 Some(crate::stream::Stream::from_c_full(ret))
83 }
84 }
85
86 pub fn close(&self, now: Instant) {
89 unsafe { crate::ffi::rice_agent_close(self.ffi, now.as_nanos()) }
90 }
91
92 pub fn controlling(&self) -> bool {
95 unsafe { crate::ffi::rice_agent_get_controlling(self.ffi) }
96 }
97
98 pub fn add_stun_server(
100 &self,
101 transport: crate::candidate::TransportType,
102 addr: crate::Address,
103 ) {
104 unsafe { crate::ffi::rice_agent_add_stun_server(self.ffi, transport.into(), addr.as_c()) }
105 }
106
107 pub fn poll(&self, now: Instant) -> AgentPoll {
111 let mut ret = crate::ffi::RiceAgentPoll {
112 tag: crate::ffi::RICE_AGENT_POLL_CLOSED,
113 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
114 field1: core::mem::ManuallyDrop::new(
115 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_1 {
116 wait_until_nanos: 0,
117 },
118 ),
119 },
120 };
121
122 unsafe {
123 crate::ffi::rice_agent_poll_init(&mut ret);
124 crate::ffi::rice_agent_poll(self.ffi, now.as_nanos(), &mut ret);
125 }
126
127 AgentPoll::from_c_full(ret)
128 }
129
130 pub fn poll_transmit(&self, now: Instant) -> Option<AgentTransmit> {
135 let mut ret = crate::ffi::RiceTransmit {
136 stream_id: 0,
137 transport: crate::ffi::RICE_TRANSPORT_TYPE_UDP,
138 from: core::ptr::null(),
139 to: core::ptr::null(),
140 data: crate::ffi::RiceDataImpl {
141 ptr: core::ptr::null_mut(),
142 size: 0,
143 },
144 };
145 unsafe { crate::ffi::rice_agent_poll_transmit(self.ffi, now.as_nanos(), &mut ret) }
146 if ret.from.is_null() || ret.to.is_null() {
147 return None;
148 }
149 Some(AgentTransmit::from_c_full(ret))
150 }
151 }
153
154#[derive(Debug, Default)]
156pub struct AgentBuilder {
157 trickle_ice: bool,
158 controlling: bool,
159}
160
161impl AgentBuilder {
162 pub fn trickle_ice(mut self, trickle_ice: bool) -> Self {
164 self.trickle_ice = trickle_ice;
165 self
166 }
167
168 pub fn controlling(mut self, controlling: bool) -> Self {
171 self.controlling = controlling;
172 self
173 }
174
175 pub fn build(self) -> Agent {
177 Agent {
178 ffi: unsafe { crate::ffi::rice_agent_new(self.controlling, self.trickle_ice) },
179 }
180 }
181}
182
183#[derive(Debug, Default)]
185pub enum AgentPoll {
186 #[default]
188 Closed,
189 WaitUntilNanos(i64),
191 AllocateSocket(AgentSocket),
194 RemoveSocket(AgentSocket),
197 SelectedPair(AgentSelectedPair),
199 ComponentStateChange(AgentComponentStateChange),
201 GatheredCandidate(AgentGatheredCandidate),
203 GatheringComplete(AgentGatheringComplete),
205}
206
207impl AgentPoll {
208 fn from_c_full(ffi: crate::ffi::RiceAgentPoll) -> Self {
209 unsafe {
210 match ffi.tag {
211 crate::ffi::RICE_AGENT_POLL_CLOSED => Self::Closed,
212 crate::ffi::RICE_AGENT_POLL_WAIT_UNTIL_NANOS => Self::WaitUntilNanos(
213 core::mem::ManuallyDrop::into_inner(ffi.field1.field1).wait_until_nanos,
214 ),
215 crate::ffi::RICE_AGENT_POLL_ALLOCATE_SOCKET => {
216 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field2).allocate_socket;
217 Self::AllocateSocket(AgentSocket {
218 stream_id: ty.stream_id,
219 component_id: ty.component_id,
220 transport: ty.transport.into(),
221 from: crate::Address::from_c_full(mut_override(ty.from)),
222 to: crate::Address::from_c_full(mut_override(ty.to)),
223 })
224 }
225 crate::ffi::RICE_AGENT_POLL_REMOVE_SOCKET => {
226 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field3).remove_socket;
227 Self::RemoveSocket(AgentSocket {
228 stream_id: ty.stream_id,
229 component_id: ty.component_id,
230 transport: ty.transport.into(),
231 from: crate::Address::from_c_full(mut_override(ty.from)),
232 to: crate::Address::from_c_full(mut_override(ty.to)),
233 })
234 }
235 crate::ffi::RICE_AGENT_POLL_SELECTED_PAIR => {
236 let mut ty =
237 core::mem::ManuallyDrop::into_inner(ffi.field1.field4).selected_pair;
238 let local = crate::candidate::Candidate::from_c_none(&ty.local);
239 let remote = crate::candidate::Candidate::from_c_none(&ty.remote);
240 crate::ffi::rice_candidate_clear(&mut ty.local);
241 crate::ffi::rice_candidate_clear(&mut ty.remote);
242 let turn = if !ty.local_turn_local_addr.is_null()
243 && !ty.local_turn_remote_addr.is_null()
244 {
245 Some(SelectedTurn {
246 transport: ty.local_turn_transport.into(),
247 local_addr: crate::Address::from_c_none(ty.local_turn_local_addr),
248 remote_addr: crate::Address::from_c_none(ty.local_turn_remote_addr),
249 })
250 } else {
251 None
252 };
253 crate::ffi::rice_address_free(mut_override(ty.local_turn_local_addr));
254 ty.local_turn_local_addr = core::ptr::null_mut();
255 crate::ffi::rice_address_free(mut_override(ty.local_turn_remote_addr));
256 ty.local_turn_remote_addr = core::ptr::null_mut();
257 Self::SelectedPair(AgentSelectedPair {
258 stream_id: ty.stream_id,
259 component_id: ty.component_id,
260 local,
261 remote,
262 turn,
263 })
264 }
265 crate::ffi::RICE_AGENT_POLL_COMPONENT_STATE_CHANGE => {
266 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field5)
267 .component_state_change;
268 Self::ComponentStateChange(AgentComponentStateChange {
269 stream_id: ty.stream_id,
270 component_id: ty.component_id,
271 state: crate::component::ComponentConnectionState::from_c(ty.state),
272 })
273 }
274 crate::ffi::RICE_AGENT_POLL_GATHERED_CANDIDATE => {
275 let ty =
276 core::mem::ManuallyDrop::into_inner(ffi.field1.field6).gathered_candidate;
277 let stream_id = ty.stream_id;
278 let gathered = crate::stream::GatheredCandidate::from_c_full(ty.gathered);
279 Self::GatheredCandidate(AgentGatheredCandidate {
280 stream_id,
281 gathered,
282 })
283 }
284 crate::ffi::RICE_AGENT_POLL_GATHERING_COMPLETE => {
285 let ty =
286 core::mem::ManuallyDrop::into_inner(ffi.field1.field7).gathering_complete;
287 Self::GatheringComplete(AgentGatheringComplete {
288 stream_id: ty.stream_id,
289 component_id: ty.component_id,
290 })
291 }
292 tag => panic!("Unkown AgentPoll value {tag:x?}"),
293 }
294 }
295 }
296}
297
298impl Drop for AgentPoll {
299 fn drop(&mut self) {
300 unsafe {
301 if let Self::GatheredCandidate(gathered) = self {
302 let mut ret = crate::ffi::RiceAgentPoll {
303 tag: crate::ffi::RICE_AGENT_POLL_GATHERED_CANDIDATE,
304 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
305 field6: core::mem::ManuallyDrop::new(
306 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_6 {
307 gathered_candidate: crate::ffi::RiceAgentGatheredCandidate {
308 stream_id: gathered.stream_id,
309 gathered: crate::stream::GatheredCandidate::take(
310 &mut gathered.gathered,
311 )
312 .ffi,
313 },
314 },
315 ),
316 },
317 };
318 crate::ffi::rice_agent_poll_clear(&raw mut ret);
319 }
320 }
321 }
322}
323
324#[derive(Debug)]
326pub struct AgentTransmit {
327 pub stream_id: usize,
329 pub from: crate::Address,
331 pub to: crate::Address,
333 pub transport: crate::candidate::TransportType,
335 pub data: &'static [u8],
337}
338
339impl AgentTransmit {
340 pub(crate) fn from_c_full(ffi: crate::ffi::RiceTransmit) -> Self {
341 unsafe {
342 let data = ffi.data.ptr;
343 let len = ffi.data.size;
344 let data = core::slice::from_raw_parts(data, len);
345 AgentTransmit {
346 stream_id: ffi.stream_id,
347 from: crate::Address::from_c_full(mut_override(ffi.from)),
348 to: crate::Address::from_c_full(mut_override(ffi.to)),
349 transport: ffi.transport.into(),
350 data,
351 }
352 }
353 }
354}
355
356impl Drop for AgentTransmit {
357 fn drop(&mut self) {
358 unsafe {
359 let mut transmit = crate::ffi::RiceTransmit {
360 stream_id: self.stream_id,
361 from: core::ptr::null_mut(),
362 to: core::ptr::null_mut(),
363 transport: self.transport.into(),
364 data: crate::ffi::RiceDataImpl::to_c(self.data),
365 };
366 crate::ffi::rice_transmit_clear(&mut transmit);
367 }
368 }
369}
370
371#[derive(Debug)]
373pub struct AgentSocket {
374 pub stream_id: usize,
376 pub component_id: usize,
378 pub transport: crate::candidate::TransportType,
380 pub from: crate::Address,
382 pub to: crate::Address,
384}
385
386#[derive(Debug)]
388pub struct AgentSelectedPair {
389 pub stream_id: usize,
391 pub component_id: usize,
393 pub local: crate::candidate::Candidate,
395 pub remote: crate::candidate::Candidate,
397 pub turn: Option<SelectedTurn>,
399}
400
401#[derive(Debug)]
403pub struct SelectedTurn {
404 pub transport: TransportType,
406 pub local_addr: crate::Address,
408 pub remote_addr: crate::Address,
410}
411
412#[derive(Debug)]
414#[repr(C)]
415pub struct AgentComponentStateChange {
416 pub stream_id: usize,
418 pub component_id: usize,
420 pub state: crate::component::ComponentConnectionState,
422}
423
424#[derive(Debug)]
426#[repr(C)]
427pub struct AgentGatheredCandidate {
428 pub stream_id: usize,
430 pub gathered: crate::stream::GatheredCandidate,
432}
433
434#[derive(Debug)]
436#[repr(C)]
437pub struct AgentGatheringComplete {
438 pub stream_id: usize,
440 pub component_id: usize,
442}
443
444#[derive(Debug, Copy, Clone, PartialEq, Eq)]
446#[repr(i32)]
447pub enum AgentError {
448 Failed = crate::ffi::RICE_ERROR_FAILED,
450 ResourceNotFound = crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND,
452 AlreadyInProgress = crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS,
454}
455
456impl core::fmt::Display for AgentError {
457 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
458 match self {
459 Self::Failed => write!(f, "Failed"),
460 Self::ResourceNotFound => write!(f, "Resource Not Found"),
461 Self::AlreadyInProgress => write!(f, "Already In Progress"),
462 }
463 }
464}
465
466impl AgentError {
467 pub(crate) fn from_c(value: crate::ffi::RiceError) -> Result<(), AgentError> {
468 match value {
469 crate::ffi::RICE_ERROR_SUCCESS => Ok(()),
470 crate::ffi::RICE_ERROR_FAILED => Err(AgentError::Failed),
471 crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND => Err(AgentError::ResourceNotFound),
472 crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS => Err(AgentError::AlreadyInProgress),
473 val => panic!("unknown RiceError value {val:x?}"),
474 }
475 }
476}