Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8e261d1

Browse files
committedMar 4, 2016
Auto merge of rust-lang#31945 - sfackler:net2, r=alexcrichton
I have these tagged as stable in 1.9, so this shouldn't merge until the 1.8 beta's cut.
2 parents e91f889 + e4aa513 commit 8e261d1

File tree

6 files changed

+733
-4
lines changed

6 files changed

+733
-4
lines changed
 

‎src/libstd/net/tcp.rs

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,89 @@ impl TcpStream {
180180
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
181181
self.0.write_timeout()
182182
}
183+
184+
/// Sets the value of the `TCP_NODELAY` option on this socket.
185+
///
186+
/// If set, this option disables the Nagle algorithm. This means that
187+
/// segments are always sent as soon as possible, even if there is only a
188+
/// small amount of data. When not set, data is buffered until there is a
189+
/// sufficient amount to send out, thereby avoiding the frequent sending of
190+
/// small packets.
191+
#[stable(feature = "net2_mutators", since = "1.9.0")]
192+
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
193+
self.0.set_nodelay(nodelay)
194+
}
195+
196+
/// Gets the value of the `TCP_NODELAY` option on this socket.
197+
///
198+
/// For more information about this option, see [`set_nodelay`][link].
199+
///
200+
/// [link]: #tymethod.set_nodelay
201+
#[stable(feature = "net2_mutators", since = "1.9.0")]
202+
pub fn nodelay(&self) -> io::Result<bool> {
203+
self.0.nodelay()
204+
}
205+
206+
/// Sets the value for the `IP_TTL` option on this socket.
207+
///
208+
/// This value sets the time-to-live field that is used in every packet sent
209+
/// from this socket.
210+
#[stable(feature = "net2_mutators", since = "1.9.0")]
211+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
212+
self.0.set_ttl(ttl)
213+
}
214+
215+
/// Gets the value of the `IP_TTL` option for this socket.
216+
///
217+
/// For more information about this option, see [`set_ttl`][link].
218+
///
219+
/// [link]: #tymethod.set_ttl
220+
#[stable(feature = "net2_mutators", since = "1.9.0")]
221+
pub fn ttl(&self) -> io::Result<u32> {
222+
self.0.ttl()
223+
}
224+
225+
/// Sets the value for the `IPV6_V6ONLY` option on this socket.
226+
///
227+
/// If this is set to `true` then the socket is restricted to sending and
228+
/// receiving IPv6 packets only. If this is the case, an IPv4 and an IPv6
229+
/// application can each bind the same port at the same time.
230+
///
231+
/// If this is set to `false` then the socket can be used to send and
232+
/// receive packets from an IPv4-mapped IPv6 address.
233+
#[stable(feature = "net2_mutators", since = "1.9.0")]
234+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
235+
self.0.set_only_v6(only_v6)
236+
}
237+
238+
/// Gets the value of the `IPV6_V6ONLY` option for this socket.
239+
///
240+
/// For more information about this option, see [`set_only_v6`][link].
241+
///
242+
/// [link]: #tymethod.set_only_v6
243+
#[stable(feature = "net2_mutators", since = "1.9.0")]
244+
pub fn only_v6(&self) -> io::Result<bool> {
245+
self.0.only_v6()
246+
}
247+
248+
/// Get the value of the `SO_ERROR` option on this socket.
249+
///
250+
/// This will retrieve the stored error in the underlying socket, clearing
251+
/// the field in the process. This can be useful for checking errors between
252+
/// calls.
253+
#[stable(feature = "net2_mutators", since = "1.9.0")]
254+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
255+
self.0.take_error()
256+
}
257+
258+
/// Moves this TCP stream into or out of nonblocking mode.
259+
///
260+
/// On Unix this corresponds to calling fcntl, and on Windows this
261+
/// corresponds to calling ioctlsocket.
262+
#[stable(feature = "net2_mutators", since = "1.9.0")]
263+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
264+
self.0.set_nonblocking(nonblocking)
265+
}
183266
}
184267

185268
#[stable(feature = "rust1", since = "1.0.0")]
@@ -278,6 +361,67 @@ impl TcpListener {
278361
pub fn incoming(&self) -> Incoming {
279362
Incoming { listener: self }
280363
}
364+
365+
/// Sets the value for the `IP_TTL` option on this socket.
366+
///
367+
/// This value sets the time-to-live field that is used in every packet sent
368+
/// from this socket.
369+
#[stable(feature = "net2_mutators", since = "1.9.0")]
370+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
371+
self.0.set_ttl(ttl)
372+
}
373+
374+
/// Gets the value of the `IP_TTL` option for this socket.
375+
///
376+
/// For more information about this option, see [`set_ttl`][link].
377+
///
378+
/// [link]: #tymethod.set_ttl
379+
#[stable(feature = "net2_mutators", since = "1.9.0")]
380+
pub fn ttl(&self) -> io::Result<u32> {
381+
self.0.ttl()
382+
}
383+
384+
/// Sets the value for the `IPV6_V6ONLY` option on this socket.
385+
///
386+
/// If this is set to `true` then the socket is restricted to sending and
387+
/// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
388+
/// can bind the same port at the same time.
389+
///
390+
/// If this is set to `false` then the socket can be used to send and
391+
/// receive packets from an IPv4-mapped IPv6 address.
392+
#[stable(feature = "net2_mutators", since = "1.9.0")]
393+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
394+
self.0.set_only_v6(only_v6)
395+
}
396+
397+
/// Gets the value of the `IPV6_V6ONLY` option for this socket.
398+
///
399+
/// For more information about this option, see [`set_only_v6`][link].
400+
///
401+
/// [link]: #tymethod.set_only_v6
402+
#[stable(feature = "net2_mutators", since = "1.9.0")]
403+
pub fn only_v6(&self) -> io::Result<bool> {
404+
self.0.only_v6()
405+
}
406+
407+
/// Get the value of the `SO_ERROR` option on this socket.
408+
///
409+
/// This will retrieve the stored error in the underlying socket, clearing
410+
/// the field in the process. This can be useful for checking errors between
411+
/// calls.
412+
#[stable(feature = "net2_mutators", since = "1.9.0")]
413+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
414+
self.0.take_error()
415+
}
416+
417+
/// Moves this TCP stream into or out of nonblocking mode.
418+
///
419+
/// On Unix this corresponds to calling fcntl, and on Windows this
420+
/// corresponds to calling ioctlsocket.
421+
#[stable(feature = "net2_mutators", since = "1.9.0")]
422+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
423+
self.0.set_nonblocking(nonblocking)
424+
}
281425
}
282426

283427
#[stable(feature = "rust1", since = "1.0.0")]
@@ -969,4 +1113,55 @@ mod tests {
9691113
assert!(start.elapsed() > Duration::from_millis(400));
9701114
drop(listener);
9711115
}
1116+
1117+
#[test]
1118+
fn nodelay() {
1119+
let addr = next_test_ip4();
1120+
let _listener = t!(TcpListener::bind(&addr));
1121+
1122+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1123+
1124+
assert_eq!(false, t!(stream.nodelay()));
1125+
t!(stream.set_nodelay(true));
1126+
assert_eq!(true, t!(stream.nodelay()));
1127+
t!(stream.set_nodelay(false));
1128+
assert_eq!(false, t!(stream.nodelay()));
1129+
}
1130+
1131+
#[test]
1132+
fn ttl() {
1133+
let ttl = 100;
1134+
1135+
let addr = next_test_ip4();
1136+
let listener = t!(TcpListener::bind(&addr));
1137+
1138+
t!(listener.set_ttl(ttl));
1139+
assert_eq!(ttl, t!(listener.ttl()));
1140+
1141+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1142+
1143+
t!(stream.set_ttl(ttl));
1144+
assert_eq!(ttl, t!(stream.ttl()));
1145+
}
1146+
1147+
#[test]
1148+
fn set_nonblocking() {
1149+
let addr = next_test_ip4();
1150+
let listener = t!(TcpListener::bind(&addr));
1151+
1152+
t!(listener.set_nonblocking(true));
1153+
t!(listener.set_nonblocking(false));
1154+
1155+
let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
1156+
1157+
t!(stream.set_nonblocking(false));
1158+
t!(stream.set_nonblocking(true));
1159+
1160+
let mut buf = [0];
1161+
match stream.read(&mut buf) {
1162+
Ok(_) => panic!("expected error"),
1163+
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
1164+
Err(e) => panic!("unexpected error {}", e),
1165+
}
1166+
}
9721167
}

‎src/libstd/net/udp.rs

Lines changed: 252 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use fmt;
1212
use io::{self, Error, ErrorKind};
13-
use net::{ToSocketAddrs, SocketAddr};
13+
use net::{ToSocketAddrs, SocketAddr, Ipv4Addr, Ipv6Addr};
1414
use sys_common::net as net_imp;
1515
use sys_common::{AsInner, FromInner, IntoInner};
1616
use time::Duration;
@@ -140,6 +140,221 @@ impl UdpSocket {
140140
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
141141
self.0.write_timeout()
142142
}
143+
144+
/// Sets the value of the `SO_BROADCAST` option for this socket.
145+
///
146+
/// When enabled, this socket is allowed to send packets to a broadcast
147+
/// address.
148+
#[stable(feature = "net2_mutators", since = "1.9.0")]
149+
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
150+
self.0.set_broadcast(broadcast)
151+
}
152+
153+
/// Gets the value of the `SO_BROADCAST` option for this socket.
154+
///
155+
/// For more information about this option, see
156+
/// [`set_broadcast`][link].
157+
///
158+
/// [link]: #tymethod.set_broadcast
159+
#[stable(feature = "net2_mutators", since = "1.9.0")]
160+
pub fn broadcast(&self) -> io::Result<bool> {
161+
self.0.broadcast()
162+
}
163+
164+
/// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
165+
///
166+
/// If enabled, multicast packets will be looped back to the local socket.
167+
/// Note that this may not have any affect on IPv6 sockets.
168+
#[stable(feature = "net2_mutators", since = "1.9.0")]
169+
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
170+
self.0.set_multicast_loop_v4(multicast_loop_v4)
171+
}
172+
173+
/// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
174+
///
175+
/// For more information about this option, see
176+
/// [`set_multicast_loop_v4`][link].
177+
///
178+
/// [link]: #tymethod.set_multicast_loop_v4
179+
#[stable(feature = "net2_mutators", since = "1.9.0")]
180+
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
181+
self.0.multicast_loop_v4()
182+
}
183+
184+
/// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
185+
///
186+
/// Indicates the time-to-live value of outgoing multicast packets for
187+
/// this socket. The default value is 1 which means that multicast packets
188+
/// don't leave the local network unless explicitly requested.
189+
///
190+
/// Note that this may not have any affect on IPv6 sockets.
191+
#[stable(feature = "net2_mutators", since = "1.9.0")]
192+
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
193+
self.0.set_multicast_ttl_v4(multicast_ttl_v4)
194+
}
195+
196+
/// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
197+
///
198+
/// For more information about this option, see
199+
/// [`set_multicast_ttl_v4`][link].
200+
///
201+
/// [link]: #tymethod.set_multicast_ttl_v4
202+
#[stable(feature = "net2_mutators", since = "1.9.0")]
203+
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
204+
self.0.multicast_ttl_v4()
205+
}
206+
207+
/// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
208+
///
209+
/// Controls whether this socket sees the multicast packets it sends itself.
210+
/// Note that this may not have any affect on IPv4 sockets.
211+
#[stable(feature = "net2_mutators", since = "1.9.0")]
212+
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
213+
self.0.set_multicast_loop_v6(multicast_loop_v6)
214+
}
215+
216+
/// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
217+
///
218+
/// For more information about this option, see
219+
/// [`set_multicast_loop_v6`][link].
220+
///
221+
/// [link]: #tymethod.set_multicast_loop_v6
222+
#[stable(feature = "net2_mutators", since = "1.9.0")]
223+
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
224+
self.0.multicast_loop_v6()
225+
}
226+
227+
/// Sets the value for the `IP_TTL` option on this socket.
228+
///
229+
/// This value sets the time-to-live field that is used in every packet sent
230+
/// from this socket.
231+
#[stable(feature = "net2_mutators", since = "1.9.0")]
232+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
233+
self.0.set_ttl(ttl)
234+
}
235+
236+
/// Gets the value of the `IP_TTL` option for this socket.
237+
///
238+
/// For more information about this option, see [`set_ttl`][link].
239+
///
240+
/// [link]: #tymethod.set_ttl
241+
#[stable(feature = "net2_mutators", since = "1.9.0")]
242+
pub fn ttl(&self) -> io::Result<u32> {
243+
self.0.ttl()
244+
}
245+
246+
/// Sets the value for the `IPV6_V6ONLY` option on this socket.
247+
///
248+
/// If this is set to `true` then the socket is restricted to sending and
249+
/// receiving IPv6 packets only. If this is the case, an IPv4 and an IPv6
250+
/// application can each bind the same port at the same time.
251+
///
252+
/// If this is set to `false` then the socket can be used to send and
253+
/// receive packets from an IPv4-mapped IPv6 address.
254+
#[stable(feature = "net2_mutators", since = "1.9.0")]
255+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
256+
self.0.set_only_v6(only_v6)
257+
}
258+
259+
/// Gets the value of the `IPV6_V6ONLY` option for this socket.
260+
///
261+
/// For more information about this option, see [`set_only_v6`][link].
262+
///
263+
/// [link]: #tymethod.set_only_v6
264+
#[stable(feature = "net2_mutators", since = "1.9.0")]
265+
pub fn only_v6(&self) -> io::Result<bool> {
266+
self.0.only_v6()
267+
}
268+
269+
/// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
270+
///
271+
/// This function specifies a new multicast group for this socket to join.
272+
/// The address must be a valid multicast address, and `interface` is the
273+
/// address of the local interface with which the system should join the
274+
/// multicast group. If it's equal to `INADDR_ANY` then an appropriate
275+
/// interface is chosen by the system.
276+
#[stable(feature = "net2_mutators", since = "1.9.0")]
277+
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
278+
self.0.join_multicast_v4(multiaddr, interface)
279+
}
280+
281+
/// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
282+
///
283+
/// This function specifies a new multicast group for this socket to join.
284+
/// The address must be a valid multicast address, and `interface` is the
285+
/// index of the interface to join/leave (or 0 to indicate any interface).
286+
#[stable(feature = "net2_mutators", since = "1.9.0")]
287+
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
288+
self.0.join_multicast_v6(multiaddr, interface)
289+
}
290+
291+
/// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
292+
///
293+
/// For more information about this option, see
294+
/// [`join_multicast_v4`][link].
295+
///
296+
/// [link]: #tymethod.join_multicast_v4
297+
#[stable(feature = "net2_mutators", since = "1.9.0")]
298+
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
299+
self.0.leave_multicast_v4(multiaddr, interface)
300+
}
301+
302+
/// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
303+
///
304+
/// For more information about this option, see
305+
/// [`join_multicast_v6`][link].
306+
///
307+
/// [link]: #tymethod.join_multicast_v6
308+
#[stable(feature = "net2_mutators", since = "1.9.0")]
309+
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
310+
self.0.leave_multicast_v6(multiaddr, interface)
311+
}
312+
313+
/// Get the value of the `SO_ERROR` option on this socket.
314+
///
315+
/// This will retrieve the stored error in the underlying socket, clearing
316+
/// the field in the process. This can be useful for checking errors between
317+
/// calls.
318+
#[stable(feature = "net2_mutators", since = "1.9.0")]
319+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
320+
self.0.take_error()
321+
}
322+
323+
/// Connects this UDP socket to a remote address, allowing the `send` and
324+
/// `recv` syscalls to be used to send data and also applies filters to only
325+
/// receive data from the specified address.
326+
#[stable(feature = "net2_mutators", since = "1.9.0")]
327+
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
328+
super::each_addr(addr, |addr| self.0.connect(addr))
329+
}
330+
331+
/// Sends data on the socket to the remote address to which it is connected.
332+
///
333+
/// The `connect` method will connect this socket to a remote address. This
334+
/// method will fail if the socket is not connected.
335+
#[stable(feature = "net2_mutators", since = "1.9.0")]
336+
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
337+
self.0.send(buf)
338+
}
339+
340+
/// Receives data on the socket from the remote address to which it is
341+
/// connected.
342+
///
343+
/// The `connect` method will connect this socket to a remote address. This
344+
/// method will fail if the socket is not connected.
345+
#[stable(feature = "net2_mutators", since = "1.9.0")]
346+
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
347+
self.0.recv(buf)
348+
}
349+
350+
/// Moves this TCP stream into or out of nonblocking mode.
351+
///
352+
/// On Unix this corresponds to calling fcntl, and on Windows this
353+
/// corresponds to calling ioctlsocket.
354+
#[stable(feature = "net2_mutators", since = "1.9.0")]
355+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
356+
self.0.set_nonblocking(nonblocking)
357+
}
143358
}
144359

145360
impl AsInner<net_imp::UdpSocket> for UdpSocket {
@@ -400,4 +615,40 @@ mod tests {
400615
assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
401616
assert!(start.elapsed() > Duration::from_millis(400));
402617
}
618+
619+
#[test]
620+
fn connect_send_recv() {
621+
let addr = next_test_ip4();
622+
623+
let socket = t!(UdpSocket::bind(&addr));
624+
t!(socket.connect(addr));
625+
626+
t!(socket.send(b"hello world"));
627+
628+
let mut buf = [0; 11];
629+
t!(socket.recv(&mut buf));
630+
assert_eq!(b"hello world", &buf[..]);
631+
}
632+
633+
#[test]
634+
fn ttl() {
635+
let ttl = 100;
636+
637+
let addr = next_test_ip4();
638+
639+
let stream = t!(UdpSocket::bind(&addr));
640+
641+
t!(stream.set_ttl(ttl));
642+
assert_eq!(ttl, t!(stream.ttl()));
643+
}
644+
645+
#[test]
646+
fn set_nonblocking() {
647+
let addr = next_test_ip4();
648+
649+
let stream = t!(UdpSocket::bind(&addr));
650+
651+
t!(stream.set_nonblocking(true));
652+
t!(stream.set_nonblocking(false));
653+
}
403654
}

‎src/libstd/sys/common/net.rs

Lines changed: 221 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,31 @@ use io::{self, Error, ErrorKind};
1717
use libc::{c_int, c_char, c_void};
1818
use mem;
1919
#[allow(deprecated)]
20-
use net::{SocketAddr, Shutdown, IpAddr};
20+
use net::{SocketAddr, Shutdown, IpAddr, Ipv4Addr, Ipv6Addr};
2121
use ptr;
2222
use str::from_utf8;
2323
use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
2424
use sys::net::netc as c;
2525
use sys_common::{AsInner, FromInner, IntoInner};
2626
use time::Duration;
2727

28+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
29+
target_os = "ios", target_os = "macos",
30+
target_os = "openbsd", target_os = "netbsd"))]
31+
use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
32+
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
33+
target_os = "ios", target_os = "macos",
34+
target_os = "openbsd", target_os = "netbsd")))]
35+
use sys::net::netc::IPV6_ADD_MEMBERSHIP;
36+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
37+
target_os = "ios", target_os = "macos",
38+
target_os = "openbsd", target_os = "netbsd"))]
39+
use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
40+
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
41+
target_os = "ios", target_os = "macos",
42+
target_os = "openbsd", target_os = "netbsd")))]
43+
use sys::net::netc::IPV6_DROP_MEMBERSHIP;
44+
2845
////////////////////////////////////////////////////////////////////////////////
2946
// sockaddr and misc bindings
3047
////////////////////////////////////////////////////////////////////////////////
@@ -84,6 +101,16 @@ fn sockaddr_to_addr(storage: &c::sockaddr_storage,
84101
}
85102
}
86103

104+
#[cfg(target_os = "android")]
105+
fn to_ipv6mr_interface(value: u32) -> c_int {
106+
value as c_int
107+
}
108+
109+
#[cfg(not(target_os = "android"))]
110+
fn to_ipv6mr_interface(value: u32) -> ::libc::c_uint {
111+
value as ::libc::c_uint
112+
}
113+
87114
////////////////////////////////////////////////////////////////////////////////
88115
// get_host_addresses
89116
////////////////////////////////////////////////////////////////////////////////
@@ -228,6 +255,45 @@ impl TcpStream {
228255
pub fn duplicate(&self) -> io::Result<TcpStream> {
229256
self.inner.duplicate().map(|s| TcpStream { inner: s })
230257
}
258+
259+
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
260+
self.inner.set_nodelay(nodelay)
261+
}
262+
263+
pub fn nodelay(&self) -> io::Result<bool> {
264+
self.inner.nodelay()
265+
}
266+
267+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
268+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
269+
}
270+
271+
pub fn ttl(&self) -> io::Result<u32> {
272+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL));
273+
Ok(raw as u32)
274+
}
275+
276+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
277+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
278+
}
279+
280+
pub fn only_v6(&self) -> io::Result<bool> {
281+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
282+
Ok(raw != 0)
283+
}
284+
285+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
286+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR));
287+
if raw == 0 {
288+
Ok(None)
289+
} else {
290+
Ok(Some(io::Error::from_raw_os_error(raw as i32)))
291+
}
292+
}
293+
294+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
295+
self.inner.set_nonblocking(nonblocking)
296+
}
231297
}
232298

233299
impl FromInner<Socket> for TcpStream {
@@ -307,6 +373,37 @@ impl TcpListener {
307373
pub fn duplicate(&self) -> io::Result<TcpListener> {
308374
self.inner.duplicate().map(|s| TcpListener { inner: s })
309375
}
376+
377+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
378+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
379+
}
380+
381+
pub fn ttl(&self) -> io::Result<u32> {
382+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL));
383+
Ok(raw as u32)
384+
}
385+
386+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
387+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
388+
}
389+
390+
pub fn only_v6(&self) -> io::Result<bool> {
391+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
392+
Ok(raw != 0)
393+
}
394+
395+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
396+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR));
397+
if raw == 0 {
398+
Ok(None)
399+
} else {
400+
Ok(Some(io::Error::from_raw_os_error(raw as i32)))
401+
}
402+
}
403+
404+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
405+
self.inner.set_nonblocking(nonblocking)
406+
}
310407
}
311408

312409
impl FromInner<Socket> for TcpListener {
@@ -401,6 +498,129 @@ impl UdpSocket {
401498
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
402499
self.inner.timeout(c::SO_SNDTIMEO)
403500
}
501+
502+
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
503+
setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
504+
}
505+
506+
pub fn broadcast(&self) -> io::Result<bool> {
507+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST));
508+
Ok(raw != 0)
509+
}
510+
511+
pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
512+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP, multicast_loop_v4 as c_int)
513+
}
514+
515+
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
516+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP));
517+
Ok(raw != 0)
518+
}
519+
520+
pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
521+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, multicast_ttl_v4 as c_int)
522+
}
523+
524+
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
525+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL));
526+
Ok(raw as u32)
527+
}
528+
529+
pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
530+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
531+
}
532+
533+
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
534+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP));
535+
Ok(raw != 0)
536+
}
537+
538+
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
539+
-> io::Result<()> {
540+
let mreq = c::ip_mreq {
541+
imr_multiaddr: *multiaddr.as_inner(),
542+
imr_interface: *interface.as_inner(),
543+
};
544+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
545+
}
546+
547+
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
548+
-> io::Result<()> {
549+
let mreq = c::ipv6_mreq {
550+
ipv6mr_multiaddr: *multiaddr.as_inner(),
551+
ipv6mr_interface: to_ipv6mr_interface(interface),
552+
};
553+
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
554+
}
555+
556+
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
557+
-> io::Result<()> {
558+
let mreq = c::ip_mreq {
559+
imr_multiaddr: *multiaddr.as_inner(),
560+
imr_interface: *interface.as_inner(),
561+
};
562+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
563+
}
564+
565+
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
566+
-> io::Result<()> {
567+
let mreq = c::ipv6_mreq {
568+
ipv6mr_multiaddr: *multiaddr.as_inner(),
569+
ipv6mr_interface: to_ipv6mr_interface(interface),
570+
};
571+
setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
572+
}
573+
574+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
575+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
576+
}
577+
578+
pub fn ttl(&self) -> io::Result<u32> {
579+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL));
580+
Ok(raw as u32)
581+
}
582+
583+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
584+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
585+
}
586+
587+
pub fn only_v6(&self) -> io::Result<bool> {
588+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
589+
Ok(raw != 0)
590+
}
591+
592+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
593+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR));
594+
if raw == 0 {
595+
Ok(None)
596+
} else {
597+
Ok(Some(io::Error::from_raw_os_error(raw as i32)))
598+
}
599+
}
600+
601+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
602+
self.inner.set_nonblocking(nonblocking)
603+
}
604+
605+
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
606+
self.inner.read(buf)
607+
}
608+
609+
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
610+
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
611+
let ret = try!(cvt(unsafe {
612+
c::send(*self.inner.as_inner(),
613+
buf.as_ptr() as *const c_void,
614+
len,
615+
0)
616+
}));
617+
Ok(ret as usize)
618+
}
619+
620+
pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
621+
let (addrp, len) = addr.into_inner();
622+
cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(|_| ())
623+
}
404624
}
405625

406626
impl FromInner<Socket> for UdpSocket {

‎src/libstd/sys/unix/net.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,20 @@ impl Socket {
168168
try!(cvt(unsafe { libc::shutdown(self.0.raw(), how) }));
169169
Ok(())
170170
}
171+
172+
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
173+
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
174+
}
175+
176+
pub fn nodelay(&self) -> io::Result<bool> {
177+
let raw: c_int = try!(getsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY));
178+
Ok(raw != 0)
179+
}
180+
181+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
182+
let mut nonblocking = nonblocking as libc::c_ulong;
183+
cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(|_| ())
184+
}
171185
}
172186

173187
impl AsInner<c_int> for Socket {

‎src/libstd/sys/windows/c.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#![allow(bad_style)]
1414
#![cfg_attr(test, allow(dead_code))]
1515

16-
use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort};
16+
use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort,};
1717
use os::raw::{c_char, c_ulonglong};
1818
use libc::{wchar_t, size_t, c_void};
1919
use ptr;
@@ -114,6 +114,8 @@ pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
114114
pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
115115
pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
116116

117+
pub const FIONBIO: c_ulong = 0x8004667e;
118+
117119
#[repr(C)]
118120
#[derive(Copy)]
119121
pub struct WIN32_FIND_DATAW {
@@ -223,6 +225,33 @@ pub const SOL_SOCKET: c_int = 0xffff;
223225
pub const SO_RCVTIMEO: c_int = 0x1006;
224226
pub const SO_SNDTIMEO: c_int = 0x1005;
225227
pub const SO_REUSEADDR: c_int = 0x0004;
228+
pub const IPPROTO_IP: c_int = 0;
229+
pub const IPPROTO_TCP: c_int = 6;
230+
pub const IPPROTO_IPV6: c_int = 41;
231+
pub const TCP_NODELAY: c_int = 0x0001;
232+
pub const IP_TTL: c_int = 4;
233+
pub const IPV6_V6ONLY: c_int = 27;
234+
pub const SO_ERROR: c_int = 0x1007;
235+
pub const SO_BROADCAST: c_int = 0x0020;
236+
pub const IP_MULTICAST_LOOP: c_int = 11;
237+
pub const IPV6_MULTICAST_LOOP: c_int = 11;
238+
pub const IP_MULTICAST_TTL: c_int = 10;
239+
pub const IP_ADD_MEMBERSHIP: c_int = 12;
240+
pub const IP_DROP_MEMBERSHIP: c_int = 13;
241+
pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
242+
pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
243+
244+
#[repr(C)]
245+
pub struct ip_mreq {
246+
pub imr_multiaddr: in_addr,
247+
pub imr_interface: in_addr,
248+
}
249+
250+
#[repr(C)]
251+
pub struct ipv6_mreq {
252+
pub ipv6mr_multiaddr: in6_addr,
253+
pub ipv6mr_interface: c_uint,
254+
}
226255

227256
pub const VOLUME_NAME_DOS: DWORD = 0x0;
228257
pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1;
@@ -833,6 +862,7 @@ extern "system" {
833862
lpProtocolInfo: LPWSAPROTOCOL_INFO,
834863
g: GROUP,
835864
dwFlags: DWORD) -> SOCKET;
865+
pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int;
836866
pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
837867
pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
838868
pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN;

‎src/libstd/sys/windows/net.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use cmp;
1212
use io;
13-
use libc::{c_int, c_void};
13+
use libc::{c_int, c_void, c_ulong};
1414
use mem;
1515
use net::{SocketAddr, Shutdown};
1616
use num::One;
@@ -185,6 +185,25 @@ impl Socket {
185185
try!(cvt(unsafe { c::shutdown(self.0, how) }));
186186
Ok(())
187187
}
188+
189+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
190+
let mut nonblocking = nonblocking as c_ulong;
191+
let r = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
192+
if r == 0 {
193+
Ok(())
194+
} else {
195+
Err(io::Error::last_os_error())
196+
}
197+
}
198+
199+
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
200+
net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
201+
}
202+
203+
pub fn nodelay(&self) -> io::Result<bool> {
204+
let raw: c::BYTE = try!(net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY));
205+
Ok(raw != 0)
206+
}
188207
}
189208

190209
impl Drop for Socket {

0 commit comments

Comments
 (0)
Please sign in to comment.