use crate::data_channel::RTCDataChannelId;
use crate::data_channel::internal::RTCDataChannelInternal;
use crate::peer_connection::transport::dtls::role::RTCDtlsRole;
use shared::error::{Error, Result};
use std::collections::HashMap;
#[derive(Default)]
pub(crate) struct DataChannelRegistry {
channels: HashMap<RTCDataChannelId, RTCDataChannelInternal>,
by_stream: HashMap<u16, RTCDataChannelId>,
next_handle: RTCDataChannelId,
}
impl DataChannelRegistry {
pub(crate) fn new() -> Self {
Self {
channels: HashMap::new(),
by_stream: HashMap::new(),
next_handle: 0,
}
}
pub(crate) fn insert(&mut self, data_channel: RTCDataChannelInternal) -> RTCDataChannelId {
let handle = self.alloc_handle();
if let Some(stream_id) = data_channel.stream_id {
self.by_stream.insert(stream_id, handle);
}
self.channels.insert(handle, data_channel);
handle
}
fn alloc_handle(&mut self) -> RTCDataChannelId {
for _ in 0..=RTCDataChannelId::MAX {
let candidate = self.next_handle;
self.next_handle = self.next_handle.wrapping_add(1);
if !self.channels.contains_key(&candidate) {
return candidate;
}
}
self.next_handle
}
pub(crate) fn get(&self, handle: &RTCDataChannelId) -> Option<&RTCDataChannelInternal> {
self.channels.get(handle)
}
pub(crate) fn get_mut(
&mut self,
handle: &RTCDataChannelId,
) -> Option<&mut RTCDataChannelInternal> {
self.channels.get_mut(handle)
}
pub(crate) fn contains(&self, handle: &RTCDataChannelId) -> bool {
self.channels.contains_key(handle)
}
pub(crate) fn handle_of_stream(&self, stream_id: &u16) -> Option<RTCDataChannelId> {
self.by_stream.get(stream_id).copied()
}
pub(crate) fn get_by_stream(&self, stream_id: &u16) -> Option<&RTCDataChannelInternal> {
self.channels.get(self.by_stream.get(stream_id)?)
}
pub(crate) fn get_by_stream_mut(
&mut self,
stream_id: &u16,
) -> Option<&mut RTCDataChannelInternal> {
let handle = *self.by_stream.get(stream_id)?;
self.channels.get_mut(&handle)
}
pub(crate) fn remove_by_stream(
&mut self,
stream_id: &u16,
) -> Option<(RTCDataChannelId, RTCDataChannelInternal)> {
let handle = self.by_stream.remove(stream_id)?;
let data_channel = self.channels.remove(&handle)?;
Some((handle, data_channel))
}
pub(crate) fn stream_id_in_use(&self, stream_id: &u16) -> bool {
self.by_stream.contains_key(stream_id)
}
pub(crate) fn pending_stream_id_handles(&self) -> Vec<RTCDataChannelId> {
let mut handles: Vec<_> = self
.channels
.iter()
.filter(|(_, dc)| dc.stream_id.is_none())
.map(|(handle, _)| *handle)
.collect();
handles.sort_unstable();
handles
}
pub(crate) fn assign_stream_ids(&mut self, role: RTCDtlsRole, max_channels: u16) -> Result<()> {
let mut next: u16 = match role {
RTCDtlsRole::Client => 0,
RTCDtlsRole::Server => 1,
_ => return Err(Error::ErrDataChannelStreamIdNotAssigned),
};
let max = max_channels;
for handle in self.pending_stream_id_handles() {
while next < max.saturating_sub(1) && self.stream_id_in_use(&next) {
next += 2;
}
if next >= max.saturating_sub(1) {
return Err(Error::ErrMaxDataChannelID);
}
self.assign_stream_id(handle, next);
next += 2;
}
Ok(())
}
pub(crate) fn assign_stream_id(&mut self, handle: RTCDataChannelId, stream_id: u16) {
if let Some(data_channel) = self.channels.get_mut(&handle) {
data_channel.stream_id = Some(stream_id);
self.by_stream.insert(stream_id, handle);
}
}
pub(crate) fn is_empty(&self) -> bool {
self.channels.is_empty()
}
pub(crate) fn len(&self) -> usize {
self.channels.len()
}
pub(crate) fn values(&self) -> impl Iterator<Item = &RTCDataChannelInternal> {
self.channels.values()
}
pub(crate) fn values_mut(&mut self) -> impl Iterator<Item = &mut RTCDataChannelInternal> {
self.channels.values_mut()
}
pub(crate) fn iter_mut(
&mut self,
) -> impl Iterator<Item = (RTCDataChannelId, &mut RTCDataChannelInternal)> {
self.channels.iter_mut().map(|(handle, dc)| (*handle, dc))
}
}