1use alloc::boxed::Box;
14use core::net::SocketAddr;
15
16use stun_proto::Instant;
17use stun_proto::agent::Transmit;
18use stun_proto::types::message::{BINDING, Message, MessageWriteVec};
19use stun_proto::types::prelude::MessageWrite;
20use turn_client_proto::api::TurnClientApi;
21use turn_client_proto::types::prelude::DelayedTransmitBuild;
22
23use crate::candidate::{CandidatePair, CandidateType, TransportType};
24
25use crate::agent::{Agent, AgentError};
26pub use crate::conncheck::SelectedPair;
27use crate::conncheck::{RequestRto, transmit_send};
28use crate::gathering::StunGatherer;
29use crate::stream::Stream;
30use crate::turn::TurnConfig;
31
32use tracing::{debug, trace};
33
34pub const RTP: usize = 1;
36pub const RTCP: usize = 2;
38
39#[derive(Debug)]
41#[repr(C)]
42pub struct Component<'a> {
43 agent: &'a Agent,
44 stream_id: usize,
45 component_id: usize,
46}
47
48impl<'a> Component<'a> {
49 pub(crate) fn from_stream(agent: &'a Agent, stream_id: usize, component_id: usize) -> Self {
50 Self {
51 agent,
52 stream_id,
53 component_id,
54 }
55 }
56
57 pub fn id(&self) -> usize {
59 self.component_id
60 }
61
62 pub fn stream(&self) -> Stream<'a> {
78 self.agent.stream(self.stream_id).unwrap()
79 }
80
81 pub fn state(&self) -> ComponentConnectionState {
99 let stream = self.agent.stream_state(self.stream_id).unwrap();
100 let component = stream.component_state(self.component_id).unwrap();
101 component.state
102 }
103
104 pub fn selected_pair(&self) -> Option<&CandidatePair> {
107 let stream = self.agent.stream_state(self.stream_id).unwrap();
108 let component = stream.component_state(self.component_id).unwrap();
109 component
110 .selected_pair
111 .as_ref()
112 .map(|pair| pair.candidate_pair())
113 }
114}
115
116#[derive(Debug)]
118#[repr(C)]
119pub struct ComponentMut<'a> {
120 agent: &'a mut Agent,
121 stream_id: usize,
122 component_id: usize,
123}
124
125impl<'a> core::ops::Deref for ComponentMut<'a> {
126 type Target = Component<'a>;
127
128 fn deref(&self) -> &Self::Target {
129 unsafe { core::mem::transmute(self) }
130 }
131}
132
133impl<'a> ComponentMut<'a> {
134 pub(crate) fn from_stream(agent: &'a mut Agent, stream_id: usize, component_id: usize) -> Self {
135 Self {
136 agent,
137 stream_id,
138 component_id,
139 }
140 }
141
142 pub fn gather_candidates(
159 &mut self,
160 sockets: &[(TransportType, SocketAddr)],
161 stun_servers: &[(TransportType, SocketAddr)],
162 turn_servers: &[(SocketAddr, &TurnConfig)],
163 ) -> Result<(), AgentError> {
164 let rto = self.agent.rto.clone();
165 let stream = self.agent.mut_stream_state(self.stream_id).unwrap();
166 let component = stream.mut_component_state(self.component_id).unwrap();
167 component.gather_candidates(sockets, stun_servers, turn_servers, rto)
168 }
169
170 pub fn set_selected_pair(&mut self, selected: CandidatePair) -> Result<(), AgentError> {
173 let stream = self.agent.mut_stream_state(self.stream_id).unwrap();
175 let checklist_id = stream.checklist_id;
176 let checklist = self
177 .agent
178 .checklistset
179 .mut_list(checklist_id)
180 .ok_or(AgentError::ResourceNotFound)?;
181 let (agent_id, agent) = if let Some((agent_id, agent)) = checklist.mut_agent_for_5tuple(
182 selected.local.transport_type,
183 selected.local.base_address,
184 selected.remote.address,
185 ) {
186 (agent_id, agent)
187 } else {
188 let agent_id = checklist
189 .add_agent_for_5tuple(
190 selected.local.transport_type,
191 selected.local.base_address,
192 selected.remote.address,
193 None,
194 )
195 .0;
196 let agent = checklist.mut_agent_by_id(agent_id).unwrap();
197 (agent_id, agent)
198 };
199 if !agent.is_validated_peer(selected.remote.address) {
200 let transmit = agent
202 .send_request(
203 Message::builder_request(BINDING, MessageWriteVec::new()).finish(),
204 selected.remote.address,
205 Instant::ZERO,
206 )
207 .unwrap();
208 let msg = Message::from_bytes(&transmit.data).unwrap();
209 let response = Message::builder_success(&msg, MessageWriteVec::new()).finish();
210 let response = Message::from_bytes(&response).unwrap();
211 agent.handle_stun_message(&response, selected.remote.address);
212 }
213
214 let selected_pair = SelectedPair::new(selected, agent_id, None);
215 self.set_selected_pair_with_agent(selected_pair);
216 Ok(())
217 }
218
219 pub(crate) fn set_selected_pair_with_agent(&mut self, selected: SelectedPair) {
220 let stream = self.agent.mut_stream_state(self.stream_id).unwrap();
221 let component = stream.mut_component_state(self.component_id).unwrap();
222 component.selected_pair = Some(selected);
223 }
224
225 pub fn send<T: AsRef<[u8]> + core::fmt::Debug>(
228 &mut self,
229 data: T,
230 now: Instant,
231 ) -> Result<Transmit<Box<[u8]>>, AgentError> {
232 let stream = self.agent.stream_state(self.stream_id).unwrap();
234 let checklist_id = stream.checklist_id;
235 let component = stream.component_state(self.component_id).unwrap();
236 let selected_pair = component
237 .selected_pair
238 .as_ref()
239 .ok_or(AgentError::ResourceNotFound)?;
240 let pair = selected_pair.candidate_pair();
241 let local_candidate_type = pair.local.candidate_type;
242 let local_transport = pair.local.transport_type;
243 let local_base_addr = pair.local.base_address;
244 let local_addr = pair.local.address;
245 let remote_addr = pair.remote.address;
246 let stun_agent_id = selected_pair.stun_agent_id();
247
248 let data_len = data.as_ref().len();
249
250 let checklist = self.agent.checklistset.mut_list(checklist_id).unwrap();
251 if local_candidate_type == CandidateType::Relayed {
252 let turn_client = checklist
253 .mut_turn_client_by_allocated_address(local_transport, local_base_addr)
254 .ok_or(AgentError::ResourceNotFound)?
255 .1;
256 let transmit = turn_client
257 .send_to(local_transport, remote_addr, data, now)
258 .map_err(|_| AgentError::ResourceNotFound)?
259 .unwrap();
260 trace!(
261 "sending {} bytes from {} {} through TURN server {} with allocation {local_transport} {local_base_addr} to {remote_addr}",
262 data_len, transmit.transport, transmit.from, transmit.to,
263 );
264 Ok(Transmit::new(
265 transmit.data.build().into_boxed_slice(),
266 transmit.transport,
267 transmit.from,
268 transmit.to,
269 ))
270 } else {
271 let stun_agent = checklist
272 .agent_by_id(stun_agent_id)
273 .ok_or(AgentError::ResourceNotFound)?;
274 trace!(
275 "sending {} bytes directly over {local_transport} {local_addr} -> {remote_addr}",
276 data_len
277 );
278 let transmit = stun_agent.send_data(data, remote_addr);
279 let transport = transmit.transport;
280 Ok(transmit.reinterpret_data(|data| transmit_send(transport, data.as_ref())))
281 }
282 }
283}
284
285#[derive(Debug, Default, PartialEq, Eq)]
286pub(crate) enum GatherProgress {
287 #[default]
288 New,
289 InProgress,
290 Completed,
291}
292
293#[derive(Copy, Clone, Debug, PartialEq, Eq)]
295#[repr(u32)]
296pub enum ComponentConnectionState {
297 New,
299 Connecting,
301 Connected,
303 Failed,
305}
306
307#[derive(Debug)]
308pub(crate) struct ComponentState {
309 pub(crate) id: usize,
310 state: ComponentConnectionState,
311 selected_pair: Option<SelectedPair>,
312 pub(crate) gather_state: GatherProgress,
313 pub(crate) gatherer: Option<StunGatherer>,
314}
315
316impl ComponentState {
317 pub(crate) fn new(id: usize) -> Self {
318 Self {
319 id,
320 state: ComponentConnectionState::New,
321 selected_pair: None,
322 gather_state: GatherProgress::New,
323 gatherer: None,
324 }
325 }
326
327 pub(crate) fn gather_candidates(
328 &mut self,
329 sockets: &[(TransportType, SocketAddr)],
330 stun_servers: &[(TransportType, SocketAddr)],
331 turn_servers: &[(SocketAddr, &TurnConfig)],
332 rto: Option<RequestRto>,
333 ) -> Result<(), AgentError> {
334 if self.gather_state != GatherProgress::New {
335 return Err(AgentError::AlreadyInProgress);
336 }
337
338 let mut gatherer = StunGatherer::new(self.id, sockets, stun_servers, turn_servers);
339 if let Some(rto) = rto {
340 gatherer.set_request_retransmits(rto);
341 }
342 self.gatherer = Some(gatherer);
343 self.gather_state = GatherProgress::InProgress;
344
345 Ok(())
346 }
347
348 #[tracing::instrument(name = "set_component_state", level = "debug", skip(self, state))]
349 pub(crate) fn set_state(&mut self, state: ComponentConnectionState) -> bool {
350 if self.state != state {
351 debug!(old_state = ?self.state, new_state = ?state, "setting");
352 self.state = state;
353 true
354 } else {
355 false
356 }
357 }
358}
359
360#[cfg(test)]
361mod tests {
362 use super::*;
363 use crate::agent::Agent;
364 use crate::candidate::Candidate;
365 use alloc::vec;
366
367 #[test]
368 fn initial_state_new() {
369 let _log = crate::tests::test_init_log();
370 let mut agent = Agent::builder().build();
371 let sid = agent.add_stream();
372 let mut s = agent.mut_stream(sid).unwrap();
373 let cid = s.add_component().unwrap();
374 let c = s.component(cid).unwrap();
375 assert_eq!(c.state(), ComponentConnectionState::New);
376 }
377
378 #[test]
379 fn send_recv() {
380 let _log = crate::tests::test_init_log();
381 let mut agent = Agent::builder().controlling(false).build();
382 let stream_id = agent.add_stream();
383 let mut stream = agent.mut_stream(stream_id).unwrap();
384 let send_id = stream.add_component().unwrap();
385 let local_addr = "127.0.0.1:1000".parse().unwrap();
386 let remote_addr = "127.0.0.1:2000".parse().unwrap();
387 let now = Instant::ZERO;
388
389 let local_cand = Candidate::builder(
390 send_id,
391 CandidateType::Host,
392 TransportType::Udp,
393 "0",
394 local_addr,
395 )
396 .build();
397 let remote_cand = Candidate::builder(
398 send_id,
399 CandidateType::Host,
400 TransportType::Udp,
401 "0",
402 remote_addr,
403 )
404 .build();
405 let candidate_pair = CandidatePair::new(local_cand, remote_cand);
406
407 let mut send = stream.mut_component(send_id).unwrap();
408 send.set_selected_pair(candidate_pair.clone()).unwrap();
409 assert_eq!(send.selected_pair().unwrap(), &candidate_pair);
410
411 let data = vec![3; 4];
412 let transmit = send.send(&data, now).unwrap();
413 assert_eq!(transmit.transport, TransportType::Udp);
414 assert_eq!(transmit.from, local_addr);
415 assert_eq!(transmit.to, remote_addr);
416 assert_eq!(transmit.data.as_ref(), data.as_slice());
417
418 let recved_data = vec![7; 6];
419 let ret = stream.handle_incoming_data(
420 send_id,
421 Transmit::new(
422 recved_data.clone(),
423 TransportType::Udp,
424 remote_addr,
425 local_addr,
426 ),
427 now,
428 );
429 assert_eq!(recved_data.as_slice(), ret.data.unwrap().as_ref());
430 assert!(!ret.handled);
431 assert!(!ret.have_more_data);
432
433 let recved_data2 = vec![9; 12];
435 let ret = stream.handle_incoming_data(
436 send_id,
437 Transmit::new(recved_data2, TransportType::Udp, local_addr, local_addr),
438 now,
439 );
440 assert!(ret.data.is_none());
441 assert!(!ret.handled);
442 assert!(!ret.have_more_data);
443 }
444}