1use std::sync::Arc;
5
6use crate::{Error, Id, NonZeroSlab, State, ffi};
7
8#[derive(Default)]
10pub(crate) struct Bandwidth {
11 allocators: NonZeroSlab<moq_net::bandwidth::Allocator>,
12 reservations: NonZeroSlab<Arc<moq_net::bandwidth::Reservation>>,
13}
14
15impl Bandwidth {
16 pub fn insert(&mut self, allocator: moq_net::bandwidth::Allocator) -> Result<Id, Error> {
17 self.allocators.insert(allocator)
18 }
19
20 pub fn allocator(&self, id: Id) -> Result<moq_net::bandwidth::Allocator, Error> {
21 self.allocators.get(id).cloned().ok_or(Error::NotFound)
22 }
23
24 pub fn close(&mut self, id: Id) -> Result<(), Error> {
25 self.allocators.remove(id).ok_or(Error::NotFound)?;
26 Ok(())
27 }
28
29 pub fn reserve(&mut self, allocator: Id, demand: &moq_net::track::Demand, max_bps: u64) -> Result<Id, Error> {
30 let allocator = self.allocator(allocator)?;
31 let reservation = allocator.reserve(demand, moq_net::bandwidth::Rate::from_bps(max_bps));
32 self.reservations.insert(Arc::new(reservation))
33 }
34
35 pub fn hold(&mut self, reservation: Arc<moq_net::bandwidth::Reservation>) -> Result<Id, Error> {
36 self.reservations.insert(reservation)
37 }
38
39 pub fn reservation(&self, id: Id) -> Result<Arc<moq_net::bandwidth::Reservation>, Error> {
40 self.reservations.get(id).cloned().ok_or(Error::NotFound)
41 }
42
43 pub fn reservation_close(&mut self, id: Id) -> Result<(), Error> {
44 self.reservations.remove(id).ok_or(Error::NotFound)?;
45 Ok(())
46 }
47}
48
49#[unsafe(no_mangle)]
53pub extern "C" fn moq_session_bandwidth(session: u32) -> i32 {
54 ffi::enter(move || {
55 let session = ffi::parse_id(session)?;
56 let mut state = State::lock();
57 let allocator = state.session.bandwidth(session)?;
58 state.bandwidth.insert(allocator)
59 })
60}
61
62#[unsafe(no_mangle)]
65pub extern "C" fn moq_bandwidth_close(bandwidth: u32) -> i32 {
66 ffi::enter(move || {
67 let bandwidth = ffi::parse_id(bandwidth)?;
68 State::lock().bandwidth.close(bandwidth)
69 })
70}
71
72#[unsafe(no_mangle)]
78pub extern "C" fn moq_bandwidth_reserve(bandwidth: u32, track: u32, max_bps: u64) -> i32 {
79 ffi::enter(move || {
80 let bandwidth = ffi::parse_id(bandwidth)?;
81 let track = ffi::parse_id(track)?;
82 let mut state = State::lock();
83 let demand = state.publish.track_demand(track)?;
84 state.bandwidth.reserve(bandwidth, &demand, max_bps)
85 })
86}
87
88#[unsafe(no_mangle)]
96pub unsafe extern "C" fn moq_reservation_grant(reservation: u32, bps: *mut u64, present: *mut bool) -> i32 {
97 ffi::enter(move || {
98 let reservation = ffi::parse_id(reservation)?;
99 let bps = unsafe { bps.as_mut() }.ok_or(Error::InvalidPointer)?;
100 let present = unsafe { present.as_mut() }.ok_or(Error::InvalidPointer)?;
101 match State::lock().bandwidth.reservation(reservation)?.peek() {
102 Some(rate) => {
103 *bps = rate.as_bps();
104 *present = true;
105 }
106 None => {
107 *bps = 0;
108 *present = false;
109 }
110 }
111 Ok(())
112 })
113}
114
115#[unsafe(no_mangle)]
117pub extern "C" fn moq_reservation_update(reservation: u32, max_bps: u64) -> i32 {
118 ffi::enter(move || {
119 let reservation = ffi::parse_id(reservation)?;
120 State::lock()
121 .bandwidth
122 .reservation(reservation)?
123 .update(moq_net::bandwidth::Rate::from_bps(max_bps));
124 Ok(())
125 })
126}
127
128#[unsafe(no_mangle)]
133pub extern "C" fn moq_reservation_close(reservation: u32) -> i32 {
134 ffi::enter(move || {
135 let reservation = ffi::parse_id(reservation)?;
136 State::lock().bandwidth.reservation_close(reservation)
137 })
138}