Skip to main content

orinium_browser/platform/network/
sender_pool.rs

1//! HTTP Sender Pool.
2//! HTTP/1 と HTTP/2 の Sender を統一的に管理できるプール。
3
4use http_body_util::Full;
5use hyper::{
6    body::Bytes,
7    client::conn::{http1, http2},
8};
9use std::collections::HashMap;
10
11#[derive(Hash, Eq, PartialEq, Clone, Debug)]
12pub struct HostKey {
13    pub scheme: hyper::http::uri::Scheme,
14    pub host: String,
15    pub port: u16,
16}
17
18/// HTTP/1 と HTTP/2 の Sender を統一的に扱う型
19pub enum HttpSender {
20    Http1(http1::SendRequest<Full<Bytes>>),
21    Http2(http2::SendRequest<Full<Bytes>>),
22}
23
24pub struct SenderPool {
25    pool: HashMap<HostKey, Vec<HttpSender>>,
26    max_connections_per_host: usize,
27}
28
29impl Default for SenderPool {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl SenderPool {
36    pub fn new() -> Self {
37        Self {
38            pool: HashMap::new(),
39            max_connections_per_host: 6,
40        }
41    }
42
43    pub fn get_connection(&mut self, key: &HostKey) -> Option<HttpSender> {
44        self.pool.get_mut(key).and_then(|v| v.pop())
45    }
46
47    /// Returns whether no connections are currently pooled.
48    pub fn is_empty(&self) -> bool {
49        self.pool.values().all(Vec::is_empty)
50    }
51
52    pub fn add_connection(&mut self, key: HostKey, conn: HttpSender) {
53        let entry = self.pool.entry(key).or_default();
54        if entry.len() < self.max_connections_per_host {
55            entry.push(conn);
56        }
57    }
58
59    pub fn remove_connection(&mut self, key: &HostKey) {
60        if let Some(conns) = self.pool.get_mut(key) {
61            conns.pop();
62            if conns.is_empty() {
63                self.pool.remove(key);
64            }
65        }
66    }
67
68    pub fn clear(&mut self) {
69        self.pool.clear();
70    }
71}