use crate::data_channel::RTCDataChannelId;
use crate::data_channel::internal::RTCDataChannelInternal;
use crate::peer_connection::transport::dtls::role::RTCDtlsRole;
use crate::peer_connection::transport::sctp::SCTP_MAX_CHANNELS;
use sctp::StreamId;
use shared::error::{Error, Result};
use std::collections::HashMap;
#[derive(Default)]
pub(crate) struct DataChannelRegistry {
channels: HashMap<RTCDataChannelId, RTCDataChannelInternal>,
by_stream: HashMap<StreamId, 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, mut data_channel: RTCDataChannelInternal) -> RTCDataChannelId {
let handle = self.next_handle;
self.next_handle += 1;
data_channel.id = handle;
if let Some(stream_id) = data_channel.stream_id {
self.by_stream.insert(stream_id, handle);
}
self.channels.insert(handle, data_channel);
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: &StreamId) -> Option<RTCDataChannelId> {
self.by_stream.get(stream_id).copied()
}
pub(crate) fn get_by_stream(&self, stream_id: &StreamId) -> Option<&RTCDataChannelInternal> {
self.channels.get(self.by_stream.get(stream_id)?)
}
pub(crate) fn get_by_stream_mut(
&mut self,
stream_id: &StreamId,
) -> 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: &StreamId,
) -> Option<RTCDataChannelInternal> {
let handle = self.by_stream.remove(stream_id)?;
self.channels.remove(&handle)
}
pub(crate) fn stream_id_in_use(&self, stream_id: &StreamId) -> bool {
self.by_stream.contains_key(stream_id)
}
pub(crate) fn pending_stream_id_handles(&self) -> Vec<RTCDataChannelId> {
let mut handles: Vec<_> = self
.channels
.values()
.filter(|dc| dc.stream_id.is_none())
.map(|dc| dc.id)
.collect();
handles.sort_unstable();
handles
}
pub(crate) fn assign_stream_ids(
&mut self,
role: RTCDtlsRole,
max_channels: Option<StreamId>,
) -> Result<()> {
let mut next: StreamId = match role {
RTCDtlsRole::Client => 0,
RTCDtlsRole::Server => 1,
_ => return Err(Error::ErrDataChannelStreamIdNotAssigned),
};
let max = max_channels.unwrap_or(SCTP_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: StreamId) {
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()
}
}