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