1use std::collections::HashSet;
2use std::fmt;
3use std::sync::{Arc, Mutex};
4
5use crate::credential::{Credential, append_bytes};
6use crate::epoch::Epoch;
7use crate::error::{Error, Result};
8use crate::key::TrackKey;
9use crate::limits::{KEY_LABEL, KEY_LEN, NAME_LABEL};
10use crate::name::{Name, encode};
11use crate::track;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub(crate) enum Domain {
16 Group = 0x00,
17 Datagram = 0x01,
18}
19
20struct Inner {
21 credential: Credential,
22 epoch: Epoch,
23 claims: Mutex<HashSet<Name>>,
26}
27
28#[derive(Clone)]
32pub struct Generation(Arc<Inner>);
33
34impl fmt::Debug for Generation {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.debug_struct("Generation")
37 .field("credential", &self.0.credential)
38 .field("epoch", &self.0.epoch)
39 .finish()
40 }
41}
42
43impl Generation {
44 pub(crate) fn new(credential: Credential, epoch: Epoch) -> Self {
45 Self(Arc::new(Inner {
46 credential,
47 epoch,
48 claims: Mutex::new(HashSet::new()),
49 }))
50 }
51
52 pub fn credential(&self) -> &Credential {
54 &self.0.credential
55 }
56
57 pub fn epoch(&self) -> &Epoch {
59 &self.0.epoch
60 }
61
62 pub fn name(&self, semantic: &str) -> Result<Name> {
68 let material = self.0.credential.expand(&self.name_info(semantic)?)?;
69 Ok(encode(material))
70 }
71
72 pub fn produce(&self, track: moq_net::track::Producer) -> Result<track::Producer> {
79 let name: Name = track.name().parse()?;
80 if !self.0.claims.lock().expect("claims").insert(name) {
81 return Err(Error::Reuse);
82 }
83 Ok(track::Producer::new(
84 track,
85 self.key(&name, Domain::Group)?,
86 self.key(&name, Domain::Datagram)?,
87 ))
88 }
89
90 pub fn consume(&self, track: moq_net::track::Subscriber) -> Result<track::Consumer> {
96 let name: Name = track.name().parse()?;
97 Ok(track::Consumer::new(
98 track,
99 self.key(&name, Domain::Group)?,
100 self.key(&name, Domain::Datagram)?,
101 ))
102 }
103
104 pub(crate) fn key(&self, name: &Name, domain: Domain) -> Result<TrackKey> {
105 Ok(TrackKey::new(self.key_bytes(name, domain)?))
106 }
107
108 pub(crate) fn key_bytes(&self, name: &Name, domain: Domain) -> Result<[u8; KEY_LEN]> {
109 self.0.credential.expand(&self.key_info(name, domain)?)
110 }
111
112 pub(crate) fn name_info(&self, semantic: &str) -> Result<Vec<u8>> {
113 let mut info = Vec::with_capacity(NAME_LABEL.len() + 64 + semantic.len());
114 info.extend_from_slice(NAME_LABEL);
115 self.scope(&mut info)?;
116 append_bytes(&mut info, semantic.as_bytes())?;
117 Ok(info)
118 }
119
120 pub(crate) fn key_info(&self, name: &Name, domain: Domain) -> Result<Vec<u8>> {
121 let mut info = Vec::with_capacity(KEY_LABEL.len() + 64 + name.as_str().len() + 1);
122 info.extend_from_slice(KEY_LABEL);
123 self.scope(&mut info)?;
124 append_bytes(&mut info, name.as_str().as_bytes())?;
125 info.push(domain as u8);
126 Ok(info)
127 }
128
129 fn scope(&self, info: &mut Vec<u8>) -> Result<()> {
131 append_bytes(info, self.0.credential.context())?;
132 append_bytes(info, self.0.epoch.as_str().as_bytes())?;
133 info.extend_from_slice(&self.0.credential.kid().to_be_bytes());
134 Ok(())
135 }
136}