use std::fmt;
#[cfg(not(feature = "tokio"))]
use std::io::Write;
-use std::net::ToSocketAddrs;
+use std::net::{SocketAddr, ToSocketAddrs};
use std::time::Duration;
#[cfg(feature = "tokio")]
/// Timeout for reading the first byte of a response. This is separate from the general read
/// timeout as it is not uncommon for Bitcoin Core to be blocked waiting on UTXO cache flushes for
-/// upwards of a minute or more. Note that we always retry once when we time out, so the maximum
-/// time we allow Bitcoin Core to block for is twice this value.
-const TCP_STREAM_RESPONSE_TIMEOUT: Duration = Duration::from_secs(120);
+/// upwards of 10 minutes on slow devices (e.g. RPis with SSDs over USB). Note that we always retry
+/// once when we time out, so the maximum time we allow Bitcoin Core to block for is twice this
+/// value.
+const TCP_STREAM_RESPONSE_TIMEOUT: Duration = Duration::from_secs(300);
/// Maximum HTTP message header size in bytes.
const MAX_HTTP_MESSAGE_HEADER_SIZE: usize = 8192;
/// Client for making HTTP requests.
pub(crate) struct HttpClient {
+ address: SocketAddr,
stream: TcpStream,
}
TcpStream::from_std(stream)?
};
- Ok(Self { stream })
+ Ok(Self { address, stream })
}
/// Sends a `GET` request for a resource identified by `uri` at the `host`.
/// Sends an HTTP request message and reads the response, returning its body. Attempts to
/// reconnect and retry if the connection has been closed.
async fn send_request_with_retry(&mut self, request: &str) -> std::io::Result<Vec<u8>> {
- let endpoint = self.stream.peer_addr().unwrap();
match self.send_request(request).await {
Ok(bytes) => Ok(bytes),
Err(_) => {
tokio::time::sleep(Duration::from_millis(100)).await;
#[cfg(not(feature = "tokio"))]
std::thread::sleep(Duration::from_millis(100));
- *self = Self::connect(endpoint)?;
+ *self = Self::connect(self.address)?;
self.send_request(request).await
},
}
#[test]
fn connect_to_unresolvable_host() {
match HttpClient::connect(("example.invalid", 80)) {
- Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::Other),
+ Err(e) => {
+ assert!(e.to_string().contains("failed to lookup address information") ||
+ e.to_string().contains("No such host"), "{:?}", e);
+ },
Ok(_) => panic!("Expected error"),
}
}