@@ -59,6 +59,7 @@ pub(crate) struct H3Connector {
5959 resolver : DynResolver ,
6060 endpoint : Endpoint ,
6161 client_config : H3ClientConfig ,
62+ bound_addr : IpAddr ,
6263}
6364
6465impl H3Connector {
@@ -74,6 +75,7 @@ impl H3Connector {
7475 // FIXME: Replace this when there is a setter.
7576 config. transport_config ( Arc :: new ( transport_config) ) ;
7677
78+ // Pipe the local address through to the endpoint creation
7779 let socket_addr = match local_addr {
7880 Some ( ip) => SocketAddr :: new ( ip, 0 ) ,
7981 None => "[::]:0" . parse :: < SocketAddr > ( ) . unwrap ( ) ,
@@ -82,10 +84,14 @@ impl H3Connector {
8284 let mut endpoint = Endpoint :: client ( socket_addr) ?;
8385 endpoint. set_default_client_config ( config) ;
8486
87+ // Get the actual bound address from the endpoint
88+ let bound_addr = endpoint. local_addr ( ) ?. ip ( ) ;
89+
8590 Ok ( Self {
8691 resolver,
8792 endpoint,
8893 client_config,
94+ bound_addr,
8995 } )
9096 }
9197
@@ -117,28 +123,83 @@ impl H3Connector {
117123 addrs : Vec < SocketAddr > ,
118124 server_name : & str ,
119125 ) -> Result < H3Connection , BoxError > {
120- let mut err = None ;
126+ if addrs. is_empty ( ) {
127+ return Err ( "no addresses to connect to" . into ( ) ) ;
128+ }
129+
130+ let ( mut ipv6_addrs, mut ipv4_addrs) : ( Vec < SocketAddr > , Vec < SocketAddr > ) =
131+ addrs. into_iter ( ) . partition ( |addr| addr. is_ipv6 ( ) ) ;
132+
133+ if self . bound_addr . is_ipv6 ( ) {
134+ ipv4_addrs. clear ( ) ;
135+ } else {
136+ ipv6_addrs. clear ( ) ;
137+ }
138+
139+ if ipv6_addrs. is_empty ( ) {
140+ return Self :: try_addresses_static (
141+ & self . endpoint ,
142+ & ipv4_addrs,
143+ server_name,
144+ & self . client_config ,
145+ )
146+ . await ;
147+ }
148+ if ipv4_addrs. is_empty ( ) {
149+ return Self :: try_addresses_static (
150+ & self . endpoint ,
151+ & ipv6_addrs,
152+ server_name,
153+ & self . client_config ,
154+ )
155+ . await ;
156+ }
157+
158+ let endpoint = self . endpoint . clone ( ) ;
159+ let client_config = self . client_config . clone ( ) ;
160+
161+ match Self :: try_addresses_static ( & endpoint, & ipv6_addrs, server_name, & client_config) . await
162+ {
163+ Ok ( conn) => Ok ( conn) ,
164+ Err ( _) => {
165+ Self :: try_addresses_static ( & endpoint, & ipv4_addrs, server_name, & client_config)
166+ . await
167+ }
168+ }
169+ }
170+
171+ async fn try_addresses_static (
172+ endpoint : & Endpoint ,
173+ addrs : & [ SocketAddr ] ,
174+ server_name : & str ,
175+ client_config : & H3ClientConfig ,
176+ ) -> Result < H3Connection , BoxError > {
177+ let mut last_err: Option < BoxError > = None ;
178+
121179 for addr in addrs {
122- match self . endpoint . connect ( addr, server_name) ?. await {
123- Ok ( new_conn) => {
124- let quinn_conn = Connection :: new ( new_conn) ;
125- let mut h3_client_builder = h3:: client:: builder ( ) ;
126- if let Some ( max_field_section_size) = self . client_config . max_field_section_size
127- {
128- h3_client_builder. max_field_section_size ( max_field_section_size) ;
180+ match endpoint. connect ( * addr, server_name) {
181+ Ok ( connecting) => match connecting. await {
182+ Ok ( new_conn) => {
183+ let quinn_conn = Connection :: new ( new_conn) ;
184+ let mut h3_client_builder = h3:: client:: builder ( ) ;
185+ if let Some ( max_field_section_size) = client_config. max_field_section_size {
186+ h3_client_builder. max_field_section_size ( max_field_section_size) ;
187+ }
188+ if let Some ( send_grease) = client_config. send_grease {
189+ h3_client_builder. send_grease ( send_grease) ;
190+ }
191+ return Ok ( h3_client_builder. build ( quinn_conn) . await ?) ;
129192 }
130- if let Some ( send_grease ) = self . client_config . send_grease {
131- h3_client_builder . send_grease ( send_grease ) ;
193+ Err ( e ) => {
194+ last_err = Some ( Box :: new ( e ) as BoxError ) ;
132195 }
133- return Ok ( h3_client_builder. build ( quinn_conn) . await ?) ;
196+ } ,
197+ Err ( e) => {
198+ last_err = Some ( Box :: new ( e) as BoxError ) ;
134199 }
135- Err ( e) => err = Some ( e) ,
136200 }
137201 }
138202
139- match err {
140- Some ( e) => Err ( Box :: new ( e) as BoxError ) ,
141- None => Err ( "failed to establish connection for HTTP/3 request" . into ( ) ) ,
142- }
203+ Err ( last_err. unwrap_or_else ( || "no addresses available" . into ( ) ) )
143204 }
144205}
0 commit comments