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    /// Flow control limit for the connection in bytes
47    pub max_data: u64,
48    /// Flow control limit for locally-initiated bidirectional streams in bytes.
49    pub max_stream_data_bidi_local: u64,
50    /// Flow control limit for remotely-initiated bidirectional streams in
51    /// bytes.
52    pub max_stream_data_bidi_remote: u64,
53    /// Flow control limit for unidirectional streams in bytes.
54    pub max_stream_data_uni: u64,
55    /// Maximum count for concurrent remotely-initiated bidirectional streams.
56    pub max_streams_bidi: u64,
57    /// "Maximum count for concurrent remotely-initiated unidirectional
58    /// streams".
59    pub max_streams_uni: u64,
60    /// Receiver window limit for the connection in bytes.
61    pub max_window: u64,
62    /// Receiver window limit for a stream in bytes.
63    pub max_stream_window: u64,
64    /// Set the session to attempt resumption.
65    pub session: Option<Vec<u8>>,
66    /// Enables sending or receiving early data.
67    pub enable_early_data: bool,
68    /// Whether to enable datagram sending.
69    pub enable_dgram: bool,
70    /// Datagram receive queue length.
71    pub dgram_recv_queue_len: usize,
72    /// Datagram send queue length.
73    pub dgram_send_queue_len: usize,
74}
75
76impl Config {
77    /// Construct a new config object with default values.
78    pub fn new() -> Self {
79        Self::default()
80    }
81
82    pub fn with_host_port(mut self, host_port: String) -> Self {
83        self.host_port = host_port;
84        self
85    }
86
87    pub fn omit_sni(mut self) -> Self {
88        self.omit_sni = true;
89        self
90    }
91
92    pub fn with_connect_to(mut self, connect_to: String) -> Self {
93        self.connect_to = Some(connect_to);
94        self
95    }
96
97    pub fn with_source_port(mut self, port: u32) -> Self {
98        self.source_port = port;
99        self
100    }
101
102    pub fn verify_peer(mut self, verify_peer: bool) -> Self {
103        self.verify_peer = verify_peer;
104        self
105    }
106
107    pub fn with_idle_timeout(mut self, idle_timeout: u64) -> Self {
108        self.idle_timeout = idle_timeout;
109        self
110    }
111
112    pub fn with_max_data(mut self, max_data: u64) -> Self {
113        self.max_data = max_data;
114        self
115    }
116
117    pub fn with_max_stream_data_bidi_local(
118        mut self, max_stream_data_bidi_local: u64,
119    ) -> Self {
120        self.max_stream_data_bidi_local = max_stream_data_bidi_local;
121        self
122    }
123
124    pub fn with_max_stream_data_bidi_remote(
125        mut self, max_stream_data_bidi_remote: u64,
126    ) -> Self {
127        self.max_stream_data_bidi_remote = max_stream_data_bidi_remote;
128        self
129    }
130
131    pub fn with_max_stream_data_uni(mut self, max_stream_data_uni: u64) -> Self {
132        self.max_stream_data_uni = max_stream_data_uni;
133        self
134    }
135
136    pub fn with_max_streams_bidi(mut self, max_streams_bidi: u64) -> Self {
137        self.max_streams_bidi = max_streams_bidi;
138        self
139    }
140
141    pub fn with_max_streams_uni(mut self, max_streams_uni: u64) -> Self {
142        self.max_streams_uni = max_streams_uni;
143        self
144    }
145
146    pub fn with_max_window(mut self, max_window: u64) -> Self {
147        self.max_window = max_window;
148        self
149    }
150
151    pub fn with_max_stream_window(mut self, max_stream_window: u64) -> Self {
152        self.max_stream_window = max_stream_window;
153        self
154    }
155
156    pub fn enable_dgram(mut self, enable_dgram: bool) -> Self {
157        self.enable_dgram = enable_dgram;
158        self
159    }
160
161    pub fn with_dgram_recv_queue_len(
162        mut self, dgram_recv_queue_len: usize,
163    ) -> Self {
164        self.dgram_recv_queue_len = dgram_recv_queue_len;
165        self
166    }
167
168    pub fn with_dgram_send_queue_len(
169        mut self, dgram_send_queue_len: usize,
170    ) -> Self {
171        self.dgram_send_queue_len = dgram_send_queue_len;
172        self
173    }
174
175    pub fn build(self) -> Result<Self, io::Error> {
176        if self.host_port.is_empty() {
177            return Err(io::Error::new(
178                io::ErrorKind::InvalidInput,
179                "Must provide a <host:port> to connect".to_string(),
180            ));
181        }
182
183        Ok(Config {
184            host_port: self.host_port,
185            omit_sni: self.omit_sni,
186            connect_to: self.connect_to,
187            source_port: self.source_port,
188            verify_peer: self.verify_peer,
189            idle_timeout: self.idle_timeout,
190            max_data: self.max_data,
191            max_stream_data_bidi_local: self.max_stream_data_bidi_local,
192            max_stream_data_bidi_remote: self.max_stream_data_bidi_remote,
193            max_stream_data_uni: self.max_stream_data_uni,
194            max_streams_bidi: self.max_streams_bidi,
195            max_streams_uni: self.max_streams_uni,
196            max_window: self.max_window,
197            max_stream_window: self.max_stream_window,
198            session: None,
199            enable_early_data: self.enable_early_data,
200            enable_dgram: self.enable_dgram,
201            dgram_recv_queue_len: self.dgram_recv_queue_len,
202            dgram_send_queue_len: self.dgram_send_queue_len,
203        })
204    }
205}
206
207impl Default for Config {
208    fn default() -> Self {
209        // Values mirror config_from_clap()
210        Self {
211            host_port: "".to_string(),
212            omit_sni: false,
213            connect_to: None,
214            source_port: 0,
215            verify_peer: true,
216            idle_timeout: 5000,
217            max_data: 10000000,
218            max_stream_data_bidi_local: 10000000,
219            max_stream_data_bidi_remote: 10000000,
220            max_stream_data_uni: 10000000,
221            max_streams_bidi: 100,
222            max_streams_uni: 100,
223            max_window: 25165824,
224            max_stream_window: 16777216,
225            session: None,
226            enable_early_data: false,
227            enable_dgram: true,
228            dgram_recv_queue_len: 65536,
229            dgram_send_queue_len: 65536,
230        }
231    }
232}