mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
auto merge of #18462 : netvl/rust/to-socket-addr, r=alexcrichton
This is a follow-up to [RFC PR #173](https://github.com/rust-lang/rfcs/pull/173). I was told there that changes like this don't need to go through the RFC process, so I'm submitting this directly. This PR introduces `ToSocketAddr` trait as defined in said RFC. This trait defines a conversion from different types like `&str`, `(&str, u16)` or even `SocketAddr` to `SocketAddr`. Then this trait is used in all constructor methods for `TcpStream`, `TcpListener` and `UdpSocket`. This unifies these constructor methods - previously they were using different types of input parameters (TCP ones used `(&str, u16)` pair while UDP ones used `SocketAddr`), which is not consistent by itself and sometimes inconvenient - for example, when the address initially is available as `SocketAddr`, you still need to convert it to string to pass it to e.g. `TcpStream`. This is very prominently demonstrated by the unit tests for TCP functionality. This PR makes working with network objects much like with `Path`, which also uses similar trait to be able to be constructed from `&[u8]`, `Vec<u8>` and other `Path`s. This is a breaking change. If constant literals were used before, like this: ```rust TcpStream::connect("localhost", 12345) ``` then the nicest fix is to change it to this: ```rust TcpStream::connect("localhost:12345") ``` If variables were used before, like this: ```rust TcpStream::connect(some_address, some_port) ``` then the arguments should be wrapped in another set of parentheses: ```rust TcpStream::connect((some_address, some_port)) ``` `UdpSocket` usages won't break because its constructor method accepted `SocketAddr` which implements `ToSocketAddr`, so `bind()` calls: ```rust UdpSocket::bind(some_socket_addr) ``` will continue working as before. I haven't changed `UdpStream` constructor because it is deprecated anyway.
This commit is contained in:
commit
5c1fd5f8b7
@ -444,7 +444,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
|
||||
//waiting 1 second for gdbserver start
|
||||
timer::sleep(Duration::milliseconds(1000));
|
||||
let result = task::try(proc() {
|
||||
tcp::TcpStream::connect("127.0.0.1", 5039).unwrap();
|
||||
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
|
||||
});
|
||||
if result.is_err() {
|
||||
continue;
|
||||
|
@ -91,7 +91,7 @@ Some examples of obvious things you might want to do
|
||||
# // locally, we still want to be type checking this code, so lets
|
||||
# // just stop it running (#11576)
|
||||
# if false {
|
||||
let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap();
|
||||
let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
|
||||
socket.write(b"GET / HTTP/1.0\n\n");
|
||||
let response = socket.read_to_end();
|
||||
# }
|
||||
@ -106,7 +106,7 @@ Some examples of obvious things you might want to do
|
||||
use std::io::{TcpListener, TcpStream};
|
||||
use std::io::{Acceptor, Listener};
|
||||
|
||||
let listener = TcpListener::bind("127.0.0.1", 80);
|
||||
let listener = TcpListener::bind("127.0.0.1:80");
|
||||
|
||||
// bind the listener to the specified address
|
||||
let mut acceptor = listener.listen();
|
||||
|
@ -17,10 +17,14 @@
|
||||
|
||||
use fmt;
|
||||
use from_str::FromStr;
|
||||
use io::{mod, IoResult, IoError};
|
||||
use io::net;
|
||||
use iter::Iterator;
|
||||
use option::{Option, None, Some};
|
||||
use result::{Ok, Err};
|
||||
use str::StrSlice;
|
||||
use slice::{MutableCloneableSlice, MutableSlice, ImmutableSlice};
|
||||
use vec::Vec;
|
||||
|
||||
pub type Port = u16;
|
||||
|
||||
@ -348,6 +352,189 @@ impl FromStr for SocketAddr {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for objects which can be converted or resolved to one or more `SocketAddr` values.
|
||||
///
|
||||
/// Implementing types minimally have to implement either `to_socket_addr` or `to_socket_addr_all`
|
||||
/// method, and its trivial counterpart will be available automatically.
|
||||
///
|
||||
/// This trait is used for generic address resolution when constructing network objects.
|
||||
/// By default it is implemented for the following types:
|
||||
///
|
||||
/// * `SocketAddr` - `to_socket_addr` is identity function.
|
||||
///
|
||||
/// * `(IpAddr, u16)` - `to_socket_addr` constructs `SocketAddr` trivially.
|
||||
///
|
||||
/// * `(&str, u16)` - the string should be either a string representation of an IP address
|
||||
/// expected by `FromStr` implementation for `IpAddr` or a host name.
|
||||
///
|
||||
/// For the former, `to_socket_addr_all` returns a vector with a single element corresponding
|
||||
/// to that IP address joined with the given port.
|
||||
///
|
||||
/// For the latter, it tries to resolve the host name and returns a vector of all IP addresses
|
||||
/// for the host name, each joined with the given port.
|
||||
///
|
||||
/// * `&str` - the string should be either a string representation of a `SocketAddr` as
|
||||
/// expected by its `FromStr` implementation or a string like `<host_name>:<port>` pair
|
||||
/// where `<port>` is a `u16` value.
|
||||
///
|
||||
/// For the former, `to_socker_addr_all` returns a vector with a single element corresponding
|
||||
/// to that socker address.
|
||||
///
|
||||
/// For the latter, it tries to resolve the host name and returns a vector of all IP addresses
|
||||
/// for the host name, each joined with the port.
|
||||
///
|
||||
///
|
||||
/// This trait allows constructing network objects like `TcpStream` or `UdpSocket` easily with
|
||||
/// values of various types for the bind/connection address. It is needed because sometimes
|
||||
/// one type is more appropriate than the other: for simple uses a string like `"localhost:12345"`
|
||||
/// is much nicer than manual construction of the corresponding `SocketAddr`, but sometimes
|
||||
/// `SocketAddr` value is *the* main source of the address, and converting it to some other type
|
||||
/// (e.g. a string) just for it to be converted back to `SocketAddr` in constructor methods
|
||||
/// is pointless.
|
||||
///
|
||||
/// Some examples:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![allow(unused_must_use)]
|
||||
///
|
||||
/// use std::io::{TcpStream, TcpListener};
|
||||
/// use std::io::net::udp::UdpSocket;
|
||||
/// use std::io::net::ip::{Ipv4Addr, SocketAddr};
|
||||
///
|
||||
/// fn main() {
|
||||
/// // The following lines are equivalent modulo possible "localhost" name resolution
|
||||
/// // differences
|
||||
/// let tcp_s = TcpStream::connect(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 12345 });
|
||||
/// let tcp_s = TcpStream::connect((Ipv4Addr(127, 0, 0, 1), 12345u16));
|
||||
/// let tcp_s = TcpStream::connect(("127.0.0.1", 12345u16));
|
||||
/// let tcp_s = TcpStream::connect(("localhost", 12345u16));
|
||||
/// let tcp_s = TcpStream::connect("127.0.0.1:12345");
|
||||
/// let tcp_s = TcpStream::connect("localhost:12345");
|
||||
///
|
||||
/// // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to() behave similarly
|
||||
/// let tcp_l = TcpListener::bind("localhost:12345");
|
||||
///
|
||||
/// let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451u16)).unwrap();
|
||||
/// udp_s.send_to([7u8, 7u8, 7u8].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451u16));
|
||||
/// }
|
||||
/// ```
|
||||
pub trait ToSocketAddr {
|
||||
/// Converts this object to single socket address value.
|
||||
///
|
||||
/// If more than one value is available, this method returns the first one. If no
|
||||
/// values are available, this method returns an `IoError`.
|
||||
///
|
||||
/// By default this method delegates to `to_socket_addr_all` method, taking the first
|
||||
/// item from its result.
|
||||
fn to_socket_addr(&self) -> IoResult<SocketAddr> {
|
||||
self.to_socket_addr_all()
|
||||
.and_then(|v| v.into_iter().next().ok_or_else(|| IoError {
|
||||
kind: io::InvalidInput,
|
||||
desc: "no address available",
|
||||
detail: None
|
||||
}))
|
||||
}
|
||||
|
||||
/// Converts this object to all available socket address values.
|
||||
///
|
||||
/// Some values like host name string naturally corrrespond to multiple IP addresses.
|
||||
/// This method tries to return all available addresses corresponding to this object.
|
||||
///
|
||||
/// By default this method delegates to `to_socket_addr` method, creating a singleton
|
||||
/// vector from its result.
|
||||
#[inline]
|
||||
fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
|
||||
self.to_socket_addr().map(|a| vec![a])
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSocketAddr for SocketAddr {
|
||||
#[inline]
|
||||
fn to_socket_addr(&self) -> IoResult<SocketAddr> { Ok(*self) }
|
||||
}
|
||||
|
||||
impl ToSocketAddr for (IpAddr, u16) {
|
||||
#[inline]
|
||||
fn to_socket_addr(&self) -> IoResult<SocketAddr> {
|
||||
let (ip, port) = *self;
|
||||
Ok(SocketAddr { ip: ip, port: port })
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_socket_addr(s: &str, p: u16) -> IoResult<Vec<SocketAddr>> {
|
||||
net::get_host_addresses(s)
|
||||
.map(|v| v.into_iter().map(|a| SocketAddr { ip: a, port: p }).collect())
|
||||
}
|
||||
|
||||
fn parse_and_resolve_socket_addr(s: &str) -> IoResult<Vec<SocketAddr>> {
|
||||
macro_rules! try_opt(
|
||||
($e:expr, $msg:expr) => (
|
||||
match $e {
|
||||
Some(r) => r,
|
||||
None => return Err(IoError {
|
||||
kind: io::InvalidInput,
|
||||
desc: $msg,
|
||||
detail: None
|
||||
})
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// split the string by ':' and convert the second part to u16
|
||||
let mut parts_iter = s.rsplitn(2, ':');
|
||||
let port_str = try_opt!(parts_iter.next(), "invalid socket address");
|
||||
let host = try_opt!(parts_iter.next(), "invalid socket address");
|
||||
let port: u16 = try_opt!(FromStr::from_str(port_str), "invalid port value");
|
||||
resolve_socket_addr(host, port)
|
||||
}
|
||||
|
||||
impl<'a> ToSocketAddr for (&'a str, u16) {
|
||||
fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
|
||||
let (host, port) = *self;
|
||||
|
||||
// try to parse the host as a regular IpAddr first
|
||||
match FromStr::from_str(host) {
|
||||
Some(addr) => return Ok(vec![SocketAddr {
|
||||
ip: addr,
|
||||
port: port
|
||||
}]),
|
||||
None => {}
|
||||
}
|
||||
|
||||
resolve_socket_addr(host, port)
|
||||
}
|
||||
}
|
||||
|
||||
// accepts strings like 'localhost:12345'
|
||||
impl<'a> ToSocketAddr for &'a str {
|
||||
fn to_socket_addr(&self) -> IoResult<SocketAddr> {
|
||||
// try to parse as a regular SocketAddr first
|
||||
match FromStr::from_str(*self) {
|
||||
Some(addr) => return Ok(addr),
|
||||
None => {}
|
||||
}
|
||||
|
||||
parse_and_resolve_socket_addr(*self)
|
||||
.and_then(|v| v.into_iter().next()
|
||||
.ok_or_else(|| IoError {
|
||||
kind: io::InvalidInput,
|
||||
desc: "no address available",
|
||||
detail: None
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
|
||||
// try to parse as a regular SocketAddr first
|
||||
match FromStr::from_str(*self) {
|
||||
Some(addr) => return Ok(vec![addr]),
|
||||
None => {}
|
||||
}
|
||||
|
||||
parse_and_resolve_socket_addr(*self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
@ -457,4 +644,48 @@ mod test {
|
||||
assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
|
||||
"8:9:a:b:c:d:e:f".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_socketaddr() {
|
||||
let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 12345 };
|
||||
assert_eq!(Ok(a), a.to_socket_addr());
|
||||
assert_eq!(Ok(vec![a]), a.to_socket_addr_all());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_ipaddr_u16() {
|
||||
let a = Ipv4Addr(77, 88, 21, 11);
|
||||
let p = 12345u16;
|
||||
let e = SocketAddr { ip: a, port: p };
|
||||
assert_eq!(Ok(e), (a, p).to_socket_addr());
|
||||
assert_eq!(Ok(vec![e]), (a, p).to_socket_addr_all());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_str_u16() {
|
||||
let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 24352 };
|
||||
assert_eq!(Ok(a), ("77.88.21.11", 24352u16).to_socket_addr());
|
||||
assert_eq!(Ok(vec![a]), ("77.88.21.11", 24352u16).to_socket_addr_all());
|
||||
|
||||
let a = SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 };
|
||||
assert_eq!(Ok(a), ("2a02:6b8:0:1::1", 53).to_socket_addr());
|
||||
assert_eq!(Ok(vec![a]), ("2a02:6b8:0:1::1", 53).to_socket_addr_all());
|
||||
|
||||
let a = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 23924 };
|
||||
assert!(("localhost", 23924u16).to_socket_addr_all().unwrap().contains(&a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_str() {
|
||||
let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 24352 };
|
||||
assert_eq!(Ok(a), "77.88.21.11:24352".to_socket_addr());
|
||||
assert_eq!(Ok(vec![a]), "77.88.21.11:24352".to_socket_addr_all());
|
||||
|
||||
let a = SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 };
|
||||
assert_eq!(Ok(a), "[2a02:6b8:0:1::1]:53".to_socket_addr());
|
||||
assert_eq!(Ok(vec![a]), "[2a02:6b8:0:1::1]:53".to_socket_addr_all());
|
||||
|
||||
let a = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 23924 };
|
||||
assert!("localhost:23924".to_socket_addr_all().unwrap().contains(&a));
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,11 @@
|
||||
|
||||
//! Networking I/O
|
||||
|
||||
use io::{IoError, IoResult, InvalidInput};
|
||||
use option::None;
|
||||
use result::{Result, Ok, Err};
|
||||
use rt::rtio;
|
||||
use self::ip::{Ipv4Addr, Ipv6Addr, IpAddr};
|
||||
use self::ip::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr, ToSocketAddr};
|
||||
|
||||
pub use self::addrinfo::get_host_addresses;
|
||||
|
||||
@ -38,3 +41,44 @@ fn from_rtio(ip: rtio::IpAddr) -> IpAddr {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_addresses_io<A: ToSocketAddr, T>(
|
||||
addr: A,
|
||||
action: |&mut rtio::IoFactory, rtio::SocketAddr| -> Result<T, rtio::IoError>
|
||||
) -> Result<T, IoError> {
|
||||
const DEFAULT_ERROR: IoError = IoError {
|
||||
kind: InvalidInput,
|
||||
desc: "no addresses found for hostname",
|
||||
detail: None
|
||||
};
|
||||
|
||||
let addresses = try!(addr.to_socket_addr_all());
|
||||
let mut err = DEFAULT_ERROR;
|
||||
for addr in addresses.into_iter() {
|
||||
let addr = rtio::SocketAddr { ip: to_rtio(addr.ip), port: addr.port };
|
||||
match rtio::LocalIo::maybe_raise(|io| action(io, addr)) {
|
||||
Ok(r) => return Ok(r),
|
||||
Err(e) => err = IoError::from_rtio_error(e)
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
|
||||
fn with_addresses<A: ToSocketAddr, T>(addr: A, action: |SocketAddr| -> IoResult<T>)
|
||||
-> IoResult<T> {
|
||||
const DEFAULT_ERROR: IoError = IoError {
|
||||
kind: InvalidInput,
|
||||
desc: "no addresses found for hostname",
|
||||
detail: None
|
||||
};
|
||||
|
||||
let addresses = try!(addr.to_socket_addr_all());
|
||||
let mut err = DEFAULT_ERROR;
|
||||
for addr in addresses.into_iter() {
|
||||
match action(addr) {
|
||||
Ok(r) => return Ok(r),
|
||||
Err(e) => err = e
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
|
@ -20,18 +20,15 @@
|
||||
use clone::Clone;
|
||||
use io::IoResult;
|
||||
use iter::Iterator;
|
||||
use slice::ImmutableSlice;
|
||||
use result::{Ok,Err};
|
||||
use io::net::addrinfo::get_host_addresses;
|
||||
use io::net::ip::SocketAddr;
|
||||
use io::{IoError, ConnectionFailed, InvalidInput};
|
||||
use io::net::ip::{SocketAddr, ToSocketAddr};
|
||||
use io::IoError;
|
||||
use io::{Reader, Writer, Listener, Acceptor};
|
||||
use io::{standard_error, TimedOut};
|
||||
use from_str::FromStr;
|
||||
use kinds::Send;
|
||||
use option::{None, Some, Option};
|
||||
use boxed::Box;
|
||||
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
|
||||
use rt::rtio::{IoFactory, RtioSocket, RtioTcpListener};
|
||||
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
|
||||
use rt::rtio;
|
||||
use time::Duration;
|
||||
@ -45,7 +42,7 @@ use time::Duration;
|
||||
/// # #![allow(unused_must_use)]
|
||||
/// use std::io::TcpStream;
|
||||
///
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1", 34254);
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:34254");
|
||||
///
|
||||
/// stream.write([1]);
|
||||
/// let mut buf = [0];
|
||||
@ -61,35 +58,13 @@ impl TcpStream {
|
||||
TcpStream { obj: s }
|
||||
}
|
||||
|
||||
/// Open a TCP connection to a remote host by hostname or IP address.
|
||||
/// Open a TCP connection to a remote host.
|
||||
///
|
||||
/// `host` can be a hostname or IP address string. If no error is
|
||||
/// encountered, then `Ok(stream)` is returned.
|
||||
pub fn connect(host: &str, port: u16) -> IoResult<TcpStream> {
|
||||
let addresses = match FromStr::from_str(host) {
|
||||
Some(addr) => vec!(addr),
|
||||
None => try!(get_host_addresses(host))
|
||||
};
|
||||
let mut err = IoError {
|
||||
kind: ConnectionFailed,
|
||||
desc: "no addresses found for hostname",
|
||||
detail: None
|
||||
};
|
||||
for addr in addresses.iter() {
|
||||
let addr = rtio::SocketAddr{ ip: super::to_rtio(*addr), port: port };
|
||||
let result = LocalIo::maybe_raise(|io| {
|
||||
io.tcp_connect(addr, None).map(TcpStream::new)
|
||||
});
|
||||
match result {
|
||||
Ok(stream) => {
|
||||
return Ok(stream)
|
||||
}
|
||||
Err(connect_err) => {
|
||||
err = IoError::from_rtio_error(connect_err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
/// `addr` is an address of the remote host. Anything which implements `ToSocketAddr`
|
||||
/// trait can be supplied for the address; see this trait documentation for
|
||||
/// concrete examples.
|
||||
pub fn connect<A: ToSocketAddr>(addr: A) -> IoResult<TcpStream> {
|
||||
super::with_addresses_io(addr, |io, addr| io.tcp_connect(addr, None).map(TcpStream::new))
|
||||
}
|
||||
|
||||
/// Creates a TCP connection to a remote socket address, timing out after
|
||||
@ -99,23 +74,21 @@ impl TcpStream {
|
||||
/// specified elapses before a connection is made an error will be
|
||||
/// returned. The error's kind will be `TimedOut`.
|
||||
///
|
||||
/// Note that the `addr` argument may one day be split into a separate host
|
||||
/// and port, similar to the API seen in `connect`.
|
||||
/// Same as the `connect` method, `addr` argument type can be anything which
|
||||
/// implements `ToSocketAddr` trait.
|
||||
///
|
||||
/// If a `timeout` with zero or negative duration is specified then
|
||||
/// the function returns `Err`, with the error kind set to `TimedOut`.
|
||||
#[experimental = "the timeout argument may eventually change types"]
|
||||
pub fn connect_timeout(addr: SocketAddr,
|
||||
timeout: Duration) -> IoResult<TcpStream> {
|
||||
pub fn connect_timeout<A: ToSocketAddr>(addr: A,
|
||||
timeout: Duration) -> IoResult<TcpStream> {
|
||||
if timeout <= Duration::milliseconds(0) {
|
||||
return Err(standard_error(TimedOut));
|
||||
}
|
||||
|
||||
let SocketAddr { ip, port } = addr;
|
||||
let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
|
||||
LocalIo::maybe_raise(|io| {
|
||||
super::with_addresses_io(addr, |io, addr|
|
||||
io.tcp_connect(addr, Some(timeout.num_milliseconds() as u64)).map(TcpStream::new)
|
||||
}).map_err(IoError::from_rtio_error)
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote peer of this TCP connection.
|
||||
@ -174,7 +147,7 @@ impl TcpStream {
|
||||
/// use std::io::TcpStream;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1", 34254).unwrap();
|
||||
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
|
||||
/// let stream2 = stream.clone();
|
||||
///
|
||||
/// spawn(proc() {
|
||||
@ -311,7 +284,7 @@ impl Writer for TcpStream {
|
||||
/// use std::io::{TcpListener, TcpStream};
|
||||
/// use std::io::{Acceptor, Listener};
|
||||
///
|
||||
/// let listener = TcpListener::bind("127.0.0.1", 80);
|
||||
/// let listener = TcpListener::bind("127.0.0.1:80");
|
||||
///
|
||||
/// // bind the listener to the specified address
|
||||
/// let mut acceptor = listener.listen();
|
||||
@ -340,32 +313,18 @@ pub struct TcpListener {
|
||||
}
|
||||
|
||||
impl TcpListener {
|
||||
/// Creates a new `TcpListener` which will be bound to the specified IP
|
||||
/// and port. This listener is not ready for accepting connections,
|
||||
/// `listen` must be called on it before that's possible.
|
||||
/// Creates a new `TcpListener` which will be bound to the specified address.
|
||||
/// This listener is not ready for accepting connections, `listen` must be called
|
||||
/// on it before that's possible.
|
||||
///
|
||||
/// Binding with a port number of 0 will request that the OS assigns a port
|
||||
/// to this listener. The port allocated can be queried via the
|
||||
/// `socket_name` function.
|
||||
pub fn bind(addr: &str, port: u16) -> IoResult<TcpListener> {
|
||||
match FromStr::from_str(addr) {
|
||||
Some(ip) => {
|
||||
let addr = rtio::SocketAddr{
|
||||
ip: super::to_rtio(ip),
|
||||
port: port,
|
||||
};
|
||||
LocalIo::maybe_raise(|io| {
|
||||
io.tcp_bind(addr).map(|l| TcpListener { obj: l })
|
||||
}).map_err(IoError::from_rtio_error)
|
||||
}
|
||||
None => {
|
||||
Err(IoError{
|
||||
kind: InvalidInput,
|
||||
desc: "invalid IP address specified",
|
||||
detail: None
|
||||
})
|
||||
}
|
||||
}
|
||||
///
|
||||
/// The address type can be any implementor of `ToSocketAddr` trait. See its
|
||||
/// documentation for concrete examples.
|
||||
pub fn bind<A: ToSocketAddr>(addr: A) -> IoResult<TcpListener> {
|
||||
super::with_addresses_io(addr, |io, addr| io.tcp_bind(addr).map(|l| TcpListener { obj: l }))
|
||||
}
|
||||
|
||||
/// Returns the local socket address of this listener.
|
||||
@ -419,7 +378,7 @@ impl TcpAcceptor {
|
||||
/// use std::io::TcpListener;
|
||||
/// use std::io::{Listener, Acceptor, TimedOut};
|
||||
///
|
||||
/// let mut a = TcpListener::bind("127.0.0.1", 8482).listen().unwrap();
|
||||
/// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
|
||||
///
|
||||
/// // After 100ms have passed, all accepts will fail
|
||||
/// a.set_timeout(Some(100));
|
||||
@ -462,7 +421,7 @@ impl TcpAcceptor {
|
||||
/// # #![allow(experimental)]
|
||||
/// use std::io::{TcpListener, Listener, Acceptor, EndOfFile};
|
||||
///
|
||||
/// let mut a = TcpListener::bind("127.0.0.1", 8482).listen().unwrap();
|
||||
/// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
|
||||
/// let a2 = a.clone();
|
||||
///
|
||||
/// spawn(proc() {
|
||||
@ -531,7 +490,7 @@ mod test {
|
||||
#[cfg_attr(any(windows, target_os = "android"), ignore)]
|
||||
#[test]
|
||||
fn bind_error() {
|
||||
match TcpListener::bind("0.0.0.0", 1) {
|
||||
match TcpListener::bind("0.0.0.0:1") {
|
||||
Ok(..) => panic!(),
|
||||
Err(e) => assert_eq!(e.kind, PermissionDenied),
|
||||
}
|
||||
@ -539,7 +498,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn connect_error() {
|
||||
match TcpStream::connect("0.0.0.0", 1) {
|
||||
match TcpStream::connect("0.0.0.0:1") {
|
||||
Ok(..) => panic!(),
|
||||
Err(e) => assert_eq!(e.kind, ConnectionRefused),
|
||||
}
|
||||
@ -548,13 +507,11 @@ mod test {
|
||||
#[test]
|
||||
fn listen_ip4_localhost() {
|
||||
let socket_addr = next_test_ip4();
|
||||
let ip_str = socket_addr.ip.to_string();
|
||||
let port = socket_addr.port;
|
||||
let listener = TcpListener::bind(ip_str.as_slice(), port);
|
||||
let listener = TcpListener::bind(socket_addr);
|
||||
let mut acceptor = listener.listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect("localhost", port);
|
||||
let mut stream = TcpStream::connect(("localhost", socket_addr.port));
|
||||
stream.write([144]).unwrap();
|
||||
});
|
||||
|
||||
@ -567,12 +524,10 @@ mod test {
|
||||
#[test]
|
||||
fn connect_localhost() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect("localhost", addr.port);
|
||||
let mut stream = TcpStream::connect(("localhost", addr.port));
|
||||
stream.write([64]).unwrap();
|
||||
});
|
||||
|
||||
@ -585,12 +540,10 @@ mod test {
|
||||
#[test]
|
||||
fn connect_ip4_loopback() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect("127.0.0.1", addr.port);
|
||||
let mut stream = TcpStream::connect(("127.0.0.1", addr.port));
|
||||
stream.write([44]).unwrap();
|
||||
});
|
||||
|
||||
@ -603,12 +556,10 @@ mod test {
|
||||
#[test]
|
||||
fn connect_ip6_loopback() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect("::1", addr.port);
|
||||
let mut stream = TcpStream::connect(("::1", addr.port));
|
||||
stream.write([66]).unwrap();
|
||||
});
|
||||
|
||||
@ -621,12 +572,10 @@ mod test {
|
||||
#[test]
|
||||
fn smoke_test_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
});
|
||||
|
||||
@ -639,12 +588,10 @@ mod test {
|
||||
#[test]
|
||||
fn smoke_test_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
});
|
||||
|
||||
@ -657,12 +604,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_eof_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -675,12 +620,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_eof_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -693,12 +636,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_eof_twice_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -719,12 +660,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_eof_twice_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -745,12 +684,10 @@ mod test {
|
||||
#[test]
|
||||
fn write_close_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -773,12 +710,10 @@ mod test {
|
||||
#[test]
|
||||
fn write_close_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let _stream = TcpStream::connect(addr);
|
||||
// Close
|
||||
});
|
||||
|
||||
@ -801,14 +736,12 @@ mod test {
|
||||
#[test]
|
||||
fn multiple_connect_serial_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let max = 10u;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
for _ in range(0, max) {
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
});
|
||||
@ -823,14 +756,12 @@ mod test {
|
||||
#[test]
|
||||
fn multiple_connect_serial_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let max = 10u;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
for _ in range(0, max) {
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
stream.write([99]).unwrap();
|
||||
}
|
||||
});
|
||||
@ -845,10 +776,8 @@ mod test {
|
||||
#[test]
|
||||
fn multiple_connect_interleaved_greedy_schedule_ip4() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
static MAX: int = 10;
|
||||
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = acceptor;
|
||||
@ -867,13 +796,11 @@ mod test {
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
if i == MAX { return }
|
||||
|
||||
spawn(proc() {
|
||||
debug!("connecting");
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
// Connect again before writing
|
||||
connect(i + 1, addr);
|
||||
debug!("writing");
|
||||
@ -885,10 +812,8 @@ mod test {
|
||||
#[test]
|
||||
fn multiple_connect_interleaved_greedy_schedule_ip6() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
static MAX: int = 10;
|
||||
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = acceptor;
|
||||
@ -907,13 +832,11 @@ mod test {
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
if i == MAX { return }
|
||||
|
||||
spawn(proc() {
|
||||
debug!("connecting");
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
// Connect again before writing
|
||||
connect(i + 1, addr);
|
||||
debug!("writing");
|
||||
@ -926,9 +849,7 @@ mod test {
|
||||
fn multiple_connect_interleaved_lazy_schedule_ip4() {
|
||||
static MAX: int = 10;
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = acceptor;
|
||||
@ -947,13 +868,11 @@ mod test {
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
if i == MAX { return }
|
||||
|
||||
spawn(proc() {
|
||||
debug!("connecting");
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
// Connect again before writing
|
||||
connect(i + 1, addr);
|
||||
debug!("writing");
|
||||
@ -966,9 +885,7 @@ mod test {
|
||||
fn multiple_connect_interleaved_lazy_schedule_ip6() {
|
||||
static MAX: int = 10;
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut acceptor = acceptor;
|
||||
@ -987,13 +904,11 @@ mod test {
|
||||
connect(0, addr);
|
||||
|
||||
fn connect(i: int, addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
if i == MAX { return }
|
||||
|
||||
spawn(proc() {
|
||||
debug!("connecting");
|
||||
let mut stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut stream = TcpStream::connect(addr);
|
||||
// Connect again before writing
|
||||
connect(i + 1, addr);
|
||||
debug!("writing");
|
||||
@ -1003,9 +918,7 @@ mod test {
|
||||
}
|
||||
|
||||
pub fn socket_name(addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut listener = TcpListener::bind(ip_str.as_slice(), port).unwrap();
|
||||
let mut listener = TcpListener::bind(addr).unwrap();
|
||||
|
||||
// Make sure socket_name gives
|
||||
// us the socket we binded to.
|
||||
@ -1015,15 +928,13 @@ mod test {
|
||||
}
|
||||
|
||||
pub fn peer_name(addr: SocketAddr) {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let acceptor = TcpListener::bind(addr).listen();
|
||||
spawn(proc() {
|
||||
let mut acceptor = acceptor;
|
||||
acceptor.accept().unwrap();
|
||||
});
|
||||
|
||||
let stream = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let stream = TcpStream::connect(addr);
|
||||
|
||||
assert!(stream.is_ok());
|
||||
let mut stream = stream.unwrap();
|
||||
@ -1052,11 +963,9 @@ mod test {
|
||||
#[test]
|
||||
fn partial_read() {
|
||||
let addr = next_test_ip4();
|
||||
let port = addr.port;
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let ip_str = addr.ip.to_string();
|
||||
let mut srv = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let mut srv = TcpListener::bind(addr).listen().unwrap();
|
||||
tx.send(());
|
||||
let mut cl = srv.accept().unwrap();
|
||||
cl.write([10]).unwrap();
|
||||
@ -1066,8 +975,7 @@ mod test {
|
||||
});
|
||||
|
||||
rx.recv();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let mut c = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut c = TcpStream::connect(addr).unwrap();
|
||||
let mut b = [0, ..10];
|
||||
assert_eq!(c.read(b), Ok(1));
|
||||
c.write([1]).unwrap();
|
||||
@ -1077,11 +985,9 @@ mod test {
|
||||
#[test]
|
||||
fn double_bind() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let listener = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen();
|
||||
let listener = TcpListener::bind(addr).unwrap().listen();
|
||||
assert!(listener.is_ok());
|
||||
match TcpListener::bind(ip_str.as_slice(), port).listen() {
|
||||
match TcpListener::bind(addr).listen() {
|
||||
Ok(..) => panic!(),
|
||||
Err(e) => {
|
||||
assert!(e.kind == ConnectionRefused || e.kind == OtherIoError,
|
||||
@ -1093,20 +999,17 @@ mod test {
|
||||
#[test]
|
||||
fn fast_rebind() {
|
||||
let addr = next_test_ip4();
|
||||
let port = addr.port;
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(proc() {
|
||||
let ip_str = addr.ip.to_string();
|
||||
rx.recv();
|
||||
let _stream = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let _stream = TcpStream::connect(addr).unwrap();
|
||||
// Close
|
||||
rx.recv();
|
||||
});
|
||||
|
||||
{
|
||||
let ip_str = addr.ip.to_string();
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
tx.send(());
|
||||
{
|
||||
let _stream = acceptor.accept().unwrap();
|
||||
@ -1115,18 +1018,16 @@ mod test {
|
||||
}
|
||||
// Close listener
|
||||
}
|
||||
let _listener = TcpListener::bind(addr.ip.to_string().as_slice(), port);
|
||||
let _listener = TcpListener::bind(addr);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tcp_clone_smoke() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut s = TcpStream::connect(addr);
|
||||
let mut buf = [0, 0];
|
||||
assert_eq!(s.read(buf), Ok(1));
|
||||
assert_eq!(buf[0], 1);
|
||||
@ -1153,14 +1054,12 @@ mod test {
|
||||
#[test]
|
||||
fn tcp_clone_two_read() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
let (tx1, rx) = channel();
|
||||
let tx2 = tx1.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut s = TcpStream::connect(addr);
|
||||
s.write([1]).unwrap();
|
||||
rx.recv();
|
||||
s.write([2]).unwrap();
|
||||
@ -1188,12 +1087,10 @@ mod test {
|
||||
#[test]
|
||||
fn tcp_clone_two_write() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut acceptor = TcpListener::bind(ip_str.as_slice(), port).listen();
|
||||
let mut acceptor = TcpListener::bind(addr).listen();
|
||||
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port);
|
||||
let mut s = TcpStream::connect(addr);
|
||||
let mut buf = [0, 1];
|
||||
s.read(buf).unwrap();
|
||||
s.read(buf).unwrap();
|
||||
@ -1218,9 +1115,7 @@ mod test {
|
||||
use rt::rtio::RtioTcpStream;
|
||||
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let a = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen();
|
||||
let a = TcpListener::bind(addr).unwrap().listen();
|
||||
spawn(proc() {
|
||||
let mut a = a;
|
||||
let mut c = a.accept().unwrap();
|
||||
@ -1228,7 +1123,7 @@ mod test {
|
||||
c.write([1]).unwrap();
|
||||
});
|
||||
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
assert!(s.obj.close_write().is_ok());
|
||||
assert!(s.write([1]).is_err());
|
||||
assert_eq!(s.read_to_end(), Ok(vec!(1)));
|
||||
@ -1237,9 +1132,7 @@ mod test {
|
||||
#[test]
|
||||
fn accept_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut a = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen().unwrap();
|
||||
let mut a = TcpListener::bind(addr).unwrap().listen().unwrap();
|
||||
|
||||
a.set_timeout(Some(10));
|
||||
|
||||
@ -1258,8 +1151,7 @@ mod test {
|
||||
if !cfg!(target_os = "freebsd") {
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
tx.send(TcpStream::connect(addr.ip.to_string().as_slice(),
|
||||
port).unwrap());
|
||||
tx.send(TcpStream::connect(addr).unwrap());
|
||||
});
|
||||
let _l = rx.recv();
|
||||
for i in range(0i, 1001) {
|
||||
@ -1276,8 +1168,7 @@ mod test {
|
||||
// Unset the timeout and make sure that this always blocks.
|
||||
a.set_timeout(None);
|
||||
spawn(proc() {
|
||||
drop(TcpStream::connect(addr.ip.to_string().as_slice(),
|
||||
port).unwrap());
|
||||
drop(TcpStream::connect(addr).unwrap());
|
||||
});
|
||||
a.accept().unwrap();
|
||||
}
|
||||
@ -1285,9 +1176,7 @@ mod test {
|
||||
#[test]
|
||||
fn close_readwrite_smoke() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (_tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut a = a;
|
||||
@ -1296,7 +1185,7 @@ mod test {
|
||||
});
|
||||
|
||||
let mut b = [0];
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
let mut s2 = s.clone();
|
||||
|
||||
// closing should prevent reads/writes
|
||||
@ -1324,9 +1213,7 @@ mod test {
|
||||
#[test]
|
||||
fn close_read_wakes_up() {
|
||||
let addr = next_test_ip4();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (_tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut a = a;
|
||||
@ -1334,7 +1221,7 @@ mod test {
|
||||
let _ = rx.recv_opt();
|
||||
});
|
||||
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
let s2 = s.clone();
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
@ -1352,12 +1239,10 @@ mod test {
|
||||
#[test]
|
||||
fn readwrite_timeouts() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let mut a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
rx.recv();
|
||||
assert!(s.write([0]).is_ok());
|
||||
let _ = rx.recv_opt();
|
||||
@ -1387,12 +1272,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_timeouts() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let mut a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
rx.recv();
|
||||
let mut amt = 0;
|
||||
while amt < 100 * 128 * 1024 {
|
||||
@ -1418,12 +1301,10 @@ mod test {
|
||||
#[test]
|
||||
fn write_timeouts() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let mut a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
rx.recv();
|
||||
assert!(s.write([0]).is_ok());
|
||||
let _ = rx.recv_opt();
|
||||
@ -1448,12 +1329,10 @@ mod test {
|
||||
#[test]
|
||||
fn timeout_concurrent_read() {
|
||||
let addr = next_test_ip6();
|
||||
let ip_str = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let mut a = TcpListener::bind(ip_str.as_slice(), port).listen().unwrap();
|
||||
let mut a = TcpListener::bind(addr).listen().unwrap();
|
||||
let (tx, rx) = channel::<()>();
|
||||
spawn(proc() {
|
||||
let mut s = TcpStream::connect(ip_str.as_slice(), port).unwrap();
|
||||
let mut s = TcpStream::connect(addr).unwrap();
|
||||
rx.recv();
|
||||
assert_eq!(s.write([0]), Ok(()));
|
||||
let _ = rx.recv_opt();
|
||||
@ -1478,7 +1357,7 @@ mod test {
|
||||
#[test]
|
||||
fn clone_while_reading() {
|
||||
let addr = next_test_ip6();
|
||||
let listen = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
|
||||
let listen = TcpListener::bind(addr);
|
||||
let mut accept = listen.listen().unwrap();
|
||||
|
||||
// Enqueue a task to write to a socket
|
||||
@ -1486,8 +1365,7 @@ mod test {
|
||||
let (txdone, rxdone) = channel();
|
||||
let txdone2 = txdone.clone();
|
||||
spawn(proc() {
|
||||
let mut tcp = TcpStream::connect(addr.ip.to_string().as_slice(),
|
||||
addr.port).unwrap();
|
||||
let mut tcp = TcpStream::connect(addr).unwrap();
|
||||
rx.recv();
|
||||
tcp.write_u8(0).unwrap();
|
||||
txdone2.send(());
|
||||
@ -1519,15 +1397,15 @@ mod test {
|
||||
#[test]
|
||||
fn clone_accept_smoke() {
|
||||
let addr = next_test_ip4();
|
||||
let l = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
|
||||
let l = TcpListener::bind(addr);
|
||||
let mut a = l.listen().unwrap();
|
||||
let mut a2 = a.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let _ = TcpStream::connect(addr.ip.to_string().as_slice(), addr.port);
|
||||
let _ = TcpStream::connect(addr);
|
||||
});
|
||||
spawn(proc() {
|
||||
let _ = TcpStream::connect(addr.ip.to_string().as_slice(), addr.port);
|
||||
let _ = TcpStream::connect(addr);
|
||||
});
|
||||
|
||||
assert!(a.accept().is_ok());
|
||||
@ -1537,7 +1415,7 @@ mod test {
|
||||
#[test]
|
||||
fn clone_accept_concurrent() {
|
||||
let addr = next_test_ip4();
|
||||
let l = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
|
||||
let l = TcpListener::bind(addr);
|
||||
let a = l.listen().unwrap();
|
||||
let a2 = a.clone();
|
||||
|
||||
@ -1548,10 +1426,10 @@ mod test {
|
||||
spawn(proc() { let mut a = a2; tx2.send(a.accept()) });
|
||||
|
||||
spawn(proc() {
|
||||
let _ = TcpStream::connect(addr.ip.to_string().as_slice(), addr.port);
|
||||
let _ = TcpStream::connect(addr);
|
||||
});
|
||||
spawn(proc() {
|
||||
let _ = TcpStream::connect(addr.ip.to_string().as_slice(), addr.port);
|
||||
let _ = TcpStream::connect(addr);
|
||||
});
|
||||
|
||||
assert!(rx.recv().is_ok());
|
||||
@ -1561,7 +1439,7 @@ mod test {
|
||||
#[test]
|
||||
fn close_accept_smoke() {
|
||||
let addr = next_test_ip4();
|
||||
let l = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
|
||||
let l = TcpListener::bind(addr);
|
||||
let mut a = l.listen().unwrap();
|
||||
|
||||
a.close_accept().unwrap();
|
||||
@ -1571,7 +1449,7 @@ mod test {
|
||||
#[test]
|
||||
fn close_accept_concurrent() {
|
||||
let addr = next_test_ip4();
|
||||
let l = TcpListener::bind(addr.ip.to_string().as_slice(), addr.port);
|
||||
let l = TcpListener::bind(addr);
|
||||
let a = l.listen().unwrap();
|
||||
let mut a2 = a.clone();
|
||||
|
||||
|
@ -16,13 +16,13 @@
|
||||
//! datagram protocol.
|
||||
|
||||
use clone::Clone;
|
||||
use io::net::ip::{SocketAddr, IpAddr};
|
||||
use io::net::ip::{SocketAddr, IpAddr, ToSocketAddr};
|
||||
use io::{Reader, Writer, IoResult, IoError};
|
||||
use kinds::Send;
|
||||
use boxed::Box;
|
||||
use option::Option;
|
||||
use result::{Ok, Err};
|
||||
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
|
||||
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory};
|
||||
use rt::rtio;
|
||||
|
||||
/// A User Datagram Protocol socket.
|
||||
@ -64,19 +64,17 @@ pub struct UdpSocket {
|
||||
}
|
||||
|
||||
impl UdpSocket {
|
||||
/// Creates a UDP socket from the given socket address.
|
||||
pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
|
||||
let SocketAddr { ip, port } = addr;
|
||||
LocalIo::maybe_raise(|io| {
|
||||
let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
|
||||
io.udp_bind(addr).map(|s| UdpSocket { obj: s })
|
||||
}).map_err(IoError::from_rtio_error)
|
||||
/// Creates a UDP socket from the given address.
|
||||
///
|
||||
/// Address type can be any implementor of `ToSocketAddr` trait. See its
|
||||
/// documentation for concrete examples.
|
||||
pub fn bind<A: ToSocketAddr>(addr: A) -> IoResult<UdpSocket> {
|
||||
super::with_addresses_io(addr, |io, addr| io.udp_bind(addr).map(|s| UdpSocket { obj: s }))
|
||||
}
|
||||
|
||||
/// Receives data from the socket. On success, returns the number of bytes
|
||||
/// read and the address from whence the data came.
|
||||
pub fn recv_from(&mut self, buf: &mut [u8])
|
||||
-> IoResult<(uint, SocketAddr)> {
|
||||
pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
|
||||
match self.obj.recv_from(buf) {
|
||||
Ok((amt, rtio::SocketAddr { ip, port })) => {
|
||||
Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port }))
|
||||
@ -87,11 +85,14 @@ impl UdpSocket {
|
||||
|
||||
/// Sends data on the socket to the given address. Returns nothing on
|
||||
/// success.
|
||||
pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
|
||||
self.obj.send_to(buf, rtio::SocketAddr {
|
||||
ip: super::to_rtio(dst.ip),
|
||||
port: dst.port,
|
||||
}).map_err(IoError::from_rtio_error)
|
||||
///
|
||||
/// Address type can be any implementor of `ToSocketAddr` trait. See its
|
||||
/// documentation for concrete examples.
|
||||
pub fn send_to<A: ToSocketAddr>(&mut self, buf: &[u8], addr: A) -> IoResult<()> {
|
||||
super::with_addresses(addr, |addr| self.obj.send_to(buf, rtio::SocketAddr {
|
||||
ip: super::to_rtio(addr.ip),
|
||||
port: addr.port,
|
||||
}).map_err(IoError::from_rtio_error))
|
||||
}
|
||||
|
||||
/// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
|
||||
|
@ -24,7 +24,7 @@ fn main() {
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let mut l = TcpListener::bind("127.0.0.1", 0).unwrap();
|
||||
let mut l = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = l.socket_name().unwrap();
|
||||
let mut a = l.listen().unwrap();
|
||||
let cnt = Arc::new(atomic::AtomicUint::new(0));
|
||||
@ -56,8 +56,7 @@ fn test() {
|
||||
let cli_tx = cli_tx.clone();
|
||||
spawn(proc() {
|
||||
for _ in range(0, M) {
|
||||
let _s = TcpStream::connect(addr.ip.to_string().as_slice(),
|
||||
addr.port).unwrap();
|
||||
let _s = TcpStream::connect(addr).unwrap();
|
||||
}
|
||||
cli_tx.send(());
|
||||
});
|
||||
|
@ -31,13 +31,11 @@ use std::time::Duration;
|
||||
#[cfg_attr(target_os = "freebsd", ignore)]
|
||||
fn eventual_timeout() {
|
||||
let addr = next_test_ip4();
|
||||
let host = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
|
||||
let (tx1, rx1) = channel();
|
||||
let (_tx2, rx2) = channel::<()>();
|
||||
std::task::spawn(proc() {
|
||||
let _l = TcpListener::bind(host.as_slice(), port).unwrap().listen();
|
||||
let _l = TcpListener::bind(addr).unwrap().listen();
|
||||
tx1.send(());
|
||||
let _ = rx2.recv_opt();
|
||||
});
|
||||
@ -56,9 +54,7 @@ fn eventual_timeout() {
|
||||
|
||||
fn timeout_success() {
|
||||
let addr = next_test_ip4();
|
||||
let host = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
let _l = TcpListener::bind(host.as_slice(), port).unwrap().listen();
|
||||
let _l = TcpListener::bind(addr).unwrap().listen();
|
||||
|
||||
assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(1000)).is_ok());
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ fn main() {
|
||||
|
||||
let (tx, rx) = channel();
|
||||
spawn(proc() {
|
||||
let mut listener = TcpListener::bind("127.0.0.1", 0).unwrap();
|
||||
let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
tx.send(listener.socket_name().unwrap());
|
||||
let mut acceptor = listener.listen();
|
||||
loop {
|
||||
@ -54,9 +54,7 @@ fn main() {
|
||||
for _ in range(0u, 1000) {
|
||||
let tx = tx.clone();
|
||||
TaskBuilder::new().stack_size(64 * 1024).spawn(proc() {
|
||||
let host = addr.ip.to_string();
|
||||
let port = addr.port;
|
||||
match TcpStream::connect(host.as_slice(), port) {
|
||||
match TcpStream::connect(addr) {
|
||||
Ok(stream) => {
|
||||
let mut stream = stream;
|
||||
stream.write([1]);
|
||||
|
Loading…
Reference in New Issue
Block a user