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:
bors 2014-11-05 18:01:53 +00:00
commit 5c1fd5f8b7
9 changed files with 411 additions and 264 deletions

View file

@ -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;

View file

@ -91,7 +91,7 @@
# // 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 @@
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();

View file

@ -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 @@ fn from_str(s: &str) -> Option<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 @@ fn ipv6_addr_to_string() {
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));
}
}

View file

@ -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)
}

View file

@ -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 @@
/// # #![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 @@ fn new(s: Box<RtioTcpStream + Send>) -> 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 @@ pub fn connect(host: &str, port: u16) -> IoResult<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 @@ pub fn set_keepalive(&mut self, delay_in_seconds: Option<uint>) -> IoResult<()>
/// 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 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
/// 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 @@ fn bind_error() {
#[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 @@ fn connect_error() {
#[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 @@ fn listen_ip4_localhost() {
#[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 @@ fn connect_localhost() {
#[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 @@ fn connect_ip4_loopback() {
#[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 @@ fn connect_ip6_loopback() {
#[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 @@ fn smoke_test_ip4() {
#[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 @@ fn smoke_test_ip6() {
#[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 @@ fn read_eof_ip4() {
#[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 @@ fn read_eof_ip6() {
#[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 @@ fn read_eof_twice_ip4() {
#[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 @@ fn read_eof_twice_ip6() {
#[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 @@ fn write_close_ip4() {
#[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 @@ fn write_close_ip6() {
#[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 @@ fn multiple_connect_serial_ip4() {
#[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 @@ fn multiple_connect_serial_ip6() {
#[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 @@ fn multiple_connect_interleaved_greedy_schedule_ip4() {
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 @@ fn connect(i: int, addr: SocketAddr) {
#[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 @@ fn multiple_connect_interleaved_greedy_schedule_ip6() {
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 @@ fn connect(i: int, addr: SocketAddr) {
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 @@ fn multiple_connect_interleaved_lazy_schedule_ip4() {
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 @@ fn connect(i: int, addr: SocketAddr) {
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 @@ fn multiple_connect_interleaved_lazy_schedule_ip6() {
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 @@ fn connect(i: int, addr: SocketAddr) {
}
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 @@ pub fn socket_name(addr: SocketAddr) {
}
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 @@ fn socket_and_peer_name_ip6() {
#[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 @@ fn partial_read() {
});
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 @@ fn partial_read() {
#[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 @@ fn double_bind() {
#[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 @@ fn fast_rebind() {
}
// 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 @@ fn tcp_clone_smoke() {
#[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 @@ fn tcp_clone_two_read() {
#[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 @@ fn shutdown_smoke() {
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 @@ fn shutdown_smoke() {
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 @@ fn shutdown_smoke() {
#[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 @@ fn accept_timeout() {
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 @@ fn accept_timeout() {
// 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 @@ fn accept_timeout() {
#[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 @@ fn close_readwrite_smoke() {
});
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 @@ fn close_readwrite_smoke() {
#[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 @@ fn close_read_wakes_up() {
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 @@ fn close_read_wakes_up() {
#[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 @@ fn readwrite_timeouts() {
#[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 @@ fn read_timeouts() {
#[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 @@ fn write_timeouts() {
#[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 @@ fn timeout_concurrent_read() {
#[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 @@ fn clone_while_reading() {
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 @@ fn clone_while_reading() {
#[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 @@ fn clone_accept_smoke() {
#[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 @@ fn clone_accept_concurrent() {
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 @@ fn clone_accept_concurrent() {
#[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 @@ fn close_accept_smoke() {
#[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();

View file

@ -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 @@ pub fn recv_from(&mut self, buf: &mut [u8])
/// 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`

View file

@ -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(());
});

View file

@ -31,13 +31,11 @@
#[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());
}

View file

@ -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]);