1use crate::{candidate::TransportType, mut_override, stream::Stream};
12
13use sans_io_time::Instant;
14
15#[derive(Debug)]
17pub struct Agent {
18 ffi: *mut crate::ffi::RiceAgent,
19}
20
21unsafe impl Send for Agent {}
22unsafe impl Sync for Agent {}
23
24impl Clone for Agent {
25 fn clone(&self) -> Self {
26 Self {
27 ffi: unsafe { crate::ffi::rice_agent_ref(self.ffi) },
28 }
29 }
30}
31
32impl Drop for Agent {
33 fn drop(&mut self) {
34 unsafe { crate::ffi::rice_agent_unref(self.ffi) }
35 }
36}
37
38impl Default for Agent {
39 fn default() -> Self {
40 Agent::builder().build()
41 }
42}
43
44impl Agent {
45 pub(crate) fn from_c_full(ffi: *mut crate::ffi::RiceAgent) -> Self {
46 Self { ffi }
47 }
48
49 pub fn builder() -> AgentBuilder {
51 AgentBuilder::default()
52 }
53
54 pub fn id(&self) -> u64 {
56 unsafe { crate::ffi::rice_agent_id(self.ffi) }
57 }
58
59 pub fn add_stream(&self) -> crate::stream::Stream {
71 unsafe { Stream::from_c_full(crate::ffi::rice_agent_add_stream(self.ffi)) }
72 }
73
74 pub fn stream(&self, id: usize) -> Option<crate::stream::Stream> {
76 let ret = unsafe { crate::ffi::rice_agent_get_stream(self.ffi, id) };
77 if ret.is_null() {
78 None
79 } else {
80 Some(crate::stream::Stream::from_c_full(ret))
81 }
82 }
83
84 pub fn close(&self, now: Instant) {
87 unsafe { crate::ffi::rice_agent_close(self.ffi, now.as_nanos()) }
88 }
89
90 pub fn controlling(&self) -> bool {
93 unsafe { crate::ffi::rice_agent_get_controlling(self.ffi) }
94 }
95
96 pub fn add_stun_server(
98 &self,
99 transport: crate::candidate::TransportType,
100 addr: crate::Address,
101 ) {
102 unsafe { crate::ffi::rice_agent_add_stun_server(self.ffi, transport.into(), addr.as_c()) }
103 }
104
105 pub fn poll(&self, now: Instant) -> AgentPoll {
109 let mut ret = crate::ffi::RiceAgentPoll {
110 tag: crate::ffi::RICE_AGENT_POLL_CLOSED,
111 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
112 field1: core::mem::ManuallyDrop::new(
113 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_1 {
114 wait_until_nanos: 0,
115 },
116 ),
117 },
118 };
119
120 unsafe {
121 crate::ffi::rice_agent_poll_init(&mut ret);
122 crate::ffi::rice_agent_poll(self.ffi, now.as_nanos(), &mut ret);
123 }
124
125 AgentPoll::from_c_full(ret)
126 }
127
128 pub fn poll_transmit(&self, now: Instant) -> Option<AgentTransmit> {
133 let mut ret = crate::ffi::RiceTransmit {
134 stream_id: 0,
135 transport: crate::ffi::RICE_TRANSPORT_TYPE_UDP,
136 from: core::ptr::null(),
137 to: core::ptr::null(),
138 data: crate::ffi::RiceDataImpl {
139 ptr: core::ptr::null_mut(),
140 size: 0,
141 },
142 };
143 unsafe { crate::ffi::rice_agent_poll_transmit(self.ffi, now.as_nanos(), &mut ret) }
144 if ret.from.is_null() || ret.to.is_null() {
145 return None;
146 }
147 Some(AgentTransmit::from_c_full(ret))
148 }
149 }
151
152#[derive(Debug, Default)]
154pub struct AgentBuilder {
155 trickle_ice: bool,
156 controlling: bool,
157}
158
159impl AgentBuilder {
160 pub fn trickle_ice(mut self, trickle_ice: bool) -> Self {
162 self.trickle_ice = trickle_ice;
163 self
164 }
165
166 pub fn controlling(mut self, controlling: bool) -> Self {
169 self.controlling = controlling;
170 self
171 }
172
173 pub fn build(self) -> Agent {
175 Agent {
176 ffi: unsafe { crate::ffi::rice_agent_new(self.controlling, self.trickle_ice) },
177 }
178 }
179}
180
181#[derive(Debug, Default)]
183pub enum AgentPoll {
184 #[default]
186 Closed,
187 WaitUntilNanos(i64),
189 AllocateSocket(AgentSocket),
192 RemoveSocket(AgentSocket),
195 SelectedPair(AgentSelectedPair),
197 ComponentStateChange(AgentComponentStateChange),
199 GatheredCandidate(AgentGatheredCandidate),
201 GatheringComplete(AgentGatheringComplete),
203}
204
205impl AgentPoll {
206 fn from_c_full(mut ffi: crate::ffi::RiceAgentPoll) -> Self {
207 unsafe {
208 match ffi.tag {
209 crate::ffi::RICE_AGENT_POLL_CLOSED => Self::Closed,
210 crate::ffi::RICE_AGENT_POLL_WAIT_UNTIL_NANOS => Self::WaitUntilNanos(
211 core::mem::ManuallyDrop::into_inner(ffi.field1.field1).wait_until_nanos,
212 ),
213 crate::ffi::RICE_AGENT_POLL_ALLOCATE_SOCKET => {
214 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field2).allocate_socket;
215 Self::AllocateSocket(AgentSocket {
216 stream_id: ty.stream_id,
217 component_id: ty.component_id,
218 transport: ty.transport.into(),
219 from: crate::Address::from_c_full(mut_override(ty.from)),
220 to: crate::Address::from_c_full(mut_override(ty.to)),
221 })
222 }
223 crate::ffi::RICE_AGENT_POLL_REMOVE_SOCKET => {
224 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field3).remove_socket;
225 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
226 Self::RemoveSocket(AgentSocket {
227 stream_id: ty.stream_id,
228 component_id: ty.component_id,
229 transport: ty.transport.into(),
230 from: crate::Address::from_c_full(mut_override(ty.from)),
231 to: crate::Address::from_c_full(mut_override(ty.to)),
232 })
233 }
234 crate::ffi::RICE_AGENT_POLL_SELECTED_PAIR => {
235 let mut ty =
236 core::mem::ManuallyDrop::into_inner(ffi.field1.field4).selected_pair;
237 let local = crate::candidate::Candidate::from_c_none(&ty.local);
238 let remote = crate::candidate::Candidate::from_c_none(&ty.remote);
239 crate::ffi::rice_candidate_clear(&mut ty.local);
240 crate::ffi::rice_candidate_clear(&mut ty.remote);
241 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
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 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
280 Self::GatheredCandidate(AgentGatheredCandidate {
281 stream_id,
282 gathered,
283 })
284 }
285 crate::ffi::RICE_AGENT_POLL_GATHERING_COMPLETE => {
286 let ty =
287 core::mem::ManuallyDrop::into_inner(ffi.field1.field7).gathering_complete;
288 Self::GatheringComplete(AgentGatheringComplete {
289 stream_id: ty.stream_id,
290 component_id: ty.component_id,
291 })
292 }
293 tag => panic!("Unkown AgentPoll value {tag:x?}"),
294 }
295 }
296 }
297}
298
299impl Drop for AgentPoll {
300 fn drop(&mut self) {
301 unsafe {
302 if let Self::GatheredCandidate(gathered) = self {
303 let mut ret = crate::ffi::RiceAgentPoll {
304 tag: crate::ffi::RICE_AGENT_POLL_GATHERED_CANDIDATE,
305 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
306 field6: core::mem::ManuallyDrop::new(
307 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_6 {
308 gathered_candidate: crate::ffi::RiceAgentGatheredCandidate {
309 stream_id: gathered.stream_id,
310 gathered: crate::stream::GatheredCandidate::take(
311 &mut gathered.gathered,
312 )
313 .ffi,
314 },
315 },
316 ),
317 },
318 };
319 crate::ffi::rice_agent_poll_clear(&raw mut ret);
320 }
321 }
322 }
323}
324
325#[derive(Debug)]
327pub struct AgentTransmit {
328 pub stream_id: usize,
330 pub from: crate::Address,
332 pub to: crate::Address,
334 pub transport: crate::candidate::TransportType,
336 pub data: &'static [u8],
338}
339
340impl AgentTransmit {
341 pub(crate) fn from_c_full(ffi: crate::ffi::RiceTransmit) -> Self {
342 unsafe {
343 let data = ffi.data.ptr;
344 let len = ffi.data.size;
345 let data = core::slice::from_raw_parts(data, len);
346 AgentTransmit {
347 stream_id: ffi.stream_id,
348 from: crate::Address::from_c_full(mut_override(ffi.from)),
349 to: crate::Address::from_c_full(mut_override(ffi.to)),
350 transport: ffi.transport.into(),
351 data,
352 }
353 }
354 }
355}
356
357impl Drop for AgentTransmit {
358 fn drop(&mut self) {
359 unsafe {
360 let mut transmit = crate::ffi::RiceTransmit {
361 stream_id: self.stream_id,
362 from: core::ptr::null_mut(),
363 to: core::ptr::null_mut(),
364 transport: self.transport.into(),
365 data: crate::ffi::RiceDataImpl::to_c(self.data),
366 };
367 crate::ffi::rice_transmit_clear(&mut transmit);
368 }
369 }
370}
371
372#[derive(Debug)]
374pub struct AgentSocket {
375 pub stream_id: usize,
377 pub component_id: usize,
379 pub transport: crate::candidate::TransportType,
381 pub from: crate::Address,
383 pub to: crate::Address,
385}
386
387#[derive(Debug)]
389pub struct AgentSelectedPair {
390 pub stream_id: usize,
392 pub component_id: usize,
394 pub local: crate::candidate::Candidate,
396 pub remote: crate::candidate::Candidate,
398 pub turn: Option<SelectedTurn>,
400}
401
402#[derive(Debug)]
404pub struct SelectedTurn {
405 pub transport: TransportType,
407 pub local_addr: crate::Address,
409 pub remote_addr: crate::Address,
411}
412
413#[derive(Debug)]
415#[repr(C)]
416pub struct AgentComponentStateChange {
417 pub stream_id: usize,
419 pub component_id: usize,
421 pub state: crate::component::ComponentConnectionState,
423}
424
425#[derive(Debug)]
427#[repr(C)]
428pub struct AgentGatheredCandidate {
429 pub stream_id: usize,
431 pub gathered: crate::stream::GatheredCandidate,
433}
434
435#[derive(Debug)]
437#[repr(C)]
438pub struct AgentGatheringComplete {
439 pub stream_id: usize,
441 pub component_id: usize,
443}
444
445#[derive(Debug, Copy, Clone, PartialEq, Eq)]
447#[repr(i32)]
448pub enum AgentError {
449 Failed = crate::ffi::RICE_ERROR_FAILED,
451 ResourceNotFound = crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND,
453 AlreadyInProgress = crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS,
455}
456
457impl core::fmt::Display for AgentError {
458 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459 match self {
460 Self::Failed => write!(f, "Failed"),
461 Self::ResourceNotFound => write!(f, "Resource Not Found"),
462 Self::AlreadyInProgress => write!(f, "Already In Progress"),
463 }
464 }
465}
466
467impl AgentError {
468 pub(crate) fn from_c(value: crate::ffi::RiceError) -> Result<(), AgentError> {
469 match value {
470 crate::ffi::RICE_ERROR_SUCCESS => Ok(()),
471 crate::ffi::RICE_ERROR_FAILED => Err(AgentError::Failed),
472 crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND => Err(AgentError::ResourceNotFound),
473 crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS => Err(AgentError::AlreadyInProgress),
474 val => panic!("unknown RiceError value {val:x?}"),
475 }
476 }
477}