net2-0.2.39/.cargo_vcs_info.json0000644000000001360000000000100117770ustar { "git": { "sha1": "505ac98326824dda2379fa35069e3b7ead3c661d" }, "path_in_vcs": "" }net2-0.2.39/Cargo.toml0000644000000024370000000000100100030ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "net2" version = "0.2.39" authors = ["Alex Crichton "] include = [ "Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "README.md", "src/**/*.rs", ] description = """ Extensions to the standard library's networking types as proposed in RFC 1158. """ homepage = "https://github.com/deprecrated/net2-rs" documentation = "https://docs.rs/net2/~0.2" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/deprecrated/net2-rs" [dependencies.cfg-if] version = "0.1" [features] default = ["duration"] duration = [] nightly = [] [target."cfg(any(unix, target_os=\"wasi\"))".dependencies.libc] version = "0.2.139" [target."cfg(windows)".dependencies.winapi] version = "0.3" features = [ "handleapi", "winsock2", "ws2def", "ws2ipdef", "ws2tcpip", ] net2-0.2.39/Cargo.toml.orig000064400000000000000000000014371046102023000134630ustar 00000000000000[package] name = "net2" version = "0.2.39" authors = ["Alex Crichton "] license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/deprecrated/net2-rs" homepage = "https://github.com/deprecrated/net2-rs" documentation = "https://docs.rs/net2/~0.2" description = """ Extensions to the standard library's networking types as proposed in RFC 1158. """ include = [ "Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "README.md", "src/**/*.rs" ] [target."cfg(windows)".dependencies] winapi = { version = "0.3", features = ["handleapi", "winsock2", "ws2def", "ws2ipdef", "ws2tcpip"] } [target.'cfg(any(unix, target_os="wasi"))'.dependencies] libc = "0.2.139" [dependencies] cfg-if = "0.1" [features] nightly = [] duration = [] default = ["duration"] net2-0.2.39/LICENSE-APACHE000064400000000000000000000251371046102023000125230ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. net2-0.2.39/LICENSE-MIT000064400000000000000000000020571046102023000122270ustar 00000000000000Copyright (c) 2014 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. net2-0.2.39/README.md000064400000000000000000000020751046102023000120520ustar 00000000000000# net2 Extensions to the standard library's networking types, proposed in [RFC 1158][rfc]. [rfc]: https://github.com/alexcrichton/rfcs/blob/net2.1/text/0000-io-net-2.1.md [![Build Status](https://github.com/deprecrated/net2-rs/workflows/CI/badge.svg)](https://github.com/deprecrated/net2-rs/actions?query=workflow%3ACI+branch%3Amaster) [![Documentation](https://docs.rs/net2/badge.svg?version=0.2)](https://docs.rs/net2/~0.2) # net2 is Deprecated Prospective and existing consumers are encouraged to consider [socket2](https://crates.io/crates/socket2) instead. # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. net2-0.2.39/src/ext.rs000064400000000000000000001503611046102023000125320ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style, dead_code)] use std::io; use std::mem; use std::net::{TcpStream, TcpListener, UdpSocket, Ipv4Addr, Ipv6Addr}; use std::net::ToSocketAddrs; use {TcpBuilder, UdpBuilder, FromInner}; use sys; use sys::c; use socket; cfg_if! { if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "haiku", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "solaris", target_os = "illumos", target_env = "uclibc"))] { use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; } else { // ... } } use std::time::Duration; #[cfg(any(unix, target_os = "wasi"))] use libc::*; #[cfg(any(unix))] use std::os::unix::prelude::*; #[cfg(target_os = "wasi")] use std::os::wasi::prelude::*; #[cfg(unix)] pub type Socket = c_int; #[cfg(target_os = "wasi")] pub type Socket = std::os::wasi::io::RawFd; #[cfg(windows)] pub type Socket = SOCKET; #[cfg(windows)] use std::os::windows::prelude::*; #[cfg(any(windows, target_os = "wasi"))] use sys::c::*; #[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004; #[cfg(windows)] #[repr(C)] struct tcp_keepalive { onoff: c_ulong, keepalivetime: c_ulong, keepaliveinterval: c_ulong, } #[cfg(any(unix, target_os = "wasi"))] fn v(opt: c_int) -> c_int { opt } #[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int } #[cfg(target_os = "wasi")] pub fn set_opt(_sock: Socket, _opt: c_int, _val: c_int, _payload: T) -> io::Result<()> { Ok(()) } #[cfg(not(target_os = "wasi"))] pub fn set_opt(sock: Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { unsafe { let payload = &payload as *const T as *const c_void; try!(::cvt(setsockopt(sock, opt, val, payload as *const _, mem::size_of::() as socklen_t))); } Ok(()) } #[cfg(target_os = "wasi")] pub fn get_opt(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result { unimplemented!() } #[cfg(not(target_os = "wasi"))] pub fn get_opt(sock: Socket, opt: c_int, val: c_int) -> io::Result { unsafe { let mut slot: T = mem::zeroed(); let mut len = mem::size_of::() as socklen_t; try!(::cvt(getsockopt(sock, opt, val, &mut slot as *mut _ as *mut _, &mut len))); assert_eq!(len as usize, mem::size_of::()); Ok(slot) } } /// Extension methods for the standard [`TcpStream` type][link] in `std::net`. /// /// [link]: https://doc.rust-lang.org/std/net/struct.TcpStream.html pub trait TcpStreamExt { /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that /// segments are always sent as soon as possible, even if there is only a /// small amount of data. When not set, data is buffered until there is a /// sufficient amount to send out, thereby avoiding the frequent sending of /// small packets. fn set_nodelay(&self, nodelay: bool) -> io::Result<()>; /// Gets the value of the `TCP_NODELAY` option on this socket. /// /// For more information about this option, see [`set_nodelay`][link]. /// /// [link]: #tymethod.set_nodelay fn nodelay(&self) -> io::Result; /// Sets the value of the `SO_RCVBUF` option on this socket. /// /// Changes the size of the operating system's receive buffer associated with the socket. fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>; /// Gets the value of the `SO_RCVBUF` option on this socket. /// /// For more information about this option, see [`set_recv_buffer_size`][link]. /// /// [link]: #tymethod.set_recv_buffer_size fn recv_buffer_size(&self) -> io::Result; /// Sets the value of the `SO_SNDBUF` option on this socket. /// /// Changes the size of the operating system's send buffer associated with the socket. fn set_send_buffer_size(&self, size: usize) -> io::Result<()>; /// Gets the value of the `SO_SNDBUF` option on this socket. /// /// For more information about this option, see [`set_send_buffer`][link]. /// /// [link]: #tymethod.set_send_buffer fn send_buffer_size(&self) -> io::Result; /// Sets whether keepalive messages are enabled to be sent on this socket. /// /// On Unix, this option will set the `SO_KEEPALIVE` as well as the /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform). /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option. /// /// If `None` is specified then keepalive messages are disabled, otherwise /// the number of milliseconds specified will be the time to remain idle /// before sending a TCP keepalive probe. /// /// Some platforms specify this value in seconds, so sub-second millisecond /// specifications may be omitted. fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()>; /// Returns whether keepalive messages are enabled on this socket, and if so /// the amount of milliseconds between them. /// /// For more information about this option, see [`set_keepalive_ms`][link]. /// /// [link]: #tymethod.set_keepalive_ms fn keepalive_ms(&self) -> io::Result>; /// Sets whether keepalive messages are enabled to be sent on this socket. /// /// On Unix, this option will set the `SO_KEEPALIVE` as well as the /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform). /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option. /// /// If `None` is specified then keepalive messages are disabled, otherwise /// the duration specified will be the time to remain idle before sending a /// TCP keepalive probe. /// /// Some platforms specify this value in seconds, so sub-second /// specifications may be omitted. fn set_keepalive(&self, keepalive: Option) -> io::Result<()>; /// Returns whether keepalive messages are enabled on this socket, and if so /// the duration of time between them. /// /// For more information about this option, see [`set_keepalive`][link]. /// /// [link]: #tymethod.set_keepalive fn keepalive(&self) -> io::Result>; /// Sets the `SO_RCVTIMEO` option for this socket. /// /// This option specifies the timeout, in milliseconds, of how long calls to /// this socket's `read` function will wait before returning a timeout. A /// value of `None` means that no read timeout should be specified and /// otherwise `Some` indicates the number of milliseconds for the timeout. fn set_read_timeout_ms(&self, val: Option) -> io::Result<()>; /// Sets the `SO_RCVTIMEO` option for this socket. /// /// This option specifies the timeout of how long calls to this socket's /// `read` function will wait before returning a timeout. A value of `None` /// means that no read timeout should be specified and otherwise `Some` /// indicates the number of duration of the timeout. fn set_read_timeout(&self, val: Option) -> io::Result<()>; /// Gets the value of the `SO_RCVTIMEO` option for this socket. /// /// For more information about this option, see [`set_read_timeout_ms`][link]. /// /// [link]: #tymethod.set_read_timeout_ms fn read_timeout_ms(&self) -> io::Result>; /// Gets the value of the `SO_RCVTIMEO` option for this socket. /// /// For more information about this option, see [`set_read_timeout`][link]. /// /// [link]: #tymethod.set_read_timeout fn read_timeout(&self) -> io::Result>; /// Sets the `SO_SNDTIMEO` option for this socket. /// /// This option specifies the timeout, in milliseconds, of how long calls to /// this socket's `write` function will wait before returning a timeout. A /// value of `None` means that no read timeout should be specified and /// otherwise `Some` indicates the number of milliseconds for the timeout. fn set_write_timeout_ms(&self, val: Option) -> io::Result<()>; /// Sets the `SO_SNDTIMEO` option for this socket. /// /// This option specifies the timeout of how long calls to this socket's /// `write` function will wait before returning a timeout. A value of `None` /// means that no read timeout should be specified and otherwise `Some` /// indicates the duration of the timeout. fn set_write_timeout(&self, val: Option) -> io::Result<()>; /// Gets the value of the `SO_SNDTIMEO` option for this socket. /// /// For more information about this option, see [`set_write_timeout_ms`][link]. /// /// [link]: #tymethod.set_write_timeout_ms fn write_timeout_ms(&self) -> io::Result>; /// Gets the value of the `SO_SNDTIMEO` option for this socket. /// /// For more information about this option, see [`set_write_timeout`][link]. /// /// [link]: #tymethod.set_write_timeout fn write_timeout(&self) -> io::Result>; /// Sets the value for the `IP_TTL` option on this socket. /// /// This value sets the time-to-live field that is used in every packet sent /// from this socket. fn set_ttl(&self, ttl: u32) -> io::Result<()>; /// Gets the value of the `IP_TTL` option for this socket. /// /// For more information about this option, see [`set_ttl`][link]. /// /// [link]: #tymethod.set_ttl fn ttl(&self) -> io::Result; /// Sets the value for the `IPV6_V6ONLY` option on this socket. /// /// If this is set to `true` then the socket is restricted to sending and /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications /// can bind the same port at the same time. /// /// If this is set to `false` then the socket can be used to send and /// receive packets from an IPv4-mapped IPv6 address. fn set_only_v6(&self, only_v6: bool) -> io::Result<()>; /// Gets the value of the `IPV6_V6ONLY` option for this socket. /// /// For more information about this option, see [`set_only_v6`][link]. /// /// [link]: #tymethod.set_only_v6 fn only_v6(&self) -> io::Result; /// Executes a `connect` operation on this socket, establishing a connection /// to the host specified by `addr`. /// /// Note that this normally does not need to be called on a `TcpStream`, /// it's typically automatically done as part of a normal /// `TcpStream::connect` function call or `TcpBuilder::connect` method call. /// /// This should only be necessary if an unconnected socket was extracted /// from a `TcpBuilder` and then needs to be connected. fn connect(&self, addr: T) -> io::Result<()>; /// Get the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing /// the field in the process. This can be useful for checking errors between /// calls. fn take_error(&self) -> io::Result>; /// Moves this TCP stream into or out of nonblocking mode. /// /// On Unix this corresponds to calling fcntl, and on Windows this /// corresponds to calling ioctlsocket. fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>; /// Sets the linger duration of this socket by setting the SO_LINGER option fn set_linger(&self, dur: Option) -> io::Result<()>; /// reads the linger duration for this socket by getting the SO_LINGER option fn linger(&self) -> io::Result>; } /// Extension methods for the standard [`TcpListener` type][link] in `std::net`. /// /// [link]: https://doc.rust-lang.org/std/net/struct.TcpListener.html pub trait TcpListenerExt { /// Sets the value for the `IP_TTL` option on this socket. /// /// This is the same as [`TcpStreamExt::set_ttl`][other]. /// /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl fn set_ttl(&self, ttl: u32) -> io::Result<()>; /// Gets the value of the `IP_TTL` option for this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_ttl`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl fn ttl(&self) -> io::Result; /// Sets the value for the `IPV6_V6ONLY` option on this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_only_v6`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6 fn set_only_v6(&self, only_v6: bool) -> io::Result<()>; /// Gets the value of the `IPV6_V6ONLY` option for this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_only_v6`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6 fn only_v6(&self) -> io::Result; /// Get the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing /// the field in the process. This can be useful for checking errors between /// calls. fn take_error(&self) -> io::Result>; /// Moves this TCP listener into or out of nonblocking mode. /// /// For more information about this option, see /// [`TcpStreamExt::set_nonblocking`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>; /// Sets the linger duration of this socket by setting the SO_LINGER option fn set_linger(&self, dur: Option) -> io::Result<()>; /// reads the linger duration for this socket by getting the SO_LINGER option fn linger(&self) -> io::Result>; } /// Extension methods for the standard [`UdpSocket` type][link] in `std::net`. /// /// [link]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html pub trait UdpSocketExt { /// Sets the value of the `SO_RCVBUF` option on this socket. /// /// Changes the size of the operating system's receive buffer associated with the socket. fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>; /// Gets the value of the `SO_RCVBUF` option on this socket. /// /// For more information about this option, see [`set_recv_buffer_size`][link]. /// /// [link]: #tymethod.set_recv_buffer_size fn recv_buffer_size(&self) -> io::Result; /// Sets the value of the `SO_SNDBUF` option on this socket. /// /// Changes the size of the operating system's send buffer associated with the socket. fn set_send_buffer_size(&self, size: usize) -> io::Result<()>; /// Gets the value of the `SO_SNDBUF` option on this socket. /// /// For more information about this option, see [`set_send_buffer`][link]. /// /// [link]: #tymethod.set_send_buffer fn send_buffer_size(&self) -> io::Result; /// Sets the value of the `SO_BROADCAST` option for this socket. /// /// When enabled, this socket is allowed to send packets to a broadcast /// address. fn set_broadcast(&self, broadcast: bool) -> io::Result<()>; /// Gets the value of the `SO_BROADCAST` option for this socket. /// /// For more information about this option, see /// [`set_broadcast`][link]. /// /// [link]: #tymethod.set_broadcast fn broadcast(&self) -> io::Result; /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// If enabled, multicast packets will be looped back to the local socket. /// Note that this may not have any affect on IPv6 sockets. fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>; /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// For more information about this option, see /// [`set_multicast_loop_v4`][link]. /// /// [link]: #tymethod.set_multicast_loop_v4 fn multicast_loop_v4(&self) -> io::Result; /// Sets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// Indicates the time-to-live value of outgoing multicast packets for /// this socket. The default value is 1 which means that multicast packets /// don't leave the local network unless explicitly requested. /// /// Note that this may not have any affect on IPv6 sockets. fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>; /// Gets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// For more information about this option, see /// [`set_multicast_ttl_v4`][link]. /// /// [link]: #tymethod.set_multicast_ttl_v4 fn multicast_ttl_v4(&self) -> io::Result; /// Sets the value of the `IPV6_MULTICAST_HOPS` option for this socket fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>; /// Gets the value of the `IPV6_MULTICAST_HOPS` option for this socket fn multicast_hops_v6(&self) -> io::Result; /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// Controls whether this socket sees the multicast packets it sends itself. /// Note that this may not have any affect on IPv4 sockets. fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>; /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// For more information about this option, see /// [`set_multicast_loop_v6`][link]. /// /// [link]: #tymethod.set_multicast_loop_v6 fn multicast_loop_v6(&self) -> io::Result; /// Sets the value of the `IP_MULTICAST_IF` option for this socket. /// /// Specifies the interface to use for routing multicast packets. fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>; /// Gets the value of the `IP_MULTICAST_IF` option for this socket. /// /// Returns the interface to use for routing multicast packets. fn multicast_if_v4(&self) -> io::Result; /// Sets the value of the `IPV6_MULTICAST_IF` option for this socket. /// /// Specifies the interface to use for routing multicast packets. fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()>; /// Gets the value of the `IPV6_MULTICAST_IF` option for this socket. /// /// Returns the interface to use for routing multicast packets. fn multicast_if_v6(&self) -> io::Result; /// Sets the value for the `IP_TTL` option on this socket. /// /// This is the same as [`TcpStreamExt::set_ttl`][other]. /// /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl fn set_ttl(&self, ttl: u32) -> io::Result<()>; /// Gets the value of the `IP_TTL` option for this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_ttl`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl fn ttl(&self) -> io::Result; /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. /// /// Specifies the hop limit for ipv6 unicast packets fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()>; /// Gets the value of the `IPV6_UNICAST_HOPS` option for this socket. /// /// Specifies the hop limit for ipv6 unicast packets fn unicast_hops_v6(&self) -> io::Result; /// Sets the value for the `IPV6_V6ONLY` option on this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_only_v6`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6 fn set_only_v6(&self, only_v6: bool) -> io::Result<()>; /// Gets the value of the `IPV6_V6ONLY` option for this socket. /// /// For more information about this option, see /// [`TcpStreamExt::set_only_v6`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6 fn only_v6(&self) -> io::Result; /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. /// /// This function specifies a new multicast group for this socket to join. /// The address must be a valid multicast address, and `interface` is the /// address of the local interface with which the system should join the /// multicast group. If it's equal to `INADDR_ANY` then an appropriate /// interface is chosen by the system. fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>; /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type. /// /// This function specifies a new multicast group for this socket to join. /// The address must be a valid multicast address, and `interface` is the /// index of the interface to join/leave (or 0 to indicate any interface). fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>; /// Executes an operation of the `IP_DROP_MEMBERSHIP` type. /// /// For more information about this option, see /// [`join_multicast_v4`][link]. /// /// [link]: #tymethod.join_multicast_v4 fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>; /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type. /// /// For more information about this option, see /// [`join_multicast_v6`][link]. /// /// [link]: #tymethod.join_multicast_v6 fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>; /// Sets the `SO_RCVTIMEO` option for this socket. /// /// This option specifies the timeout, in milliseconds, of how long calls to /// this socket's `read` function will wait before returning a timeout. A /// value of `None` means that no read timeout should be specified and /// otherwise `Some` indicates the number of milliseconds for the timeout. fn set_read_timeout_ms(&self, val: Option) -> io::Result<()>; /// Sets the `SO_RCVTIMEO` option for this socket. /// /// This option specifies the timeout of how long calls to this socket's /// `read` function will wait before returning a timeout. A value of `None` /// means that no read timeout should be specified and otherwise `Some` /// indicates the number of duration of the timeout. fn set_read_timeout(&self, val: Option) -> io::Result<()>; /// Gets the value of the `SO_RCVTIMEO` option for this socket. /// /// For more information about this option, see [`set_read_timeout_ms`][link]. /// /// [link]: #tymethod.set_read_timeout_ms fn read_timeout_ms(&self) -> io::Result>; /// Gets the value of the `SO_RCVTIMEO` option for this socket. /// /// For more information about this option, see [`set_read_timeout`][link]. /// /// [link]: #tymethod.set_read_timeout fn read_timeout(&self) -> io::Result>; /// Sets the `SO_SNDTIMEO` option for this socket. /// /// This option specifies the timeout, in milliseconds, of how long calls to /// this socket's `write` function will wait before returning a timeout. A /// value of `None` means that no read timeout should be specified and /// otherwise `Some` indicates the number of milliseconds for the timeout. fn set_write_timeout_ms(&self, val: Option) -> io::Result<()>; /// Sets the `SO_SNDTIMEO` option for this socket. /// /// This option specifies the timeout of how long calls to this socket's /// `write` function will wait before returning a timeout. A value of `None` /// means that no read timeout should be specified and otherwise `Some` /// indicates the duration of the timeout. fn set_write_timeout(&self, val: Option) -> io::Result<()>; /// Gets the value of the `SO_SNDTIMEO` option for this socket. /// /// For more information about this option, see [`set_write_timeout_ms`][link]. /// /// [link]: #tymethod.set_write_timeout_ms fn write_timeout_ms(&self) -> io::Result>; /// Gets the value of the `SO_SNDTIMEO` option for this socket. /// /// For more information about this option, see [`set_write_timeout`][link]. /// /// [link]: #tymethod.set_write_timeout fn write_timeout(&self) -> io::Result>; /// Get the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing /// the field in the process. This can be useful for checking errors between /// calls. fn take_error(&self) -> io::Result>; /// Connects this UDP socket to a remote address, allowing the `send` and /// `recv` syscalls to be used to send data and also applies filters to only /// receive data from the specified address. fn connect(&self, addr: A) -> io::Result<()>; /// Sends data on the socket to the remote address to which it is connected. /// /// The `connect` method will connect this socket to a remote address. This /// method will fail if the socket is not connected. fn send(&self, buf: &[u8]) -> io::Result; /// Receives data on the socket from the remote address to which it is /// connected. /// /// The `connect` method will connect this socket to a remote address. This /// method will fail if the socket is not connected. fn recv(&self, buf: &mut [u8]) -> io::Result; /// Moves this UDP socket into or out of nonblocking mode. /// /// For more information about this option, see /// [`TcpStreamExt::set_nonblocking`][link]. /// /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>; } #[doc(hidden)] pub trait AsSock { fn as_sock(&self) -> Socket; } #[cfg(any(unix, target_os = "wasi"))] impl AsSock for T { fn as_sock(&self) -> Socket { self.as_raw_fd() } } #[cfg(windows)] impl AsSock for T { fn as_sock(&self) -> Socket { self.as_raw_socket() as Socket } } cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "nto"))] { use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION; } else if #[cfg(any(target_os = "haiku", target_os = "netbsd", target_os = "openbsd"))] { use libc::SO_KEEPALIVE as KEEPALIVE_OPTION; } else if #[cfg(unix)] { use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION; } else { // ... } } impl TcpStreamExt for TcpStream { fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> { // TODO: casting usize to a c_int should be a checked cast set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int) } fn recv_buffer_size(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize) } fn set_send_buffer_size(&self, size: usize) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int) } fn send_buffer_size(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize) } fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY, nodelay as c_int) } fn nodelay(&self) -> io::Result { get_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY) .map(int2bool) } fn set_keepalive(&self, keepalive: Option) -> io::Result<()> { self.set_keepalive_ms(keepalive.map(dur2ms)) } fn keepalive(&self) -> io::Result> { self.keepalive_ms().map(|o| o.map(ms2dur)) } #[cfg(unix)] fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()> { try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE, keepalive.is_some() as c_int)); if let Some(dur) = keepalive { try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION, (dur / 1000) as c_int)); } Ok(()) } #[cfg(unix)] fn keepalive_ms(&self) -> io::Result> { let keepalive = try!(get_opt::(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE)); if keepalive == 0 { return Ok(None) } let secs = try!(get_opt::(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION)); Ok(Some((secs as u32) * 1000)) } #[cfg(target_os = "wasi")] fn set_keepalive_ms(&self, _keepalive: Option) -> io::Result<()> { unimplemented!() } #[cfg(target_os = "wasi")] fn keepalive_ms(&self) -> io::Result> { unimplemented!() } #[cfg(windows)] fn set_keepalive_ms(&self, keepalive: Option) -> io::Result<()> { let ms = keepalive.unwrap_or(INFINITE); let ka = tcp_keepalive { onoff: keepalive.is_some() as c_ulong, keepalivetime: ms as c_ulong, keepaliveinterval: ms as c_ulong, }; unsafe { ::cvt_win(WSAIoctl(self.as_sock(), SIO_KEEPALIVE_VALS, &ka as *const _ as *mut _, mem::size_of_val(&ka) as DWORD, 0 as *mut _, 0, 0 as *mut _, 0 as *mut _, None)).map(|_| ()) } } #[cfg(windows)] fn keepalive_ms(&self) -> io::Result> { let mut ka = tcp_keepalive { onoff: 0, keepalivetime: 0, keepaliveinterval: 0, }; unsafe { try!(::cvt_win(WSAIoctl(self.as_sock(), SIO_KEEPALIVE_VALS, 0 as *mut _, 0, &mut ka as *mut _ as *mut _, mem::size_of_val(&ka) as DWORD, 0 as *mut _, 0 as *mut _, None))); } Ok({ if ka.onoff == 0 { None } else { timeout2ms(ka.keepaliveinterval as DWORD) } }) } fn set_read_timeout_ms(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO, ms2timeout(dur)) } fn read_timeout_ms(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO) .map(timeout2ms) } fn set_write_timeout_ms(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO, ms2timeout(dur)) } fn write_timeout_ms(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO) .map(timeout2ms) } fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.set_read_timeout_ms(dur.map(dur2ms)) } fn read_timeout(&self) -> io::Result> { self.read_timeout_ms().map(|o| o.map(ms2dur)) } fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.set_write_timeout_ms(dur.map(dur2ms)) } fn write_timeout(&self) -> io::Result> { self.write_timeout_ms().map(|o| o.map(ms2dur)) } fn set_ttl(&self, ttl: u32) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int) } fn ttl(&self) -> io::Result { get_opt::(self.as_sock(), IPPROTO_IP, IP_TTL) .map(|b| b as u32) } fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int) } fn only_v6(&self) -> io::Result { get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool) } fn connect(&self, addr: T) -> io::Result<()> { do_connect(self.as_sock(), addr) } fn take_error(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err) } fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { set_nonblocking(self.as_sock(), nonblocking) } fn set_linger(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur)) } fn linger(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur) } } #[cfg(any(unix, target_os = "wasi"))] fn ms2timeout(dur: Option) -> timeval { // TODO: be more rigorous match dur { Some(d) => timeval { tv_sec: (d / 1000) as time_t, tv_usec: (d % 1000) as suseconds_t, }, None => timeval { tv_sec: 0, tv_usec: 0 }, } } #[cfg(any(unix, target_os = "wasi"))] fn timeout2ms(dur: timeval) -> Option { if dur.tv_sec == 0 && dur.tv_usec == 0 { None } else { Some(dur.tv_sec as u32 * 1000 + dur.tv_usec as u32 / 1000) } } #[cfg(windows)] fn ms2timeout(dur: Option) -> DWORD { dur.unwrap_or(0) } #[cfg(windows)] fn timeout2ms(dur: DWORD) -> Option { if dur == 0 { None } else { Some(dur) } } fn linger2dur(linger_opt: linger) -> Option { if linger_opt.l_onoff == 0 { None } else { Some(Duration::from_secs(linger_opt.l_linger as u64)) } } #[cfg(windows)] fn dur2linger(dur: Option) -> linger { match dur { Some(d) => { linger { l_onoff: 1, l_linger: d.as_secs() as u16, } }, None => linger { l_onoff: 0, l_linger: 0 }, } } #[cfg(any(unix, target_os = "wasi"))] fn dur2linger(dur: Option) -> linger { match dur { Some(d) => { linger { l_onoff: 1, l_linger: d.as_secs() as c_int, } }, None => linger { l_onoff: 0, l_linger: 0 }, } } fn ms2dur(ms: u32) -> Duration { Duration::new((ms as u64) / 1000, (ms as u32) % 1000 * 1_000_000) } fn dur2ms(dur: Duration) -> u32 { (dur.as_secs() as u32 * 1000) + (dur.subsec_nanos() / 1_000_000) } pub fn int2bool(n: c_int) -> bool { if n == 0 {false} else {true} } pub fn int2usize(n: c_int) -> usize { // TODO: casting c_int to a usize should be a checked cast n as usize } pub fn int2err(n: c_int) -> Option { if n == 0 { None } else { Some(io::Error::from_raw_os_error(n as i32)) } } impl UdpSocketExt for UdpSocket { fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int) } fn recv_buffer_size(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize) } fn set_send_buffer_size(&self, size: usize) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int) } fn send_buffer_size(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize) } fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST, broadcast as c_int) } fn broadcast(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST) .map(int2bool) } fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP, multicast_loop_v4 as c_int) } fn multicast_loop_v4(&self) -> io::Result { get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP) .map(int2bool) } fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL, multicast_ttl_v4 as c_int) } fn multicast_ttl_v4(&self) -> io::Result { get_opt::(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL) .map(|b| b as u32) } fn set_multicast_hops_v6(&self, _hops: u32) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS, _hops as c_int) } fn multicast_hops_v6(&self) -> io::Result { get_opt::(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS) .map(|b| b as u32) } fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int) } fn multicast_loop_v6(&self) -> io::Result { get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP) .map(int2bool) } fn set_multicast_if_v4(&self, _interface: &Ipv4Addr) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF, ip2in_addr(_interface)) } fn multicast_if_v4(&self) -> io::Result { get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF).map(in_addr2ip) } fn set_multicast_if_v6(&self, _interface: u32) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF, to_ipv6mr_interface(_interface)) } fn multicast_if_v6(&self) -> io::Result { get_opt::(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF).map(|b| b as u32) } fn set_ttl(&self, ttl: u32) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int) } fn ttl(&self) -> io::Result { get_opt::(self.as_sock(), IPPROTO_IP, IP_TTL) .map(|b| b as u32) } fn set_unicast_hops_v6(&self, _ttl: u32) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_UNICAST_HOPS, _ttl as c_int) } fn unicast_hops_v6(&self) -> io::Result { get_opt::(self.as_sock(), IPPROTO_IP, IPV6_UNICAST_HOPS) .map(|b| b as u32) } fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int) } fn only_v6(&self) -> io::Result { get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool) } fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { let mreq = ip_mreq { imr_multiaddr: ip2in_addr(multiaddr), imr_interface: ip2in_addr(interface), }; set_opt(self.as_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq) } #[cfg(not(target_os = "nto"))] fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = ipv6_mreq { ipv6mr_multiaddr: ip2in6_addr(multiaddr), ipv6mr_interface: to_ipv6mr_interface(interface), }; set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_ADD_MEMBERSHIP, mreq) } #[cfg(target_os = "nto")] fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform")) } fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { let mreq = ip_mreq { imr_multiaddr: ip2in_addr(multiaddr), imr_interface: ip2in_addr(interface), }; set_opt(self.as_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq) } #[cfg(not(target_os = "nto"))] fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = ipv6_mreq { ipv6mr_multiaddr: ip2in6_addr(multiaddr), ipv6mr_interface: to_ipv6mr_interface(interface), }; set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_DROP_MEMBERSHIP, mreq) } #[cfg(target_os = "nto")] fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform")) } fn set_read_timeout_ms(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO, ms2timeout(dur)) } fn read_timeout_ms(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO) .map(timeout2ms) } fn set_write_timeout_ms(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO, ms2timeout(dur)) } fn write_timeout_ms(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO) .map(timeout2ms) } fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.set_read_timeout_ms(dur.map(dur2ms)) } fn read_timeout(&self) -> io::Result> { self.read_timeout_ms().map(|o| o.map(ms2dur)) } fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.set_write_timeout_ms(dur.map(dur2ms)) } fn write_timeout(&self) -> io::Result> { self.write_timeout_ms().map(|o| o.map(ms2dur)) } fn take_error(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err) } fn connect(&self, addr: A) -> io::Result<()> { do_connect(self.as_sock(), addr) } #[cfg(unix)] fn send(&self, buf: &[u8]) -> io::Result { unsafe { ::cvt(send(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len(), 0)).map(|n| n as usize) } } #[cfg(target_os = "wasi")] fn send(&self, buf: &[u8]) -> io::Result { let _so_datalen: *mut sys::c::size_t = &mut 0; unsafe { let _errno = libc::__wasi_sock_send( self.as_sock() as libc::__wasi_fd_t, buf.as_ptr() as *const _, buf.len(), 0, _so_datalen, ); // TODO: handle errno Ok((*_so_datalen) as usize) } } #[cfg(windows)] fn send(&self, buf: &[u8]) -> io::Result { let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize); let buf = &buf[..len]; unsafe { ::cvt(send(self.as_sock(), buf.as_ptr() as *const _, len as c_int, 0)) .map(|n| n as usize) } } #[cfg(unix)] fn recv(&self, buf: &mut [u8]) -> io::Result { unsafe { ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0)) .map(|n| n as usize) } } #[cfg(target_os = "wasi")] fn recv(&self, buf: &mut [u8]) -> io::Result { let _ro_datalen: *mut sys::c::size_t = &mut 0; let _ro_flags: *mut sys::c::__wasi_roflags_t = &mut 0; unsafe { let _errno = __wasi_sock_recv( self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0, _ro_datalen, _ro_flags, ); // TODO: handle errno Ok((*_ro_datalen) as usize) } } #[cfg(windows)] fn recv(&self, buf: &mut [u8]) -> io::Result { let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize); let buf = &mut buf[..len]; unsafe { ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len() as c_int, 0)) .map(|n| n as usize) } } fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { set_nonblocking(self.as_sock(), nonblocking) } } fn do_connect(sock: Socket, addr: A) -> io::Result<()> { let err = io::Error::new(io::ErrorKind::Other, "no socket addresses resolved"); let addrs = try!(addr.to_socket_addrs()); let sys = sys::Socket::from_inner(sock); let sock = socket::Socket::from_inner(sys); let ret = addrs.fold(Err(err), |prev, addr| { prev.or_else(|_| sock.connect(&addr)) }); mem::forget(sock); return ret } #[cfg(unix)] fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; ::cvt(unsafe { ioctl(sock, FIONBIO, &mut nonblocking) }).map(|_| ()) } #[cfg(target_os = "wasi")] fn set_nonblocking(_sock: Socket, _nonblocking: bool) -> io::Result<()> { Ok(()) } #[cfg(windows)] fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; ::cvt(unsafe { ioctlsocket(sock, FIONBIO as c_int, &mut nonblocking) }).map(|_| ()) } #[cfg(any(unix, target_os = "wasi"))] fn ip2in_addr(ip: &Ipv4Addr) -> in_addr { let oct = ip.octets(); in_addr { s_addr: ::hton(((oct[0] as u32) << 24) | ((oct[1] as u32) << 16) | ((oct[2] as u32) << 8) | ((oct[3] as u32) << 0)), } } #[cfg(windows)] fn ip2in_addr(ip: &Ipv4Addr) -> in_addr { let oct = ip.octets(); unsafe { let mut S_un: in_addr_S_un = mem::zeroed(); *S_un.S_addr_mut() = ::hton(((oct[0] as u32) << 24) | ((oct[1] as u32) << 16) | ((oct[2] as u32) << 8) | ((oct[3] as u32) << 0)); in_addr { S_un: S_un, } } } fn in_addr2ip(ip: &in_addr) -> Ipv4Addr { let h_addr = c::in_addr_to_u32(ip); let a: u8 = (h_addr >> 24) as u8; let b: u8 = (h_addr >> 16) as u8; let c: u8 = (h_addr >> 8) as u8; let d: u8 = (h_addr >> 0) as u8; Ipv4Addr::new(a,b,c,d) } #[cfg(target_os = "android")] fn to_ipv6mr_interface(value: u32) -> c_int { value as c_int } #[cfg(not(target_os = "android"))] fn to_ipv6mr_interface(value: u32) -> c_uint { value as c_uint } fn ip2in6_addr(ip: &Ipv6Addr) -> in6_addr { let mut ret: in6_addr = unsafe { mem::zeroed() }; let seg = ip.segments(); let bytes = [ (seg[0] >> 8) as u8, (seg[0] >> 0) as u8, (seg[1] >> 8) as u8, (seg[1] >> 0) as u8, (seg[2] >> 8) as u8, (seg[2] >> 0) as u8, (seg[3] >> 8) as u8, (seg[3] >> 0) as u8, (seg[4] >> 8) as u8, (seg[4] >> 0) as u8, (seg[5] >> 8) as u8, (seg[5] >> 0) as u8, (seg[6] >> 8) as u8, (seg[6] >> 0) as u8, (seg[7] >> 8) as u8, (seg[7] >> 0) as u8, ]; #[cfg(windows)] unsafe { *ret.u.Byte_mut() = bytes; } #[cfg(not(windows))] { ret.s6_addr = bytes; } return ret } impl TcpListenerExt for TcpListener { fn set_ttl(&self, ttl: u32) -> io::Result<()> { set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int) } fn ttl(&self) -> io::Result { get_opt::(self.as_sock(), IPPROTO_IP, IP_TTL) .map(|b| b as u32) } fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int) } fn only_v6(&self) -> io::Result { get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool) } fn take_error(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err) } fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { set_nonblocking(self.as_sock(), nonblocking) } fn set_linger(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur)) } fn linger(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur) } } impl TcpBuilder { /// Sets the value for the `IP_TTL` option on this socket. /// /// This is the same as [`TcpStreamExt::set_ttl`][other]. /// /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl pub fn ttl(&self, ttl: u32) -> io::Result<&Self> { set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int) .map(|()| self) } /// Sets the value for the `IPV6_V6ONLY` option on this socket. /// /// This is the same as [`TcpStreamExt::set_only_v6`][other]. /// /// [other]: trait.TcpStreamExt.html#tymethod.set_only_v6 pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int) .map(|()| self) } /// Set value for the `SO_REUSEADDR` option on this socket. /// /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> { set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR, reuse as c_int).map(|()| self) } /// Check the `SO_REUSEADDR` option on this socket. pub fn get_reuse_address(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool) } /// Get the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing /// the field in the process. This can be useful for checking errors between /// calls. pub fn take_error(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err) } /// Sets the linger option for this socket fn set_linger(&self, dur: Option) -> io::Result<()> { set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur)) } /// Gets the linger option for this socket fn linger(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur) } } impl UdpBuilder { /// Sets the value for the `IP_TTL` option on this socket. /// /// This is the same as [`TcpStreamExt::set_ttl`][other]. /// /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl pub fn ttl(&self, ttl: u32) -> io::Result<&Self> { set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int) .map(|()| self) } /// Sets the value for the `IPV6_V6ONLY` option on this socket. /// /// This is the same as [`TcpStream::only_v6`][other]. /// /// [other]: struct.TcpBuilder.html#method.only_v6 pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> { set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int) .map(|()| self) } /// Set value for the `SO_REUSEADDR` option on this socket. /// /// This is the same as [`TcpBuilder::reuse_address`][other]. /// /// [other]: struct.TcpBuilder.html#method.reuse_address pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> { set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR, reuse as c_int).map(|()| self) } /// Check the `SO_REUSEADDR` option on this socket. pub fn get_reuse_address(&self) -> io::Result { get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool) } /// Get the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing /// the field in the process. This can be useful for checking errors between /// calls. pub fn take_error(&self) -> io::Result> { get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err) } } net2-0.2.39/src/lib.rs000064400000000000000000000071011046102023000124710ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Extensions to `std::net` networking types. //! //! This crate implements a number of extensions to the standard `std::net` //! networking types, hopefully being slated for inclusion into the standard //! library in the future. The goal of this crate is to expose all sorts of //! cross-platform and platform-specific configuration options of UDP/TCP //! sockets. System APIs are wrapped with as thin a layer as possible instead of //! bundling multiple actions into one API call. //! //! More information about the design of this crate can be found in the //! [associated rfc][rfc] //! //! [rfc]: https://github.com/rust-lang/rfcs/pull/1158 //! //! # Examples //! //! ```no_run //! use net2::TcpBuilder; //! //! let tcp = TcpBuilder::new_v4().unwrap(); //! tcp.reuse_address(true).unwrap() //! .only_v6(false).unwrap(); //! //! let mut stream = tcp.connect("127.0.0.1:80").unwrap(); //! //! // use `stream` as a TcpStream //! ``` #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/net2-rs")] #![deny(missing_docs, warnings)] // Silence warnings about deprecated try!() usage #![allow(deprecated)] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #[cfg(any(target_os = "wasi", unix))] extern crate libc; #[cfg(windows)] extern crate winapi; #[macro_use] extern crate cfg_if; use std::io; use std::ops::Neg; use std::net::{ToSocketAddrs, SocketAddr}; use utils::{One, NetInt}; mod tcp; mod udp; mod socket; mod ext; mod utils; #[cfg(unix)] #[path = "sys/unix/mod.rs"] mod sys; #[cfg(windows)] #[path = "sys/windows/mod.rs"] mod sys; #[cfg(target_os = "wasi")] #[path = "sys/wasi/mod.rs"] mod sys; #[cfg(all(unix, not(any(target_os = "solaris", target_os = "illumos"))))] pub mod unix; pub use tcp::TcpBuilder; pub use udp::UdpBuilder; pub use ext::{TcpStreamExt, TcpListenerExt, UdpSocketExt}; fn one_addr(tsa: T) -> io::Result { let mut addrs = try!(tsa.to_socket_addrs()); let addr = match addrs.next() { Some(addr) => addr, None => return Err(io::Error::new(io::ErrorKind::Other, "no socket addresses could be resolved")) }; if addrs.next().is_none() { Ok(addr) } else { Err(io::Error::new(io::ErrorKind::Other, "more than one address resolved")) } } fn cvt>(t: T) -> io::Result { let one: T = T::one(); if t == -one { Err(io::Error::last_os_error()) } else { Ok(t) } } #[cfg(windows)] fn cvt_win(t: T) -> io::Result { if t == T::zero() { Err(io::Error::last_os_error()) } else { Ok(t) } } fn hton(i: I) -> I { i.to_be() } fn ntoh(i: I) -> I { I::from_be(i) } trait AsInner { type Inner; fn as_inner(&self) -> &Self::Inner; } trait FromInner { type Inner; fn from_inner(inner: Self::Inner) -> Self; } trait IntoInner { type Inner; fn into_inner(self) -> Self::Inner; } net2-0.2.39/src/socket.rs000064400000000000000000000210031046102023000132100ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::fmt; use std::io; use std::mem; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; #[cfg(any(unix, target_os = "wasi"))] use libc::c_int; #[cfg(windows)] use winapi::ctypes::c_int; use sys; use sys::c; pub struct Socket { inner: sys::Socket, } impl Socket { pub fn new(family: c_int, ty: c_int) -> io::Result { Ok(Socket { inner: try!(sys::Socket::new(family, ty)) }) } pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> { let (addr, len) = addr2raw(addr); unsafe { ::cvt(c::bind(self.inner.raw(), addr.as_ptr(), len as c::socklen_t)).map(|_| ()) } } pub fn listen(&self, backlog: i32) -> io::Result<()> { unsafe { ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ()) } } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { let (addr, len) = addr2raw(addr); unsafe { ::cvt(c::connect(self.inner.raw(), addr.as_ptr(), len)).map(|_| ()) } } pub fn getsockname(&self) -> io::Result { unsafe { let mut storage: c::sockaddr_storage = mem::zeroed(); let mut len = mem::size_of_val(&storage) as c::socklen_t; try!(::cvt(c::getsockname(self.inner.raw(), &mut storage as *mut _ as *mut _, &mut len))); raw2addr(&storage, len) } } } impl fmt::Debug for Socket { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.raw().fmt(f) } } impl ::AsInner for Socket { type Inner = sys::Socket; fn as_inner(&self) -> &sys::Socket { &self.inner } } impl ::FromInner for Socket { type Inner = sys::Socket; fn from_inner(sock: sys::Socket) -> Socket { Socket { inner: sock } } } impl ::IntoInner for Socket { type Inner = sys::Socket; fn into_inner(self) -> sys::Socket { self.inner } } /// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level /// SocketAddr* types into their system representation. The benefit of this specific /// type over using `c::sockaddr_storage` is that this type is exactly as large as it /// needs to be and not a lot larger. #[repr(C)] pub(crate) union SocketAddrCRepr { v4: c::sockaddr_in, v6: c::sockaddr_in6, } impl SocketAddrCRepr { pub(crate) fn as_ptr(&self) -> *const c::sockaddr { self as *const _ as *const c::sockaddr } } fn addr2raw(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) { match addr { &SocketAddr::V4(ref v4) => addr2raw_v4(v4), &SocketAddr::V6(ref v6) => addr2raw_v6(v6), } } #[cfg(unix)] fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) { let sin_addr = c::in_addr { s_addr: u32::from(*addr.ip()).to_be(), }; let sockaddr = SocketAddrCRepr { v4: c::sockaddr_in { sin_family: c::AF_INET as c::sa_family_t, sin_port: addr.port().to_be(), sin_addr, #[cfg(not(target_os = "haiku"))] sin_zero: [0; 8], #[cfg(target_os = "haiku")] sin_zero: [0; 24], #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "haiku", target_os = "nto", ))] sin_len: 0, }, }; (sockaddr, mem::size_of::() as c::socklen_t) } #[cfg(windows)] fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) { let sin_addr = unsafe { let mut s_un = mem::zeroed::(); *s_un.S_addr_mut() = u32::from(*addr.ip()).to_be(); c::IN_ADDR { S_un: s_un } }; let sockaddr = SocketAddrCRepr { v4: c::sockaddr_in { sin_family: c::AF_INET as c::sa_family_t, sin_port: addr.port().to_be(), sin_addr, sin_zero: [0; 8], }, }; (sockaddr, mem::size_of::() as c::socklen_t) } #[cfg(unix)] fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) { let sin6_addr = { let mut sin6_addr = unsafe { mem::zeroed::() }; sin6_addr.s6_addr = addr.ip().octets(); sin6_addr }; let sockaddr = SocketAddrCRepr { v6: c::sockaddr_in6 { sin6_family: c::AF_INET6 as c::sa_family_t, sin6_port: addr.port().to_be(), sin6_addr, sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "haiku", target_os = "nto", ))] sin6_len: 0, #[cfg(any(target_os = "solaris", target_os = "illumos"))] __sin6_src_id: 0, }, }; (sockaddr, mem::size_of::() as c::socklen_t) } #[cfg(windows)] fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) { let sin6_addr = unsafe { let mut u = mem::zeroed::(); *u.Byte_mut() = addr.ip().octets(); c::IN6_ADDR { u } }; let scope_id = unsafe { let mut u = mem::zeroed::(); *u.sin6_scope_id_mut() = addr.scope_id(); u }; let sockaddr = SocketAddrCRepr { v6: c::sockaddr_in6 { sin6_family: c::AF_INET6 as c::sa_family_t, sin6_port: addr.port().to_be(), sin6_addr, sin6_flowinfo: addr.flowinfo(), u: scope_id, }, }; (sockaddr, mem::size_of::() as c::socklen_t) } fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result { match storage.ss_family as c_int { c::AF_INET => { unsafe { assert!(len as usize >= mem::size_of::()); let sa = storage as *const _ as *const c::sockaddr_in; let bits = c::sockaddr_in_u32(&(*sa)); let ip = Ipv4Addr::new((bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8); Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port)))) } } c::AF_INET6 => { unsafe { assert!(len as usize >= mem::size_of::()); let sa = storage as *const _ as *const c::sockaddr_in6; #[cfg(windows)] let arr = (*sa).sin6_addr.u.Byte(); #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr; let ip = Ipv6Addr::new( (arr[0] as u16) << 8 | (arr[1] as u16), (arr[2] as u16) << 8 | (arr[3] as u16), (arr[4] as u16) << 8 | (arr[5] as u16), (arr[6] as u16) << 8 | (arr[7] as u16), (arr[8] as u16) << 8 | (arr[9] as u16), (arr[10] as u16) << 8 | (arr[11] as u16), (arr[12] as u16) << 8 | (arr[13] as u16), (arr[14] as u16) << 8 | (arr[15] as u16), ); #[cfg(windows)] let sin6_scope_id = *(*sa).u.sin6_scope_id(); #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id; Ok(SocketAddr::V6(SocketAddrV6::new(ip, ::ntoh((*sa).sin6_port), (*sa).sin6_flowinfo, sin6_scope_id))) } } _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")), } } net2-0.2.39/src/sys/unix/impls.rs000064400000000000000000000025411046102023000146530ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::os::unix::io::{FromRawFd, AsRawFd}; use libc::c_int; use {TcpBuilder, UdpBuilder, FromInner, AsInner}; use socket::Socket; use sys; impl FromRawFd for TcpBuilder { unsafe fn from_raw_fd(fd: c_int) -> TcpBuilder { let sock = sys::Socket::from_inner(fd); TcpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawFd for TcpBuilder { fn as_raw_fd(&self) -> c_int { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() } } impl FromRawFd for UdpBuilder { unsafe fn from_raw_fd(fd: c_int) -> UdpBuilder { let sock = sys::Socket::from_inner(fd); UdpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawFd for UdpBuilder { fn as_raw_fd(&self) -> c_int { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() } } net2-0.2.39/src/sys/unix/mod.rs000064400000000000000000000061601046102023000143070ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::io; use std::mem; use std::net::{TcpListener, TcpStream, UdpSocket}; use std::os::unix::io::FromRawFd; use libc::{self, c_int}; #[cfg(not(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris")))] use libc::{ioctl, FIOCLEX}; mod impls; pub mod c { pub use libc::*; pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 { ::ntoh((*sa).sin_addr.s_addr) } pub fn in_addr_to_u32(addr: &in_addr) -> u32 { ::ntoh(addr.s_addr) } } pub struct Socket { fd: c_int, } impl Socket { #[cfg(not(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris")))] pub fn new(family: c_int, ty: c_int) -> io::Result { unsafe { // Linux >2.6.26 overloads the type argument to accept SOCK_CLOEXEC, // avoiding a race with another thread running fork/exec between // socket() and ioctl() #[cfg(any(target_os = "linux", target_os = "android"))] match ::cvt(libc::socket(family, ty | libc::SOCK_CLOEXEC, 0)) { Ok(fd) => return Ok(Socket { fd: fd }), // Older versions of Linux return EINVAL; fall back to ioctl Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} Err(e) => return Err(e), } let fd = try!(::cvt(libc::socket(family, ty, 0))); ioctl(fd, FIOCLEX); Ok(Socket { fd: fd }) } } // ioctl(FIOCLEX) is not supported by Solaris/illumos or emscripten, // use fcntl(FD_CLOEXEC) instead #[cfg(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris"))] pub fn new(family: c_int, ty: c_int) -> io::Result { unsafe { let fd = try!(::cvt(libc::socket(family, ty, 0))); libc::fcntl(fd, libc::FD_CLOEXEC); Ok(Socket { fd: fd }) } } pub fn raw(&self) -> c_int { self.fd } fn into_fd(self) -> c_int { let fd = self.fd; mem::forget(self); fd } pub fn into_tcp_listener(self) -> TcpListener { unsafe { TcpListener::from_raw_fd(self.into_fd()) } } pub fn into_tcp_stream(self) -> TcpStream { unsafe { TcpStream::from_raw_fd(self.into_fd()) } } pub fn into_udp_socket(self) -> UdpSocket { unsafe { UdpSocket::from_raw_fd(self.into_fd()) } } } impl ::FromInner for Socket { type Inner = c_int; fn from_inner(fd: c_int) -> Socket { Socket { fd: fd } } } impl Drop for Socket { fn drop(&mut self) { unsafe { let _ = libc::close(self.fd); } } } net2-0.2.39/src/sys/wasi/impls.rs000064400000000000000000000017131046102023000146330ustar 00000000000000use std::os::wasi::io::{FromRawFd, AsRawFd}; use {TcpBuilder, UdpBuilder, FromInner, AsInner}; use socket::Socket; use sys::{self, c::__wasi_fd_t}; impl FromRawFd for TcpBuilder { unsafe fn from_raw_fd(fd: __wasi_fd_t) -> TcpBuilder { let sock = sys::Socket::from_inner(fd); TcpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawFd for TcpBuilder { fn as_raw_fd(&self) -> __wasi_fd_t { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t } } impl FromRawFd for UdpBuilder { unsafe fn from_raw_fd(fd: __wasi_fd_t) -> UdpBuilder { let sock = sys::Socket::from_inner(fd); UdpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawFd for UdpBuilder { fn as_raw_fd(&self) -> __wasi_fd_t { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t } } net2-0.2.39/src/sys/wasi/mod.rs000064400000000000000000000116621046102023000142720ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_camel_case_types)] use libc::{self, c_int, __wasi_fd_t}; use std::io; use std::mem; use std::net::{TcpListener, TcpStream, UdpSocket}; use std::os::wasi::io::FromRawFd; mod impls; pub mod c { pub use libc::*; pub type sa_family_t = u16; pub type socklen_t = u32; pub type in_port_t = u16; pub const SOCK_DGRAM: c_int = 0x00; pub const SOL_SOCKET: c_int = 0x00; pub const SO_RCVBUF: c_int = 0x00; pub const SO_SNDBUF: c_int = 0x00; pub const TCP_NODELAY: c_int = 0x00; pub const IPPROTO_TCP: c_int = 0x00; pub const SO_RCVTIMEO: c_int = 0x00; pub const SO_SNDTIMEO: c_int = 0x00; pub const IPPROTO_IP: c_int = 0x00; pub const IP_TTL: c_int = 0x00; pub const IPPROTO_IPV6: c_int = 0x00; pub const IPV6_V6ONLY: c_int = 0x00; pub const SO_ERROR: c_int = 0x00; pub const SO_LINGER: c_int = 0x00; pub const SO_BROADCAST: c_int = 0x00; pub const IP_MULTICAST_LOOP: c_int = 0x00; pub const IP_MULTICAST_TTL: c_int = 0x00; pub const IPV6_MULTICAST_HOPS: c_int = 0x00; pub const IPV6_MULTICAST_LOOP: c_int = 0x00; pub const IP_MULTICAST_IF: c_int = 0x00; pub const IPV6_MULTICAST_IF: c_int = 0x00; pub const IPV6_UNICAST_HOPS: c_int = 0x00; pub const IP_ADD_MEMBERSHIP: c_int = 0x00; pub const IPV6_ADD_MEMBERSHIP: c_int = 0x00; pub const IP_DROP_MEMBERSHIP: c_int = 0x00; pub const IPV6_DROP_MEMBERSHIP: c_int = 0x00; pub const SO_REUSEADDR: c_int = 0x00; pub const SOCK_STREAM: c_int = 0x00; pub const AF_INET: c_int = 0x00; pub const AF_INET6: c_int = 0x01; #[repr(C)] pub struct sockaddr_storage { pub ss_family: sa_family_t, } #[repr(C)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } #[repr(C)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } #[repr(C)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8; 8], } #[repr(align(4))] #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u8; 16], } #[derive(Copy, Clone)] pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } pub type in_addr_t = u32; #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[derive(Copy, Clone)] pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub unsafe fn getsockname(_socket: __wasi_fd_t, _address: *mut sockaddr, _address_len: *mut socklen_t) -> c_int { unimplemented!() } pub unsafe fn connect(_socket: __wasi_fd_t, _address: *const sockaddr, _len: socklen_t) -> c_int { unimplemented!() } pub unsafe fn listen(_socket: __wasi_fd_t, _backlog: c_int) -> c_int { unimplemented!() } pub unsafe fn bind(_socket: __wasi_fd_t, _address: *const sockaddr, _address_len: socklen_t) -> c_int { unimplemented!() } pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 { ::ntoh((*sa).sin_addr.s_addr) } pub fn in_addr_to_u32(addr: &in_addr) -> u32 { ::ntoh(addr.s_addr) } } pub struct Socket { fd: __wasi_fd_t, } impl Socket { pub fn new(_family: c_int, _ty: c_int) -> io::Result { unimplemented!() } pub fn raw(&self) -> libc::__wasi_fd_t { self.fd } fn into_fd(self) -> libc::__wasi_fd_t { let fd = self.fd; mem::forget(self); fd } pub fn into_tcp_listener(self) -> TcpListener { unsafe { TcpListener::from_raw_fd(self.into_fd()) } } pub fn into_tcp_stream(self) -> TcpStream { unsafe { TcpStream::from_raw_fd(self.into_fd()) } } pub fn into_udp_socket(self) -> UdpSocket { unsafe { UdpSocket::from_raw_fd(self.into_fd()) } } } impl ::FromInner for Socket { type Inner = libc::__wasi_fd_t; fn from_inner(fd: libc::__wasi_fd_t) -> Socket { Socket { fd: fd } } } impl Drop for Socket { fn drop(&mut self) { // unsafe { // let _ = libc::close(self.fd); // } } }net2-0.2.39/src/sys/windows/impls.rs000064400000000000000000000027461046102023000153710ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::os::windows::io::{FromRawSocket, RawSocket, AsRawSocket}; use winapi::um::winsock2::SOCKET; use {TcpBuilder, UdpBuilder, FromInner, AsInner}; use socket::Socket; use sys; impl FromRawSocket for TcpBuilder { unsafe fn from_raw_socket(fd: RawSocket) -> TcpBuilder { let sock = sys::Socket::from_inner(fd as SOCKET); TcpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawSocket for TcpBuilder { fn as_raw_socket(&self) -> RawSocket { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as RawSocket } } impl FromRawSocket for UdpBuilder { unsafe fn from_raw_socket(fd: RawSocket) -> UdpBuilder { let sock = sys::Socket::from_inner(fd as SOCKET); UdpBuilder::from_inner(Socket::from_inner(sock)) } } impl AsRawSocket for UdpBuilder { fn as_raw_socket(&self) -> RawSocket { // TODO: this unwrap() is very bad self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as RawSocket } } net2-0.2.39/src/sys/windows/mod.rs000064400000000000000000000073161046102023000150220ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] use std::io; use std::mem; use std::net::{TcpListener, TcpStream, UdpSocket}; use std::os::windows::io::{RawSocket, FromRawSocket}; use std::sync::{Once, ONCE_INIT}; const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; pub mod c { pub use winapi::ctypes::*; pub use winapi::um::handleapi::*; pub use winapi::um::winbase::*; pub use winapi::um::winsock2::*; pub use winapi::um::ws2tcpip::*; pub use winapi::shared::inaddr::*; pub use winapi::shared::in6addr::*; pub use winapi::shared::minwindef::*; pub use winapi::shared::ntdef::*; pub use winapi::shared::ws2def::*; pub use winapi::shared::ws2def::{SOCK_STREAM, SOCK_DGRAM}; pub use winapi::shared::ws2def::SOCKADDR as sockaddr; pub use winapi::shared::ws2def::SOCKADDR_STORAGE as sockaddr_storage; pub use winapi::shared::ws2def::SOCKADDR_IN as sockaddr_in; pub use winapi::shared::ws2def::ADDRESS_FAMILY as sa_family_t; pub use winapi::shared::ws2ipdef::*; pub use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6; pub use winapi::shared::ws2ipdef::IP_MREQ as ip_mreq; pub use winapi::shared::ws2ipdef::IPV6_MREQ as ipv6_mreq; pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 { ::ntoh(unsafe { *sa.sin_addr.S_un.S_addr() }) } pub fn in_addr_to_u32(addr: &in_addr) -> u32 { ::ntoh(unsafe { *addr.S_un.S_addr() }) } } use self::c::*; mod impls; fn init() { static INIT: Once = ONCE_INIT; INIT.call_once(|| { // Initialize winsock through the standard library by just creating a // dummy socket. Whether this is successful or not we drop the result as // libstd will be sure to have initialized winsock. let _ = UdpSocket::bind("127.0.0.1:34254"); }); } pub struct Socket { socket: SOCKET, } impl Socket { pub fn new(family: c_int, ty: c_int) -> io::Result { init(); let socket = try!(unsafe { match WSASocketW(family, ty, 0, 0 as *mut _, 0, WSA_FLAG_OVERLAPPED) { INVALID_SOCKET => Err(io::Error::last_os_error()), n => Ok(Socket { socket: n }), } }); try!(socket.set_no_inherit()); Ok(socket) } pub fn raw(&self) -> SOCKET { self.socket } fn into_socket(self) -> SOCKET { let socket = self.socket; mem::forget(self); socket } pub fn into_tcp_listener(self) -> TcpListener { unsafe { TcpListener::from_raw_socket(self.into_socket() as RawSocket) } } pub fn into_tcp_stream(self) -> TcpStream { unsafe { TcpStream::from_raw_socket(self.into_socket() as RawSocket) } } pub fn into_udp_socket(self) -> UdpSocket { unsafe { UdpSocket::from_raw_socket(self.into_socket() as RawSocket) } } fn set_no_inherit(&self) -> io::Result<()> { ::cvt_win(unsafe { SetHandleInformation(self.socket as HANDLE, HANDLE_FLAG_INHERIT, 0) }).map(|_| ()) } } impl ::FromInner for Socket { type Inner = SOCKET; fn from_inner(socket: SOCKET) -> Socket { Socket { socket: socket } } } impl Drop for Socket { fn drop(&mut self) { unsafe { let _ = closesocket(self.socket); } } } net2-0.2.39/src/tcp.rs000064400000000000000000000134361046102023000125210ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::cell::RefCell; use std::io; use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream}; use std::fmt; use IntoInner; use socket::Socket; use sys::c; /// An "in progress" TCP socket which has not yet been connected or listened. /// /// Allows configuration of a socket before one of these operations is executed. pub struct TcpBuilder { socket: RefCell>, } impl TcpBuilder { /// Constructs a new TcpBuilder with the `AF_INET` domain, the `SOCK_STREAM` /// type, and with a protocol argument of 0. /// /// Note that passing other kinds of flags or arguments can be done through /// the `FromRaw{Fd,Socket}` implementation. pub fn new_v4() -> io::Result { Socket::new(c::AF_INET, c::SOCK_STREAM).map(::FromInner::from_inner) } /// Constructs a new TcpBuilder with the `AF_INET6` domain, the `SOCK_STREAM` /// type, and with a protocol argument of 0. /// /// Note that passing other kinds of flags or arguments can be done through /// the `FromRaw{Fd,Socket}` implementation. pub fn new_v6() -> io::Result { Socket::new(c::AF_INET6, c::SOCK_STREAM).map(::FromInner::from_inner) } /// Binds this socket to the specified address. /// /// This function directly corresponds to the bind(2) function on Windows /// and Unix. pub fn bind(&self, addr: T) -> io::Result<&TcpBuilder> where T: ToSocketAddrs { self.with_socket(|sock| { let addr = try!(::one_addr(addr)); sock.bind(&addr) }).map(|()| self) } /// Mark a socket as ready to accept incoming connection requests using /// accept() /// /// This function directly corresponds to the listen(2) function on Windows /// and Unix. /// /// An error will be returned if `listen` or `connect` has already been /// called on this builder. pub fn listen(&self, backlog: i32) -> io::Result { self.with_socket(|sock| { sock.listen(backlog) }).and_then(|()| { self.to_tcp_listener() }) } /// Initiate a connection on this socket to the specified address. /// /// This function directly corresponds to the connect(2) function on Windows /// and Unix. /// /// An error will be returned if `listen` or `connect` has already been /// called on this builder. pub fn connect(&self, addr: T) -> io::Result where T: ToSocketAddrs { self.with_socket(|sock| { let err = io::Error::new(io::ErrorKind::Other, "no socket addresses resolved"); try!(addr.to_socket_addrs()).fold(Err(err), |prev, addr| { prev.or_else(|_| sock.connect(&addr)) }) }).and_then(|()| { self.to_tcp_stream() }) } /// Converts this builder into a `TcpStream` /// /// This function will consume the internal socket and return it re-wrapped /// as a `TcpStream`. An error will be returned if the internal socket has /// already been consumed from a successful call to `connect`, `listen`, /// etc. pub fn to_tcp_stream(&self) -> io::Result { self.socket.borrow_mut().take().map(|s| s.into_inner().into_tcp_stream()) .ok_or(io::Error::new(io::ErrorKind::Other, "socket has already been consumed")) } /// Converts this builder into a `TcpListener` /// /// This function will consume the internal socket and return it re-wrapped /// as a `TcpListener`. An error will be returned if the internal socket has /// already been consumed from a successful call to `connect`, `listen`, /// etc. pub fn to_tcp_listener(&self) -> io::Result { self.socket.borrow_mut().take() .map(|s| s.into_inner().into_tcp_listener()) .ok_or(io::Error::new(io::ErrorKind::Other, "socket has already been consumed")) } /// Returns the address of the local half of this TCP socket. /// /// An error will be returned if `listen` or `connect` has already been /// called on this builder. pub fn local_addr(&self) -> io::Result { match *self.socket.borrow() { Some(ref s) => s.getsockname(), None => Err(io::Error::new(io::ErrorKind::Other, "builder has already finished its socket")), } } fn with_socket(&self, f: F) -> io::Result<()> where F: FnOnce(&Socket) -> io::Result<()> { match *self.socket.borrow() { Some(ref s) => f(s), None => Err(io::Error::new(io::ErrorKind::Other, "builder has already finished its socket")), } } } impl fmt::Debug for TcpBuilder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "TcpBuilder {{ socket: {:?} }}", self.socket.borrow().as_ref().unwrap()) } } impl ::AsInner for TcpBuilder { type Inner = RefCell>; fn as_inner(&self) -> &RefCell> { &self.socket } } impl ::FromInner for TcpBuilder { type Inner = Socket; fn from_inner(sock: Socket) -> TcpBuilder { TcpBuilder { socket: RefCell::new(Some(sock)) } } } net2-0.2.39/src/udp.rs000064400000000000000000000056271046102023000125260ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::cell::RefCell; use std::fmt; use std::io; use std::net::{ToSocketAddrs, UdpSocket}; use IntoInner; use socket::Socket; use sys::c; /// An "in progress" UDP socket which has not yet been connected. /// /// Allows configuration of a socket before the socket is connected. pub struct UdpBuilder { socket: RefCell>, } impl UdpBuilder { /// Constructs a new UdpBuilder with the `AF_INET` domain, the `SOCK_DGRAM` /// type, and with a protocol argument of 0. /// /// Note that passing other kinds of flags or arguments can be done through /// the `FromRaw{Fd,Socket}` implementation. pub fn new_v4() -> io::Result { Socket::new(c::AF_INET, c::SOCK_DGRAM).map(::FromInner::from_inner) } /// Constructs a new UdpBuilder with the `AF_INET6` domain, the `SOCK_DGRAM` /// type, and with a protocol argument of 0. /// /// Note that passing other kinds of flags or arguments can be done through /// the `FromRaw{Fd,Socket}` implementation. pub fn new_v6() -> io::Result { Socket::new(c::AF_INET6, c::SOCK_DGRAM).map(::FromInner::from_inner) } /// Binds this socket to the specified address. /// /// This function directly corresponds to the bind(2) function on Windows /// and Unix. pub fn bind(&self, addr: T) -> io::Result where T: ToSocketAddrs { try!(self.with_socket(|sock| { let addr = try!(::one_addr(addr)); sock.bind(&addr) })); Ok(self.socket.borrow_mut().take().unwrap().into_inner().into_udp_socket()) } fn with_socket(&self, f: F) -> io::Result<()> where F: FnOnce(&Socket) -> io::Result<()> { match *self.socket.borrow() { Some(ref s) => f(s), None => Err(io::Error::new(io::ErrorKind::Other, "builder has already finished its socket")), } } } impl fmt::Debug for UdpBuilder { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UdpBuilder {{ socket: {:?} }}", self.socket.borrow().as_ref().unwrap()) } } impl ::AsInner for UdpBuilder { type Inner = RefCell>; fn as_inner(&self) -> &RefCell> { &self.socket } } impl ::FromInner for UdpBuilder { type Inner = Socket; fn from_inner(sock: Socket) -> UdpBuilder { UdpBuilder { socket: RefCell::new(Some(sock)) } } } net2-0.2.39/src/unix.rs000064400000000000000000000040271046102023000127120ustar 00000000000000//! Unix-specific extensions to the `std::net` types. use std::io; use sys::c::{self, c_int}; use {TcpBuilder, UdpBuilder}; use ext::{self, AsSock}; /// Unix-specific extensions for the `TcpBuilder` type in this library. pub trait UnixTcpBuilderExt { /// Set value for the `SO_REUSEPORT` option on this socket. /// /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. fn reuse_port(&self, reuse: bool) -> io::Result<&Self>; /// Check the value of the `SO_REUSEPORT` option on this socket. fn get_reuse_port(&self) -> io::Result; } impl UnixTcpBuilderExt for TcpBuilder { fn reuse_port(&self, reuse: bool) -> io::Result<&Self> { ext::set_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT, reuse as c_int).map(|()| self) } fn get_reuse_port(&self) -> io::Result { ext::get_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT) .map(ext::int2bool) } } /// Unix-specific extensions for the `UdpBuilder` type in this library. pub trait UnixUdpBuilderExt { /// Set value for the `SO_REUSEPORT` option on this socket. /// /// This indicates that further calls to `bind` may allow reuse of local /// addresses. For IPv4 sockets this means that a socket may bind even when /// there's a socket already listening on this port. fn reuse_port(&self, reuse: bool) -> io::Result<&Self>; /// Check the value of the `SO_REUSEPORT` option on this socket. fn get_reuse_port(&self) -> io::Result; } impl UnixUdpBuilderExt for UdpBuilder { fn reuse_port(&self, reuse: bool) -> io::Result<&Self> { ext::set_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT, reuse as c_int).map(|()| self) } fn get_reuse_port(&self) -> io::Result { ext::get_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT) .map(ext::int2bool) } } net2-0.2.39/src/utils.rs000064400000000000000000000023311046102023000130630ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[doc(hidden)] pub trait NetInt { fn from_be(i: Self) -> Self; fn to_be(&self) -> Self; } macro_rules! doit { ($($t:ident)*) => ($(impl NetInt for $t { fn from_be(i: Self) -> Self { <$t>::from_be(i) } fn to_be(&self) -> Self { <$t>::to_be(*self) } })*) } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } #[doc(hidden)] pub trait One { fn one() -> Self; } macro_rules! one { ($($t:ident)*) => ($( impl One for $t { fn one() -> $t { 1 } } )*) } one! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } #[doc(hidden)] pub trait Zero { fn zero() -> Self; } macro_rules! zero { ($($t:ident)*) => ($( impl Zero for $t { fn zero() -> $t { 0 } } )*) } zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }