1use crate::{mut_override, stream::Stream};
12
13pub use crate::stream::Credentials as TurnCredentials;
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 fn builder() -> AgentBuilder {
47 AgentBuilder::default()
48 }
49
50 pub fn id(&self) -> u64 {
52 unsafe { crate::ffi::rice_agent_id(self.ffi) }
53 }
54
55 pub fn now(&self) -> u64 {
57 unsafe { crate::ffi::rice_agent_now(self.ffi) }
58 }
59
60 pub fn add_stream(&self) -> crate::stream::Stream {
72 unsafe { Stream::from_c_full(crate::ffi::rice_agent_add_stream(self.ffi)) }
73 }
74
75 pub fn stream(&self, id: usize) -> Option<crate::stream::Stream> {
77 let ret = unsafe { crate::ffi::rice_agent_get_stream(self.ffi, id) };
78 if ret.is_null() {
79 None
80 } else {
81 Some(crate::stream::Stream::from_c_full(ret))
82 }
83 }
84
85 pub fn close(&self, now_micros: u64) {
88 unsafe { crate::ffi::rice_agent_close(self.ffi, now_micros) }
89 }
90
91 pub fn controlling(&self) -> bool {
94 unsafe { crate::ffi::rice_agent_get_controlling(self.ffi) }
95 }
96
97 pub fn add_stun_server(
99 &self,
100 transport: crate::candidate::TransportType,
101 addr: crate::Address,
102 ) {
103 unsafe { crate::ffi::rice_agent_add_stun_server(self.ffi, transport.into(), addr.as_c()) }
104 }
105
106 pub fn add_turn_server(
108 &self,
109 transport: crate::candidate::TransportType,
110 addr: crate::Address,
111 credentials: TurnCredentials,
112 ) {
113 unsafe {
114 crate::ffi::rice_agent_add_turn_server(
115 self.ffi,
116 transport.into(),
117 addr.as_c(),
118 credentials.into_c_none(),
119 )
120 }
121 }
122
123 pub fn poll(&self, now_micros: u64) -> AgentPoll {
127 let mut ret = crate::ffi::RiceAgentPoll {
128 tag: crate::ffi::RICE_AGENT_POLL_CLOSED,
129 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
130 field1: core::mem::ManuallyDrop::new(
131 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_1 {
132 wait_until_micros: 0,
133 },
134 ),
135 },
136 };
137
138 unsafe {
139 crate::ffi::rice_agent_poll_init(&mut ret);
140 crate::ffi::rice_agent_poll(self.ffi, now_micros, &mut ret);
141 }
142
143 AgentPoll::from_c_full(ret)
144 }
145
146 pub fn poll_transmit(&self, now_micros: u64) -> Option<AgentTransmit> {
151 let mut ret = crate::ffi::RiceTransmit {
152 stream_id: 0,
153 transport: crate::ffi::RICE_TRANSPORT_TYPE_UDP,
154 from: core::ptr::null(),
155 to: core::ptr::null(),
156 data: crate::ffi::RiceDataImpl {
157 ptr: core::ptr::null_mut(),
158 size: 0,
159 },
160 };
161 unsafe { crate::ffi::rice_agent_poll_transmit(self.ffi, now_micros, &mut ret) }
162 if ret.from.is_null() || ret.to.is_null() {
163 return None;
164 }
165 Some(AgentTransmit::from_c_full(ret))
166 }
167 }
169
170#[derive(Debug, Default)]
172pub struct AgentBuilder {
173 trickle_ice: bool,
174 controlling: bool,
175}
176
177impl AgentBuilder {
178 pub fn trickle_ice(mut self, trickle_ice: bool) -> Self {
180 self.trickle_ice = trickle_ice;
181 self
182 }
183
184 pub fn controlling(mut self, controlling: bool) -> Self {
187 self.controlling = controlling;
188 self
189 }
190
191 pub fn build(self) -> Agent {
193 Agent {
194 ffi: unsafe { crate::ffi::rice_agent_new(self.controlling, self.trickle_ice) },
195 }
196 }
197}
198
199#[derive(Debug, Default)]
201pub enum AgentPoll {
202 #[default]
204 Closed,
205 WaitUntilMicros(u64),
207 AllocateSocket(AgentSocket),
210 RemoveSocket(AgentSocket),
213 SelectedPair(AgentSelectedPair),
215 ComponentStateChange(AgentComponentStateChange),
217 GatheredCandidate(AgentGatheredCandidate),
219 GatheringComplete(AgentGatheringComplete),
221}
222
223impl AgentPoll {
224 fn from_c_full(mut ffi: crate::ffi::RiceAgentPoll) -> Self {
225 unsafe {
226 let ret = match ffi.tag {
227 crate::ffi::RICE_AGENT_POLL_CLOSED => Self::Closed,
228 crate::ffi::RICE_AGENT_POLL_WAIT_UNTIL_MICROS => Self::WaitUntilMicros(
229 core::mem::ManuallyDrop::into_inner(ffi.field1.field1).wait_until_micros,
230 ),
231 crate::ffi::RICE_AGENT_POLL_ALLOCATE_SOCKET => {
232 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field2).allocate_socket;
233 Self::AllocateSocket(AgentSocket {
234 stream_id: ty.stream_id,
235 component_id: ty.component_id,
236 transport: ty.transport.into(),
237 from: crate::Address::from_c_full(mut_override(ty.from)),
238 to: crate::Address::from_c_full(mut_override(ty.to)),
239 })
240 }
241 crate::ffi::RICE_AGENT_POLL_REMOVE_SOCKET => {
242 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field3).remove_socket;
243 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
244 Self::RemoveSocket(AgentSocket {
245 stream_id: ty.stream_id,
246 component_id: ty.component_id,
247 transport: ty.transport.into(),
248 from: crate::Address::from_c_full(mut_override(ty.from)),
249 to: crate::Address::from_c_full(mut_override(ty.to)),
250 })
251 }
252 crate::ffi::RICE_AGENT_POLL_SELECTED_PAIR => {
253 let mut ty =
254 core::mem::ManuallyDrop::into_inner(ffi.field1.field4).selected_pair;
255 let local = crate::candidate::Candidate::from_c_none(&ty.local);
256 let remote = crate::candidate::Candidate::from_c_none(&ty.remote);
257 crate::ffi::rice_candidate_clear(&mut ty.local);
258 crate::ffi::rice_candidate_clear(&mut ty.remote);
259 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
260 Self::SelectedPair(AgentSelectedPair {
261 stream_id: ty.stream_id,
262 component_id: ty.component_id,
263 local,
264 remote,
265 })
266 }
267 crate::ffi::RICE_AGENT_POLL_COMPONENT_STATE_CHANGE => {
268 let ty = core::mem::ManuallyDrop::into_inner(ffi.field1.field5)
269 .component_state_change;
270 Self::ComponentStateChange(AgentComponentStateChange {
271 stream_id: ty.stream_id,
272 component_id: ty.component_id,
273 state: crate::component::ComponentConnectionState::from_c(ty.state),
274 })
275 }
276 crate::ffi::RICE_AGENT_POLL_GATHERED_CANDIDATE => {
277 let ty =
278 core::mem::ManuallyDrop::into_inner(ffi.field1.field6).gathered_candidate;
279 let stream_id = ty.stream_id;
280 let gathered = crate::stream::GatheredCandidate::from_c_full(ty.gathered);
281 ffi.tag = crate::ffi::RICE_AGENT_POLL_CLOSED;
282 Self::GatheredCandidate(AgentGatheredCandidate {
283 stream_id,
284 gathered,
285 })
286 }
287 crate::ffi::RICE_AGENT_POLL_GATHERING_COMPLETE => {
288 let ty =
289 core::mem::ManuallyDrop::into_inner(ffi.field1.field7).gathering_complete;
290 Self::GatheringComplete(AgentGatheringComplete {
291 stream_id: ty.stream_id,
292 component_id: ty.component_id,
293 })
294 }
295 tag => panic!("Unkown AgentPoll value {tag:x?}"),
296 };
297 ret
298 }
299 }
300}
301
302impl Drop for AgentPoll {
303 fn drop(&mut self) {
304 unsafe {
305 if let Self::GatheredCandidate(gathered) = self {
306 let mut ret = crate::ffi::RiceAgentPoll {
307 tag: crate::ffi::RICE_AGENT_POLL_GATHERED_CANDIDATE,
308 field1: crate::ffi::RiceAgentPoll__bindgen_ty_1 {
309 field6: core::mem::ManuallyDrop::new(
310 crate::ffi::RiceAgentPoll__bindgen_ty_1__bindgen_ty_6 {
311 gathered_candidate: crate::ffi::RiceAgentGatheredCandidate {
312 stream_id: gathered.stream_id,
313 gathered: crate::stream::GatheredCandidate::take(
314 &mut gathered.gathered,
315 )
316 .ffi,
317 },
318 },
319 ),
320 },
321 };
322 crate::ffi::rice_agent_poll_clear(&raw mut ret);
323 }
324 }
325 }
326}
327
328#[derive(Debug)]
330pub struct AgentTransmit {
331 pub stream_id: usize,
333 pub from: crate::Address,
335 pub to: crate::Address,
337 pub transport: crate::candidate::TransportType,
339 pub data: &'static [u8],
341}
342
343impl AgentTransmit {
344 pub(crate) fn from_c_full(ffi: crate::ffi::RiceTransmit) -> Self {
345 unsafe {
346 let data = ffi.data.ptr;
347 let len = ffi.data.size;
348 let data = core::slice::from_raw_parts(data, len);
349 AgentTransmit {
350 stream_id: ffi.stream_id,
351 from: crate::Address::from_c_full(mut_override(ffi.from)),
352 to: crate::Address::from_c_full(mut_override(ffi.to)),
353 transport: ffi.transport.into(),
354 data,
355 }
356 }
357 }
358}
359
360impl Drop for AgentTransmit {
361 fn drop(&mut self) {
362 unsafe {
363 let mut transmit = crate::ffi::RiceTransmit {
364 stream_id: self.stream_id,
365 from: core::ptr::null_mut(),
366 to: core::ptr::null_mut(),
367 transport: self.transport.into(),
368 data: crate::ffi::RiceDataImpl::to_c(self.data),
369 };
370 crate::ffi::rice_transmit_clear(&mut transmit);
371 }
372 }
373}
374
375#[derive(Debug)]
377pub struct AgentSocket {
378 pub stream_id: usize,
380 pub component_id: usize,
382 pub transport: crate::candidate::TransportType,
384 pub from: crate::Address,
386 pub to: crate::Address,
388}
389
390#[derive(Debug)]
392pub struct AgentSelectedPair {
393 pub stream_id: usize,
394 pub component_id: usize,
395 pub local: crate::candidate::Candidate,
396 pub remote: crate::candidate::Candidate,
397}
398
399#[derive(Debug)]
401#[repr(C)]
402pub struct AgentComponentStateChange {
403 pub stream_id: usize,
405 pub component_id: usize,
407 pub state: crate::component::ComponentConnectionState,
409}
410
411#[derive(Debug)]
413#[repr(C)]
414pub struct AgentGatheredCandidate {
415 pub stream_id: usize,
417 pub gathered: crate::stream::GatheredCandidate,
419}
420
421#[derive(Debug)]
423#[repr(C)]
424pub struct AgentGatheringComplete {
425 pub stream_id: usize,
427 pub component_id: usize,
429}
430
431#[derive(Debug)]
433#[repr(i32)]
434pub enum AgentError {
435 Failed = crate::ffi::RICE_ERROR_FAILED,
436 ResourceNotFound = crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND,
437 AlreadyInProgress = crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS,
438}
439
440impl core::fmt::Display for AgentError {
441 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
442 match self {
443 Self::Failed => write!(f, "Failed"),
444 Self::ResourceNotFound => write!(f, "Resource Not Found"),
445 Self::AlreadyInProgress => write!(f, "Already In Progress"),
446 }
447 }
448}
449
450impl AgentError {
451 pub(crate) fn from_c(value: crate::ffi::RiceError) -> Result<(), AgentError> {
452 match value {
453 crate::ffi::RICE_ERROR_SUCCESS => Ok(()),
454 crate::ffi::RICE_ERROR_FAILED => Err(AgentError::Failed),
455 crate::ffi::RICE_ERROR_RESOURCE_NOT_FOUND => Err(AgentError::ResourceNotFound),
456 crate::ffi::RICE_ERROR_ALREADY_IN_PROGRESS => Err(AgentError::AlreadyInProgress),
457 val => panic!("unknown RiceError value {val:x?}"),
458 }
459 }
460}