Skip to content

Commit

Permalink
Allow a connection attempt to timeout and keep trying resolved addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
ex-nihil authored and algesten committed Dec 9, 2023
1 parent 53c59aa commit 9228547
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use log::debug;
use std::io::{self, BufRead, BufReader, Read, Write};
use std::net::SocketAddr;
use std::net::TcpStream;
use std::ops::Div;
use std::time::Duration;
use std::time::Instant;
use std::{fmt, io::Cursor};
Expand Down Expand Up @@ -375,10 +376,18 @@ pub(crate) fn connect_host(
let mut any_err = None;
let mut any_stream_and_addr = None;
// Find the first sock_addr that accepts a connection
let multiple_addrs = sock_addrs.len() > 1;

for sock_addr in sock_addrs {
// ensure connect timeout or overall timeout aren't yet hit.
let timeout = match connect_deadline {
Some(deadline) => Some(time_until_deadline(deadline)?),
Some(deadline) => {
let mut deadline = time_until_deadline(deadline)?;
if multiple_addrs {
deadline = deadline.div(2);
}
Some(deadline)
}
None => None,
};

Expand Down
29 changes: 28 additions & 1 deletion src/test/agent_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::error::Error;
use crate::testserver::{read_request, TestServer};
use std::io::{self, Read, Write};
use std::net::TcpStream;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
use std::thread;
use std::time::Duration;

Expand Down Expand Up @@ -111,6 +111,33 @@ fn custom_resolver() {
assert_eq!(&server.join().unwrap(), b"GET / HTTP/1.1\r\n");
}

#[test]
fn socket_addr_fail_over() {
use std::net::TcpListener;

let listener = TcpListener::bind("127.0.0.1:0").unwrap();

let local_addr = listener.local_addr().unwrap();
let non_routable_ipv4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 255, 255, 1)), 9872);
let server = std::thread::spawn(move || {
let (mut client, _) = listener.accept().unwrap();
let mut buf = vec![0u8; 16];
let read = client.read(&mut buf).unwrap();
buf.truncate(read);
buf
});

AgentBuilder::new()
.resolver(move |_: &str| Ok(vec![non_routable_ipv4, local_addr]))
.timeout_connect(Duration::from_secs(2))
.build()
.get("http://cool.server/")
.call()
.ok();

assert_eq!(&server.join().unwrap(), b"GET / HTTP/1.1\r\n");
}

#[cfg(feature = "cookies")]
#[cfg(test)]
fn cookie_and_redirect(mut stream: TcpStream) -> io::Result<()> {
Expand Down

0 comments on commit 9228547

Please sign in to comment.