Skip to main content

h3i/
config.rs

1// Copyright (C) 2024, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27//! Configuration for the h3i client.
28use std::io;
29
30/// Server details and QUIC connection properties.
31#[derive(Clone)]
32pub struct Config {
33    /// A string representing the host and port to connect to using the format
34    /// `<host>:<port>`.
35    pub host_port: String,
36    /// If the SNI should be omitted during the TLS handshake.
37    pub omit_sni: bool,
38    /// Set a specific IP address to connect to, rather than use DNS resolution.
39    pub connect_to: Option<String>,
40    /// The source port to use when connecting to a server.
41    pub source_port: u32,
42    /// Whether to verify the server certificate.
43    pub verify_peer: bool,
44    /// The QUIC idle timeout value in milliseconds.
45    pub idle_timeout: u64,
46    /// Multiplier applied to the connection's send capacity.
47    pub send_capacity_factor: f64,
48    /// Flow control limit for the connection in bytes
49    pub max_data: u64,
50    /// Flow control limit for locally-initiated bidirectional streams in bytes.
51    pub max_stream_data_bidi_local: u64,
52    /// Flow control limit for remotely-initiated bidirectional streams in
53    /// bytes.
54    pub max_stream_data_bidi_remote: u64,
55    /// Flow control limit for unidirectional streams in bytes.
56    pub max_stream_data_uni: u64,
57    /// Maximum count for concurrent remotely-initiated bidirectional streams.
58    pub max_streams_bidi: u64,
59    /// "Maximum count for concurrent remotely-initiated unidirectional
60    /// streams".
61    pub max_streams_uni: u64,
62    /// Receiver window limit for the connection in bytes.
63    pub max_window: u64,
64    /// Receiver window limit for a stream in bytes.
65    pub max_stream_window: u64,
66    /// Set the session to attempt resumption.
67    pub session: Option<Vec<u8>>,
68    /// Enables sending or receiving early data.
69    pub enable_early_data: bool,
70    /// Whether to enable datagram sending.
71    pub enable_dgram: bool,
72    /// Datagram receive queue length.
73    pub dgram_recv_queue_len: usize,
74    /// Datagram send queue length.
75    pub dgram_send_queue_len: usize,
76}
77
78impl Config {
79    /// Construct a new config object with default values.
80    pub fn new() -> Self {
81        Self::default()
82    }
83
84    pub fn with_host_port(mut self, host_port: String) -> Self {
85        self.host_port = host_port;
86        self
87    }
88
89    pub fn omit_sni(mut self) -> Self {
90        self.omit_sni = true;
91        self
92    }
93
94    pub fn with_connect_to(mut self, connect_to: String) -> Self {
95        self.connect_to = Some(connect_to);
96        self
97    }
98
99    pub fn with_source_port(mut self, port: u32) -> Self {
100        self.source_port = port;
101        self
102    }
103
104    pub fn verify_peer(mut self, verify_peer: bool) -> Self {
105        self.verify_peer = verify_peer;
106        self
107    }
108
109    pub fn with_idle_timeout(mut self, idle_timeout: u64) -> Self {
110        self.idle_timeout = idle_timeout;
111        self
112    }
113
114    pub fn with_send_capacity_factor(mut self, factor: f64) -> Self {
115        self.send_capacity_factor = factor;
116        self
117    }
118
119    pub fn with_max_data(mut self, max_data: u64) -> Self {
120        self.max_data = max_data;
121        self
122    }
123
124    pub fn with_max_stream_data_bidi_local(
125        mut self, max_stream_data_bidi_local: u64,
126    ) -> Self {
127        self.max_stream_data_bidi_local = max_stream_data_bidi_local;
128        self
129    }
130
131    pub fn with_max_stream_data_bidi_remote(
132        mut self, max_stream_data_bidi_remote: u64,
133    ) -> Self {
134        self.max_stream_data_bidi_remote = max_stream_data_bidi_remote;
135        self
136    }
137
138    pub fn with_max_stream_data_uni(mut self, max_stream_data_uni: u64) -> Self {
139        self.max_stream_data_uni = max_stream_data_uni;
140        self
141    }
142
143    pub fn with_max_streams_bidi(mut self, max_streams_bidi: u64) -> Self {
144        self.max_streams_bidi = max_streams_bidi;
145        self
146    }
147
148    pub fn with_max_streams_uni(mut self, max_streams_uni: u64) -> Self {
149        self.max_streams_uni = max_streams_uni;
150        self
151    }
152
153    pub fn with_max_window(mut self, max_window: u64) -> Self {
154        self.max_window = max_window;
155        self
156    }
157
158    pub fn with_max_stream_window(mut self, max_stream_window: u64) -> Self {
159        self.max_stream_window = max_stream_window;
160        self
161    }
162
163    pub fn enable_dgram(mut self, enable_dgram: bool) -> Self {
164        self.enable_dgram = enable_dgram;
165        self
166    }
167
168    pub fn with_dgram_recv_queue_len(
169        mut self, dgram_recv_queue_len: usize,
170    ) -> Self {
171        self.dgram_recv_queue_len = dgram_recv_queue_len;
172        self
173    }
174
175    pub fn with_dgram_send_queue_len(
176        mut self, dgram_send_queue_len: usize,
177    ) -> Self {
178        self.dgram_send_queue_len = dgram_send_queue_len;
179        self
180    }
181
182    pub fn build(self) -> Result<Self, io::Error> {
183        if self.host_port.is_empty() {
184            return Err(io::Error::new(
185                io::ErrorKind::InvalidInput,
186                "Must provide a <host:port> to connect".to_string(),
187            ));
188        }
189
190        Ok(Config {
191            host_port: self.host_port,
192            omit_sni: self.omit_sni,
193            connect_to: self.connect_to,
194            source_port: self.source_port,
195            verify_peer: self.verify_peer,
196            idle_timeout: self.idle_timeout,
197            send_capacity_factor: self.send_capacity_factor,
198            max_data: self.max_data,
199            max_stream_data_bidi_local: self.max_stream_data_bidi_local,
200            max_stream_data_bidi_remote: self.max_stream_data_bidi_remote,
201            max_stream_data_uni: self.max_stream_data_uni,
202            max_streams_bidi: self.max_streams_bidi,
203            max_streams_uni: self.max_streams_uni,
204            max_window: self.max_window,
205            max_stream_window: self.max_stream_window,
206            session: None,
207            enable_early_data: self.enable_early_data,
208            enable_dgram: self.enable_dgram,
209            dgram_recv_queue_len: self.dgram_recv_queue_len,
210            dgram_send_queue_len: self.dgram_send_queue_len,
211        })
212    }
213}
214
215impl Default for Config {
216    fn default() -> Self {
217        // Values mirror config_from_clap()
218        Self {
219            host_port: "".to_string(),
220            omit_sni: false,
221            connect_to: None,
222            source_port: 0,
223            verify_peer: true,
224            idle_timeout: 5000,
225            send_capacity_factor: 1.0,
226            max_data: 10000000,
227            max_stream_data_bidi_local: 10000000,
228            max_stream_data_bidi_remote: 10000000,
229            max_stream_data_uni: 10000000,
230            max_streams_bidi: 100,
231            max_streams_uni: 100,
232            max_window: 25165824,
233            max_stream_window: 16777216,
234            session: None,
235            enable_early_data: false,
236            enable_dgram: true,
237            dgram_recv_queue_len: 65536,
238            dgram_send_queue_len: 65536,
239        }
240    }
241}