1use alloc::vec::Vec;
14use core::net::SocketAddr;
15
16use crate::gathering::GatherPoll;
17use stun_proto::Instant;
18use stun_proto::agent::{StunError, Transmit};
19use stun_proto::types::data::Data;
20
21use crate::agent::{Agent, AgentError};
22use crate::component::{Component, ComponentMut, ComponentState, GatherProgress};
23use crate::conncheck::{HandleRecvReply, PendingRecv, RequestRto};
24
25use crate::candidate::{Candidate, TransportType};
26pub use crate::conncheck::Credentials;
29pub use crate::gathering::GatheredCandidate;
30
31use tracing::{info, trace};
32
33#[derive(Debug, Clone)]
35#[repr(C)]
36pub struct Stream<'a> {
37 agent: &'a crate::agent::Agent,
38 id: usize,
39}
40
41impl<'a> Stream<'a> {
42 pub(crate) fn from_agent(agent: &'a Agent, id: usize) -> Self {
43 Self { agent, id }
44 }
45
46 pub fn agent(&self) -> &'a crate::agent::Agent {
48 self.agent
49 }
50
51 pub fn id(&self) -> usize {
64 self.id
65 }
66
67 pub fn component(&self, index: usize) -> Option<Component<'_>> {
99 if index < 1 {
100 return None;
101 }
102 let stream_state = self.agent.stream_state(self.id)?;
103 if let Some(Some(_component)) = stream_state.components.get(index - 1) {
104 Some(Component::from_stream(self.agent, self.id, index))
105 } else {
106 None
107 }
108 }
109
110 pub fn local_credentials(&self) -> Option<Credentials> {
125 let stream_state = self.agent.stream_state(self.id)?;
126 stream_state.local_credentials()
127 }
128
129 pub fn remote_credentials(&self) -> Option<Credentials> {
144 let stream_state = self.agent.stream_state(self.id)?;
145 stream_state.remote_credentials()
146 }
147
148 pub fn local_candidates(&self) -> impl Iterator<Item = &'_ Candidate> + '_ {
150 let stream_state = self.agent.stream_state(self.id).unwrap();
151 let checklist = self
152 .agent
153 .checklistset
154 .list(stream_state.checklist_id)
155 .unwrap();
156 checklist.local_candidates()
157 }
158
159 pub fn remote_candidates(&self) -> &[Candidate] {
186 let stream_state = self.agent.stream_state(self.id).unwrap();
187 let checklist_id = stream_state.checklist_id;
188 let checklist = self.agent.checklistset.list(checklist_id).unwrap();
189 checklist.remote_candidates()
190 }
191
192 pub fn component_ids_iter(&self) -> impl Iterator<Item = usize> + '_ {
194 let stream = self.agent.stream_state(self.id).unwrap();
195 stream
196 .components
197 .iter()
198 .flatten()
199 .map(|component| component.id)
200 }
201}
202
203#[derive(Debug)]
205#[repr(C)]
206pub struct StreamMut<'a> {
207 agent: &'a mut crate::agent::Agent,
208 id: usize,
209}
210
211impl<'a> core::ops::Deref for StreamMut<'a> {
212 type Target = Stream<'a>;
213
214 fn deref(&self) -> &Self::Target {
215 unsafe { core::mem::transmute(self) }
216 }
217}
218
219impl<'a> StreamMut<'a> {
220 pub(crate) fn from_agent(agent: &'a mut Agent, id: usize) -> Self {
221 Self { agent, id }
222 }
223
224 pub fn mut_agent(&'a mut self) -> &'a mut crate::agent::Agent {
226 self.agent
227 }
228
229 pub fn add_component(&mut self) -> Result<usize, AgentError> {
247 let stream_state = self
248 .agent
249 .mut_stream_state(self.id)
250 .ok_or(AgentError::ResourceNotFound)?;
251 let component_id = stream_state.add_component()?;
252 let checklist_id = stream_state.checklist_id;
253 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
254 checklist.add_component(component_id);
255 Ok(component_id)
256 }
257
258 pub fn mut_component(&mut self, index: usize) -> Option<ComponentMut<'_>> {
261 if index < 1 {
262 return None;
263 }
264 let stream_state = self.agent.mut_stream_state(self.id)?;
265 if let Some(Some(_component)) = stream_state.components.get_mut(index - 1) {
266 Some(ComponentMut::from_stream(self.agent, self.id, index))
267 } else {
268 None
269 }
270 }
271
272 pub fn set_local_credentials(&mut self, credentials: Credentials) {
286 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
287 stream_state.set_local_credentials(credentials.clone());
288 let checklist_id = stream_state.checklist_id;
289 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
290 checklist.set_local_credentials(credentials);
291 }
292
293 pub fn set_remote_credentials(&mut self, credentials: Credentials) {
307 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
308 stream_state.set_remote_credentials(credentials.clone());
309 let checklist_id = stream_state.checklist_id;
310 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
311 checklist.set_remote_credentials(credentials);
312 }
313
314 #[tracing::instrument(
338 skip(self, cand),
339 fields(
340 stream.id = self.id
341 )
342 )]
343 pub fn add_remote_candidate(&mut self, cand: Candidate) {
344 info!("adding remote candidate {:?}", cand);
345 let Some(stream_state) = self.agent.mut_stream_state(self.id) else {
346 return;
347 };
348 let checklist_id = stream_state.checklist_id;
349 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
350 checklist.add_remote_candidate(cand);
351 }
352
353 #[tracing::instrument(
357 name = "stream_handle_incoming_data",
358 skip(self, component_id, transmit),
359 fields(
360 stream.id = self.id,
361 component.id = component_id,
362 )
363 )]
364 pub fn handle_incoming_data<T: AsRef<[u8]> + core::fmt::Debug>(
365 &mut self,
366 component_id: usize,
367 transmit: Transmit<T>,
368 now: Instant,
369 ) -> HandleRecvReply<T> {
370 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
371 let checklist_id = stream_state.checklist_id;
372 let ret = stream_state.handle_incoming_data(component_id, &transmit, now);
374 if ret.handled {
375 return ret;
376 }
377 if stream_state.component_state(component_id).is_none() {
378 return ret;
379 };
380
381 self.agent
383 .checklistset
384 .incoming_data(checklist_id, component_id, transmit, now)
385 }
386
387 pub fn poll_recv(&mut self) -> Option<PendingRecv> {
391 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
392 let checklist_id = stream_state.checklist_id;
393
394 self.agent
395 .checklistset
396 .mut_list(checklist_id)
397 .and_then(|s| s.poll_recv())
398 }
399
400 #[tracing::instrument(
403 skip(self),
404 fields(
405 component.id = self.id,
406 )
407 )]
408 pub fn end_of_remote_candidates(&mut self) {
409 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
411 let checklist_id = stream_state.checklist_id;
412 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
413 checklist.end_of_remote_candidates();
414 }
415
416 pub fn allocated_socket(
420 &mut self,
421 component_id: usize,
422 transport: TransportType,
423 from: SocketAddr,
424 to: SocketAddr,
425 local_addr: Result<SocketAddr, StunError>,
426 now: Instant,
427 ) {
428 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
429 let checklist_id = stream_state.checklist_id;
430 let Some(component_state) = stream_state.mut_component_state(component_id) else {
431 return;
432 };
433 if component_state.gather_state != GatherProgress::InProgress {
434 return;
435 }
436 if let Some(gather) = component_state.gatherer.as_mut() {
437 gather.allocated_socket(transport, from, to, &local_addr)
438 }
439 self.agent.checklistset.allocated_socket(
440 checklist_id,
441 component_id,
442 transport,
443 from,
444 to,
445 local_addr,
446 now,
447 );
448 }
449
450 pub fn add_local_candidate(&mut self, candidate: Candidate) -> bool {
454 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
455 let checklist_id = stream_state.checklist_id;
456 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
457 checklist.add_local_candidate(candidate)
458 }
459
460 pub fn add_local_gathered_candidate(&mut self, candidate: GatheredCandidate) -> bool {
464 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
465 let checklist_id = stream_state.checklist_id;
466 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
467 checklist.add_local_gathered_candidate(candidate)
468 }
469
470 pub fn end_of_local_candidates(&mut self) {
473 let stream_state = self.agent.mut_stream_state(self.id).unwrap();
474 let checklist_id = stream_state.checklist_id;
475 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
476 checklist.end_of_local_candidates()
477 }
478}
479
480#[derive(Debug, Default)]
481pub(crate) struct StreamState {
482 id: usize,
483 pub(crate) checklist_id: usize,
484 components: Vec<Option<ComponentState>>,
485 local_credentials: Option<Credentials>,
486 remote_credentials: Option<Credentials>,
487}
488
489impl StreamState {
490 pub(crate) fn new(id: usize, checklist_id: usize) -> Self {
491 Self {
492 id,
493 checklist_id,
494 components: Vec::new(),
495 local_credentials: None,
496 remote_credentials: None,
497 }
498 }
499
500 pub(crate) fn component_state(&self, component_id: usize) -> Option<&ComponentState> {
501 if component_id < 1 {
502 return None;
503 }
504 if let Some(Some(c)) = self.components.get(component_id - 1) {
505 Some(c)
506 } else {
507 None
508 }
509 }
510
511 pub(crate) fn mut_component_state(
512 &mut self,
513 component_id: usize,
514 ) -> Option<&mut ComponentState> {
515 if component_id < 1 {
516 return None;
517 }
518 if let Some(Some(c)) = self.components.get_mut(component_id - 1) {
519 Some(c)
520 } else {
521 None
522 }
523 }
524
525 pub(crate) fn id(&self) -> usize {
527 self.id
528 }
529
530 #[tracing::instrument(
531 name = "stream_add_component",
532 skip(self),
533 fields(
534 stream.id = self.id
535 )
536 )]
537 fn add_component(&mut self) -> Result<usize, AgentError> {
538 let index = self
539 .components
540 .iter()
541 .enumerate()
542 .find(|c| c.1.is_none())
543 .unwrap_or((self.components.len(), &None))
544 .0;
545 info!("adding component {}", index + 1);
546 if self.components.get(index).is_some() {
547 return Err(AgentError::AlreadyExists);
548 }
549 while self.components.len() <= index {
550 self.components.push(None);
551 }
552 let component = ComponentState::new(index + 1);
553 self.components[index] = Some(component);
554 trace!("Added component at index {}", index);
555 Ok(index + 1)
556 }
557
558 #[tracing::instrument(
559 skip(self),
560 fields(
561 stream.id = self.id
562 )
563 )]
564 fn set_local_credentials(&mut self, credentials: Credentials) {
565 info!("setting");
566 self.local_credentials = Some(credentials.clone());
567 }
568
569 fn local_credentials(&self) -> Option<Credentials> {
570 self.local_credentials.clone()
571 }
572
573 #[tracing::instrument(
574 skip(self),
575 fields(
576 stream.id = self.id()
577 )
578 )]
579 fn set_remote_credentials(&mut self, credentials: Credentials) {
580 info!("setting");
581 self.remote_credentials = Some(credentials.clone());
582 }
583
584 fn remote_credentials(&self) -> Option<Credentials> {
585 self.remote_credentials.clone()
586 }
587
588 pub(crate) fn handle_incoming_data<T: AsRef<[u8]> + core::fmt::Debug>(
589 &mut self,
590 component_id: usize,
591 transmit: &Transmit<T>,
592 now: Instant,
593 ) -> HandleRecvReply<T> {
594 let Some(component) = self.mut_component_state(component_id) else {
595 return HandleRecvReply::default();
596 };
597 if component.gather_state != GatherProgress::InProgress {
598 return HandleRecvReply::default();
599 }
600 let Some(gather) = component.gatherer.as_mut() else {
601 return HandleRecvReply::default();
602 };
603 if gather.handle_data(transmit, now) {
606 HandleRecvReply {
607 handled: true,
608 ..Default::default()
609 }
610 } else {
611 HandleRecvReply::default()
612 }
613 }
614
615 #[tracing::instrument(ret, level = "trace", skip(self))]
616 pub(crate) fn poll_gather(&mut self, now: Instant) -> GatherPoll {
617 let mut lowest_wait = None;
618 for component in self.components.iter_mut() {
619 let Some(component) = component else {
620 continue;
621 };
622 let Some(gatherer) = component.gatherer.as_mut() else {
623 continue;
624 };
625 if component.gather_state != GatherProgress::InProgress {
626 continue;
627 }
628
629 match gatherer.poll(now) {
630 GatherPoll::WaitUntil(wait) => {
631 if let Some(check_wait) = lowest_wait {
632 if wait < check_wait {
633 lowest_wait = Some(wait);
634 }
635 } else {
636 lowest_wait = Some(wait);
637 }
638 }
639 GatherPoll::Complete(component_id) => {
640 component.gather_state = GatherProgress::Completed;
641 return GatherPoll::Complete(component_id);
642 }
643 GatherPoll::Finished => (),
644 other => return other,
645 }
646 }
647 if let Some(lowest_wait) = lowest_wait {
648 GatherPoll::WaitUntil(lowest_wait)
649 } else {
650 GatherPoll::Finished
651 }
652 }
653
654 pub(crate) fn poll_gather_transmit(
655 &mut self,
656 now: Instant,
657 ) -> Option<(usize, Transmit<Data<'_>>)> {
658 for component in self.components.iter_mut() {
659 let Some(component) = component else {
660 continue;
661 };
662 let Some(gatherer) = component.gatherer.as_mut() else {
663 continue;
664 };
665 if component.gather_state != GatherProgress::InProgress {
666 continue;
667 }
668
669 if let Some(transmit) = gatherer.poll_transmit(now) {
670 return Some((component.id, transmit));
671 }
672 }
673 None
674 }
675
676 pub(crate) fn set_request_retransmits(&mut self, rto: RequestRto) {
677 for component in self.components.iter_mut() {
678 let Some(component) = component else {
679 continue;
680 };
681 let Some(gatherer) = component.gatherer.as_mut() else {
682 continue;
683 };
684
685 gatherer.set_request_retransmits(rto.clone());
686 }
687 }
688}
689
690#[cfg(test)]
691mod tests {
692 use super::*;
693
694 #[test]
695 fn getters_setters() {
696 let _log = crate::tests::test_init_log();
697 let lcreds = Credentials::new("luser".into(), "lpass".into());
698 let rcreds = Credentials::new("ruser".into(), "rpass".into());
699
700 let mut agent = Agent::default();
701 let stream_id = agent.add_stream();
702 let mut stream = agent.mut_stream(stream_id).unwrap();
703 assert!(stream.component(0).is_none());
704 let comp_id = stream.add_component().unwrap();
705 assert_eq!(comp_id, stream.component(comp_id).unwrap().id());
706
707 stream.set_local_credentials(lcreds.clone());
708 assert_eq!(stream.local_credentials().unwrap(), lcreds);
709 stream.set_remote_credentials(rcreds.clone());
710 assert_eq!(stream.remote_credentials().unwrap(), rcreds);
711 }
712}