diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-02-05 16:50:11 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-02-11 15:23:34 -0800 |
| commit | 395709ca6d39ba1e095e404e1d2a169d918b7f0c (patch) | |
| tree | e6a3d38abb028967c3139ee234d1c69935806800 /src/libstd/sys/windows | |
| parent | a954663db66fc8efb1889beaf7bd1771ecbb9b21 (diff) | |
| download | rust-395709ca6d39ba1e095e404e1d2a169d918b7f0c.tar.gz rust-395709ca6d39ba1e095e404e1d2a169d918b7f0c.zip | |
std: Add a `net` module for TCP/UDP
This commit is an implementation of [RFC 807][rfc] which adds a `std::net` module for basic neworking based on top of `std::io`. This module serves as a replacement for the `std::old_io::net` module and networking primitives in `old_io`. [rfc]: fillmein The major focus of this redesign is to cut back on the level of abstraction to the point that each of the networking types is just a bare socket. To this end functionality such as timeouts and cloning has been removed (although cloning can be done through `duplicate`, it may just yield an error). With this `net` module comes a new implementation of `SocketAddr` and `IpAddr`. This work is entirely based on #20785 and the only changes were to alter the in-memory representation to match the `libc`-expected variants and to move from public fields to accessors.
Diffstat (limited to 'src/libstd/sys/windows')
| -rw-r--r-- | src/libstd/sys/windows/ext.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/windows/mod.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/windows/net.rs | 121 |
3 files changed, 133 insertions, 0 deletions
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index dc874c2c791..ac1006e653f 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -21,6 +21,7 @@ pub use sys_common::wtf8::{Wtf8Buf, EncodeWide}; use ffi::{OsStr, OsString}; use fs::{self, OpenOptions}; use libc; +use net; use sys::os_str::Buf; use sys_common::{AsInner, FromInner, AsInnerMut}; @@ -103,6 +104,16 @@ impl AsRawSocket for old_io::net::udp::UdpSocket { } } +impl AsRawSocket for net::TcpStream { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } +} +impl AsRawSocket for net::TcpListener { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } +} +impl AsRawSocket for net::UdpSocket { + fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } +} + // Windows-specific extensions to `OsString`. pub trait OsStringExt { /// Create an `OsString` from a potentially ill-formed UTF-16 slice of 16-bit code units. diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 140bdb14501..0fa9aaf4323 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -43,6 +43,7 @@ pub mod fs2; pub mod handle; pub mod helper_signal; pub mod mutex; +pub mod net; pub mod os; pub mod os_str; pub mod pipe; diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs new file mode 100644 index 00000000000..4df72f6d4ab --- /dev/null +++ b/src/libstd/sys/windows/net.rs @@ -0,0 +1,121 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use io; +use libc::consts::os::extra::INVALID_SOCKET; +use libc::{self, c_int, c_void}; +use mem; +use net::{SocketAddr, IpAddr}; +use num::{SignedInt, Int}; +use rt; +use sync::{Once, ONCE_INIT}; +use sys::c; +use sys_common::AsInner; + +pub type wrlen_t = i32; + +pub struct Socket(libc::SOCKET); + +pub fn init() { + static START: Once = ONCE_INIT; + + START.call_once(|| unsafe { + let mut data: c::WSADATA = mem::zeroed(); + let ret = c::WSAStartup(0x202, // version 2.2 + &mut data); + assert_eq!(ret, 0); + + rt::at_exit(|| { c::WSACleanup(); }) + }); +} + +fn last_error() -> io::Error { + io::Error::from_os_error(unsafe { c::WSAGetLastError() }) +} + +pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> { + let one: T = Int::one(); + if t == -one { + Err(last_error()) + } else { + Ok(t) + } +} + +pub fn cvt_gai(err: c_int) -> io::Result<()> { + if err == 0 { return Ok(()) } + cvt(err).map(|_| ()) +} + +pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T { + cvt(f()) +} + +impl Socket { + pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { + let fam = match addr.ip { + IpAddr::V4(..) => libc::AF_INET, + IpAddr::V6(..) => libc::AF_INET6, + }; + match unsafe { libc::socket(fam, ty, 0) } { + INVALID_SOCKET => Err(last_error()), + n => Ok(Socket(n)), + } + } + + pub fn accept(&self, storage: *mut libc::sockaddr, + len: *mut libc::socklen_t) -> io::Result<Socket> { + match unsafe { libc::accept(self.0, storage, len) } { + INVALID_SOCKET => Err(last_error()), + n => Ok(Socket(n)), + } + } + + pub fn duplicate(&self) -> io::Result<Socket> { + unsafe { + let mut info: c::WSAPROTOCOL_INFO = mem::zeroed(); + try!(cvt(c::WSADuplicateSocketW(self.0, + c::GetCurrentProcessId(), + &mut info))); + match c::WSASocketW(info.iAddressFamily, + info.iSocketType, + info.iProtocol, + &mut info, 0, 0) { + INVALID_SOCKET => Err(last_error()), + n => Ok(Socket(n)), + } + } + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { + // On unix when a socket is shut down all further reads return 0, so we + // do the same on windows to map a shut down socket to returning EOF. + unsafe { + match libc::recv(self.0, buf.as_mut_ptr() as *mut c_void, + buf.len() as i32, 0) { + -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), + -1 => Err(last_error()), + n => Ok(n as usize) + } + } + } +} + +impl Drop for Socket { + fn drop(&mut self) { + unsafe { let _ = libc::closesocket(self.0); } + } +} + +impl AsInner<libc::SOCKET> for Socket { + fn as_inner(&self) -> &libc::SOCKET { &self.0 } +} |
