net: perform DNS lookup on connect / bind. (#1499)

A sealed `net::ToSocketAddrs` trait is added. This trait is not intended
to be used by users. Instead, it is an argument to `connect` and `bind`
functions.

The operating system's DNS lookup functionality is used. Blocking
operations are performed on a thread pool in order to avoid blocking the
runtime.
This commit is contained in:
Carl Lerche
2019-08-28 13:25:50 -07:00
committed by GitHub
parent de9f05d4d3
commit fc1640891e
33 changed files with 632 additions and 218 deletions
+1 -2
View File
@@ -45,12 +45,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
let state = Lock::new(Shared::new());
let addr = env::args().nth(1).unwrap_or("127.0.0.1:6142".to_string());
let addr = addr.parse::<SocketAddr>()?;
// Bind a TCP listener to the socket address.
//
// Note that this is the Tokio TcpListener, which is fully async.
let mut listener = TcpListener::bind(&addr)?;
let mut listener = TcpListener::bind(&addr).await?;
println!("server running on {}", addr);
+4 -4
View File
@@ -126,13 +126,13 @@ mod udp {
// We'll bind our UDP socket to a local IP/port, but for now we
// basically let the OS pick both of those.
let bind_addr = if addr.ip().is_ipv4() {
"0.0.0.0:0".parse()?
"0.0.0.0:0"
} else {
"[::]:0".parse()?
"[::]:0"
};
let socket = UdpSocket::bind(&bind_addr)?;
socket.connect(addr)?;
let socket = UdpSocket::bind(&bind_addr).await?;
socket.connect(addr).await?;
let (mut r, mut w) = socket.split();
future::try_join(send(stdin, &mut w), recv(stdout, &mut r)).await?;
+1 -2
View File
@@ -52,9 +52,8 @@ impl Server {
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
let socket = UdpSocket::bind(&addr)?;
let socket = UdpSocket::bind(&addr).await?;
println!("Listening on: {}", socket.local_addr()?);
let server = Server {
+1 -3
View File
@@ -27,7 +27,6 @@ use tokio::net::TcpListener;
use std::env;
use std::error::Error;
use std::net::SocketAddr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
@@ -35,12 +34,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
// program, but otherwise we'll just set up our TCP listener on
// 127.0.0.1:8080 for connections.
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
// Next up we create a TCP listener which will listen for incoming
// connections. This TCP listener is bound to the address we determined
// above and must be associated with an event loop.
let mut listener = TcpListener::bind(&addr)?;
let mut listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
loop {
+1 -4
View File
@@ -13,7 +13,6 @@
#![warn(rust_2018_idioms)]
use tokio;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
@@ -21,12 +20,10 @@ use std::error::Error;
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
let addr = "127.0.0.1:6142".parse()?;
// Open a TCP stream to the socket address.
//
// Note that this is the Tokio TcpStream, which is fully async.
let mut stream = TcpStream::connect(&addr).await?;
let mut stream = TcpStream::connect("127.0.0.1:6142").await?;
println!("created stream");
let result = stream.write(b"hello world\n").await;
+3 -5
View File
@@ -54,28 +54,26 @@
#![warn(rust_2018_idioms)]
use std::env;
use std::net::SocketAddr;
use tokio;
use tokio::codec::{BytesCodec, Decoder};
use tokio::net::TcpListener;
use tokio::prelude::*;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Allow passing an address to listen on as the first argument of this
// program, but otherwise we'll just set up our TCP listener on
// 127.0.0.1:8080 for connections.
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
// Next up we create a TCP listener which will listen for incoming
// connections. This TCP listener is bound to the address we determined
// above and must be associated with an event loop, so we pass in a handle
// to our event loop. After the socket's created we inform that we're ready
// to go and start accepting connections.
let mut listener = TcpListener::bind(&addr)?;
let mut listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
loop {
+5 -8
View File
@@ -23,7 +23,7 @@
#![warn(rust_2018_idioms)]
use futures::{future::try_join, FutureExt, StreamExt};
use std::{env, error::Error, net::SocketAddr};
use std::{env, error::Error};
use tokio::{
io::AsyncReadExt,
net::{TcpListener, TcpStream},
@@ -32,18 +32,15 @@ use tokio::{
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let listen_addr = env::args().nth(1).unwrap_or("127.0.0.1:8081".to_string());
let listen_addr = listen_addr.parse::<SocketAddr>()?;
let server_addr = env::args().nth(2).unwrap_or("127.0.0.1:8080".to_string());
let server_addr = server_addr.parse::<SocketAddr>()?;
println!("Listening on: {}", listen_addr);
println!("Proxying to: {}", server_addr);
let mut incoming = TcpListener::bind(&listen_addr)?.incoming();
let mut incoming = TcpListener::bind(listen_addr).await?.incoming();
while let Some(Ok(inbound)) = incoming.next().await {
let transfer = transfer(inbound, server_addr).map(|r| {
let transfer = transfer(inbound, server_addr.clone()).map(|r| {
if let Err(e) = r {
println!("Failed to transfer; error={}", e);
}
@@ -55,8 +52,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
async fn transfer(inbound: TcpStream, proxy_addr: SocketAddr) -> Result<(), Box<dyn Error>> {
let outbound = TcpStream::connect(&proxy_addr).await?;
async fn transfer(inbound: TcpStream, proxy_addr: String) -> Result<(), Box<dyn Error>> {
let outbound = TcpStream::connect(proxy_addr).await?;
let (mut ri, mut wi) = inbound.split();
let (mut ro, mut wo) = outbound.split();
+2 -3
View File
@@ -44,7 +44,6 @@
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use tokio;
@@ -88,8 +87,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Parse the address we're going to run this server on
// and set up our TCP listener to accept connections.
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
let mut listener = TcpListener::bind(&addr)?;
let mut listener = TcpListener::bind(&addr).await?;
println!("Listening on: {}", addr);
// Create the shared state of this server that will be shared amongst all
+2 -3
View File
@@ -17,7 +17,7 @@ use bytes::BytesMut;
use futures::{SinkExt, StreamExt};
use http::{header::HeaderValue, Request, Response, StatusCode};
use serde::Serialize;
use std::{env, error::Error, fmt, io, net::SocketAddr};
use std::{env, error::Error, fmt, io};
use tokio::{
codec::{Decoder, Encoder, Framed},
net::{TcpListener, TcpStream},
@@ -28,9 +28,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Parse the arguments, bind the TCP socket we'll be listening to, spin up
// our worker threads, and start shipping sockets to those worker threads.
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
let mut incoming = TcpListener::bind(&addr)?.incoming();
let mut incoming = TcpListener::bind(&addr).await?.incoming();
println!("Listening on: {}", addr);
while let Some(Ok(stream)) = incoming.next().await {
+2 -2
View File
@@ -55,9 +55,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
.parse()?;
let mut socket = UdpSocket::bind(&local_addr)?;
let mut socket = UdpSocket::bind(local_addr).await?;
const MAX_DATAGRAM_SIZE: usize = 65_507;
socket.connect(&remote_addr)?;
socket.connect(&remote_addr).await?;
let data = get_stdin_data()?;
socket.send(&data).await?;
let mut data = vec![0u8; MAX_DATAGRAM_SIZE];
+2 -3
View File
@@ -27,11 +27,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
let _ = env_logger::init();
let addr = env::args().nth(1).unwrap_or("127.0.0.1:0".to_string());
let addr = addr.parse::<SocketAddr>()?;
// Bind both our sockets and then figure out what ports we got.
let a = UdpSocket::bind(&addr)?;
let b = UdpSocket::bind(&addr)?;
let a = UdpSocket::bind(&addr).await?;
let b = UdpSocket::bind(&addr).await?;
let b_addr = b.local_addr()?;
+1 -3
View File
@@ -73,8 +73,7 @@ pub struct Spawn(());
///
/// # async fn process<T>(t: T) {}
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
/// let addr = "127.0.0.1:8080".parse()?;
/// let mut listener = TcpListener::bind(&addr).unwrap();
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
///
/// loop {
/// let (socket, _) = listener.accept().await?;
@@ -84,7 +83,6 @@ pub struct Spawn(());
/// process(socket).await
/// });
/// }
/// # Ok(())
/// # }
/// ```
///
+1 -2
View File
@@ -35,8 +35,7 @@
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let addr = "127.0.0.1:8080".parse()?;
//! let mut listener = TcpListener::bind(&addr).unwrap();
//! let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
//!
//! loop {
//! let (mut socket, _) = listener.accept().await?;
+3 -5
View File
@@ -39,8 +39,7 @@
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let addr = "127.0.0.1:8080".parse()?;
//! let mut listener = TcpListener::bind(&addr).unwrap();
//! let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
//!
//! loop {
//! let (mut socket, _) = listener.accept().await?;
@@ -87,12 +86,11 @@
//!
//! fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Create the runtime
//! let mut rt = Runtime::new().unwrap();
//! let mut rt = Runtime::new()?;
//!
//! // Spawn the root task
//! rt.block_on(async {
//! let addr = "127.0.0.1:8080".parse()?;
//! let mut listener = TcpListener::bind(&addr).unwrap();
//! let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
//!
//! loop {
//! let (mut socket, _) = listener.accept().await?;
+1 -2
View File
@@ -13,8 +13,7 @@ use std::thread;
async fn echo_server() {
const N: usize = 1024;
let addr = assert_ok!("127.0.0.1:0".parse());
let mut srv = assert_ok!(TcpListener::bind(&addr));
let mut srv = assert_ok!(TcpListener::bind("127.0.0.1:0").await);
let addr = assert_ok!(srv.local_addr());
let msg = "foo bar baz";
+1 -2
View File
@@ -50,9 +50,8 @@ fn test_drop_on_notify() {
// Define a task that just drains the listener
let task = Arc::new(Task::new(async move {
let addr = assert_ok!("127.0.0.1:0".parse());
// Create a listener
let mut listener = assert_ok!(TcpListener::bind(&addr));
let mut listener = assert_ok!(TcpListener::bind("127.0.0.1:0").await);
// Send the address
let addr = listener.local_addr().unwrap();
+1 -2
View File
@@ -13,8 +13,7 @@ use std::time::{Duration, Instant};
use tokio::timer::delay;
async fn client_server(tx: mpsc::Sender<()>) {
let addr = assert_ok!("127.0.0.1:0".parse());
let mut server = assert_ok!(TcpListener::bind(&addr));
let mut server = assert_ok!(TcpListener::bind("127.0.0.1:0").await);
// Get the assigned address
let addr = assert_ok!(server.local_addr());
+2 -5
View File
@@ -15,8 +15,7 @@ use std::thread;
use std::time::{Duration, Instant};
async fn client_server(tx: mpsc::Sender<()>) {
let addr = assert_ok!("127.0.0.1:0".parse());
let mut server = assert_ok!(TcpListener::bind(&addr));
let mut server = assert_ok!(TcpListener::bind("127.0.0.1:0").await);
// Get the assigned address
let addr = assert_ok!(server.local_addr());
@@ -78,11 +77,9 @@ fn block_on_socket() {
let rt = Runtime::new().unwrap();
rt.block_on(async move {
let addr = "127.0.0.1:0".parse().unwrap();
let (tx, rx) = oneshot::channel();
let mut listener = TcpListener::bind(&addr).unwrap();
let mut listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
tokio::spawn(async move {