      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274

    use crate::frame::Reason;
    use crate::proto::{WindowSize, MAX_WINDOW_SIZE};

    use std::fmt;

    // We don't want to send WINDOW_UPDATE frames for tiny changes, but instead
    // aggregate them when the changes are significant. Many implementations do
    // this by keeping a "ratio" of the update version the allowed window size.
    //
    // While some may wish to represent this ratio as percentage, using a f32,
    // we skip having to deal with float math and stick to integers. To do so,
    // the "ratio" is represented by 2 i32s, split into the numerator and
    // denominator. For example, a 50% ratio is simply represented as 1/2.
    //
    // An example applying this ratio: If a stream has an allowed window size of
    // 100 bytes, WINDOW_UPDATE frames are scheduled when the unclaimed change
    // becomes greater than 1/2, or 50 bytes.
    const UNCLAIMED_NUMERATOR: i32 = 1;
    const UNCLAIMED_DENOMINATOR: i32 = 2;

    #[test]
    fn sanity_unclaimed_ratio() {
        assert!(UNCLAIMED_NUMERATOR < UNCLAIMED_DENOMINATOR);
        assert!(UNCLAIMED_NUMERATOR >= 0);
        assert!(UNCLAIMED_DENOMINATOR > 0);
    }

    #[derive(Copy, Clone, Debug)]
    pub struct FlowControl {
        /// Window the peer knows about.
        ///
        /// This can go negative if a SETTINGS_INITIAL_WINDOW_SIZE is received.
        ///
        /// For example, say the peer sends a request and uses 32kb of the window.
        /// We send a SETTINGS_INITIAL_WINDOW_SIZE of 16kb. The peer has to adjust
        /// its understanding of the capacity of the window, and that would be:
        ///
        /// ```notrust
        /// default (64kb) - used (32kb) - settings_diff (64kb - 16kb): -16kb
        /// ```
        window_size: Window,

        /// Window that we know about.
        ///
        /// This can go negative if a user declares a smaller target window than
        /// the peer knows about.
        available: Window,
    }

    impl FlowControl {
        pub fn new() -> FlowControl {
            FlowControl {
                window_size: Window(0),
                available: Window(0),
            }
        }

        /// Returns the window size as known by the peer
        pub fn window_size(&self) -> WindowSize {
            self.window_size.as_size()
        }

        /// Returns the window size available to the consumer
        pub fn available(&self) -> Window {
            self.available
        }

        /// Returns true if there is unavailable window capacity
        pub fn has_unavailable(&self) -> bool {
            if self.window_size < 0 {
                return false;
            }

            self.window_size > self.available
        }

        pub fn claim_capacity(&mut self, capacity: WindowSize) {
            self.available -= capacity;
        }

        pub fn assign_capacity(&mut self, capacity: WindowSize) {
            self.available += capacity;
        }

        /// If a WINDOW_UPDATE frame should be sent, returns a positive number
        /// representing the increment to be used.
        ///
        /// If there is no available bytes to be reclaimed, or the number of
        /// available bytes does not reach the threshold, this returns `None`.
        ///
        /// This represents pending outbound WINDOW_UPDATE frames.
        pub fn unclaimed_capacity(&self) -> Option<WindowSize> {
            let available = self.available;

            if self.window_size >= available {
                return None;
            }

            let unclaimed = available.0 - self.window_size.0;
            let threshold = self.window_size.0 / UNCLAIMED_DENOMINATOR * UNCLAIMED_NUMERATOR;

            if unclaimed < threshold {
                None
            } else {
                Some(unclaimed as WindowSize)
            }
        }

        /// Increase the window size.
        ///
        /// This is called after receiving a WINDOW_UPDATE frame
        pub fn inc_window(&mut self, sz: WindowSize) -> Result<(), Reason> {
            let (val, overflow) = self.window_size.0.overflowing_add(sz as i32);

            if overflow {
                return Err(Reason::FLOW_CONTROL_ERROR);
            }

            if val > MAX_WINDOW_SIZE as i32 {
                return Err(Reason::FLOW_CONTROL_ERROR);
            }

            tracing::trace!(
                "inc_window; sz={}; old={}; new={}",
                sz,
                self.window_size,
                val
            );

            self.window_size = Window(val);
            Ok(())
        }

        /// Decrement the send-side window size.
        ///
        /// This is called after receiving a SETTINGS frame with a lower
        /// INITIAL_WINDOW_SIZE value.
        pub fn dec_send_window(&mut self, sz: WindowSize) {
            tracing::trace!(
                "dec_window; sz={}; window={}, available={}",
                sz,
                self.window_size,
                self.available
            );
            // This should not be able to overflow `window_size` from the bottom.
            self.window_size -= sz;
        }

        /// Decrement the recv-side window size.
        ///
        /// This is called after receiving a SETTINGS ACK frame with a lower
        /// INITIAL_WINDOW_SIZE value.
        pub fn dec_recv_window(&mut self, sz: WindowSize) {
            tracing::trace!(
                "dec_recv_window; sz={}; window={}, available={}",
                sz,
                self.window_size,
                self.available
            );
            // This should not be able to overflow `window_size` from the bottom.
            self.window_size -= sz;
            self.available -= sz;
        }

        /// Decrements the window reflecting data has actually been sent. The caller
        /// must ensure that the window has capacity.
        pub fn send_data(&mut self, sz: WindowSize) {
            tracing::trace!(
                "send_data; sz={}; window={}; available={}",
                sz,
                self.window_size,
                self.available
            );

            // Ensure that the argument is correct
            assert!(sz <= self.window_size);

            // Update values
            self.window_size -= sz;
            self.available -= sz;
        }
    }

    /// The current capacity of a flow-controlled Window.
    ///
    /// This number can go negative when either side has used a certain amount
    /// of capacity when the other side advertises a reduction in size.
    ///
    /// This type tries to centralize the knowledge of addition and subtraction
    /// to this capacity, instead of having integer casts throughout the source.
    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
    pub struct Window(i32);

    impl Window {
        pub fn as_size(&self) -> WindowSize {
            if self.0 < 0 {
                0
            } else {
                self.0 as WindowSize
            }
        }

        pub fn checked_size(&self) -> WindowSize {
            assert!(self.0 >= 0, "negative Window");
            self.0 as WindowSize
        }
    }

    impl PartialEq<WindowSize> for Window {
        fn eq(&self, other: &WindowSize) -> bool {
            if self.0 < 0 {
                false
            } else {
                (self.0 as WindowSize).eq(other)
            }
        }
    }

    impl PartialEq<Window> for WindowSize {
        fn eq(&self, other: &Window) -> bool {
            other.eq(self)
        }
    }

    impl PartialOrd<WindowSize> for Window {
        fn partial_cmp(&self, other: &WindowSize) -> Option<::std::cmp::Ordering> {
            if self.0 < 0 {
                Some(::std::cmp::Ordering::Less)
            } else {
                (self.0 as WindowSize).partial_cmp(other)
            }
        }
    }

    impl PartialOrd<Window> for WindowSize {
        fn partial_cmp(&self, other: &Window) -> Option<::std::cmp::Ordering> {
            if other.0 < 0 {
                Some(::std::cmp::Ordering::Greater)
            } else {
                self.partial_cmp(&(other.0 as WindowSize))
            }
        }
    }

    impl ::std::ops::SubAssign<WindowSize> for Window {
        fn sub_assign(&mut self, other: WindowSize) {
            self.0 -= other as i32;
        }
    }

    impl ::std::ops::Add<WindowSize> for Window {
        type Output = Self;
        fn add(self, other: WindowSize) -> Self::Output {
            Window(self.0 + other as i32)
        }
    }

    impl ::std::ops::AddAssign<WindowSize> for Window {
        fn add_assign(&mut self, other: WindowSize) {
            self.0 += other as i32;
        }
    }

    impl fmt::Display for Window {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Display::fmt(&self.0, f)
        }
    }

    impl From<Window> for isize {
        fn from(w: Window) -> isize {
            w.0 as isize
        }
    }