Skip to content

Commit 827be2d

Browse files
committed
Add TCP functionality from net2
1 parent c5237b0 commit 827be2d

File tree

5 files changed

+440
-0
lines changed

5 files changed

+440
-0
lines changed

src/libstd/net/tcp.rs

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,117 @@ 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 whether keepalive messages are enabled to be sent on this socket.
207+
///
208+
/// On Unix, this option will set the `SO_KEEPALIVE` as well as the
209+
/// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
210+
/// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
211+
///
212+
/// If `None` is specified then keepalive messages are disabled, otherwise
213+
/// the duration specified will be the time to remain idle before sending a
214+
/// TCP keepalive probe.
215+
///
216+
/// Some platforms specify this value in seconds, so sub-second
217+
/// specifications may be omitted.
218+
#[stable(feature = "net2_mutators", since = "1.9.0")]
219+
pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
220+
self.0.set_keepalive(keepalive)
221+
}
222+
223+
/// Returns whether keepalive messages are enabled on this socket, and if so
224+
/// the duration of time between them.
225+
///
226+
/// For more information about this option, see [`set_keepalive`][link].
227+
///
228+
/// [link]: #tymethod.set_keepalive
229+
#[stable(feature = "net2_mutators", since = "1.9.0")]
230+
pub fn keepalive(&self) -> io::Result<Option<Duration>> {
231+
self.0.keepalive()
232+
}
233+
234+
/// Sets the value for the `IP_TTL` option on this socket.
235+
///
236+
/// This value sets the time-to-live field that is used in every packet sent
237+
/// from this socket.
238+
#[stable(feature = "net2_mutators", since = "1.9.0")]
239+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
240+
self.0.set_ttl(ttl)
241+
}
242+
243+
/// Gets the value of the `IP_TTL` option for this socket.
244+
///
245+
/// For more information about this option, see [`set_ttl`][link].
246+
///
247+
/// [link]: #tymethod.set_ttl
248+
#[stable(feature = "net2_mutators", since = "1.9.0")]
249+
pub fn ttl(&self) -> io::Result<u32> {
250+
self.0.ttl()
251+
}
252+
253+
/// Sets the value for the `IPV6_V6ONLY` option on this socket.
254+
///
255+
/// If this is set to `true` then the socket is restricted to sending and
256+
/// receiving IPv6 packets only. If this is the case, an IPv4 and an IPv6
257+
/// application can each bind the same port at the same time.
258+
///
259+
/// If this is set to `false` then the socket can be used to send and
260+
/// receive packets from an IPv4-mapped IPv6 address.
261+
#[stable(feature = "net2_mutators", since = "1.9.0")]
262+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
263+
self.0.set_only_v6(only_v6)
264+
}
265+
266+
/// Gets the value of the `IPV6_V6ONLY` option for this socket.
267+
///
268+
/// For more information about this option, see [`set_only_v6`][link].
269+
///
270+
/// [link]: #tymethod.set_only_v6
271+
#[stable(feature = "net2_mutators", since = "1.9.0")]
272+
pub fn only_v6(&self) -> io::Result<bool> {
273+
self.0.only_v6()
274+
}
275+
276+
/// Get the value of the `SO_ERROR` option on this socket.
277+
///
278+
/// This will retrieve the stored error in the underlying socket, clearing
279+
/// the field in the process. This can be useful for checking errors between
280+
/// calls.
281+
#[stable(feature = "net2_mutators", since = "1.9.0")]
282+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
283+
self.0.take_error()
284+
}
285+
286+
/// Moves this TCP stream into or out of nonblocking mode.
287+
///
288+
/// On Unix this corresponds to calling fcntl, and on Windows this
289+
/// corresponds to calling ioctlsocket.
290+
#[stable(feature = "net2_mutators", since = "1.9.0")]
291+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
292+
self.0.set_nonblocking(nonblocking)
293+
}
183294
}
184295

185296
#[stable(feature = "rust1", since = "1.0.0")]
@@ -278,6 +389,67 @@ impl TcpListener {
278389
pub fn incoming(&self) -> Incoming {
279390
Incoming { listener: self }
280391
}
392+
393+
/// Sets the value for the `IP_TTL` option on this socket.
394+
///
395+
/// This value sets the time-to-live field that is used in every packet sent
396+
/// from this socket.
397+
#[stable(feature = "net2_mutators", since = "1.9.0")]
398+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
399+
self.0.set_ttl(ttl)
400+
}
401+
402+
/// Gets the value of the `IP_TTL` option for this socket.
403+
///
404+
/// For more information about this option, see [`set_ttl`][link].
405+
///
406+
/// [link]: #tymethod.set_ttl
407+
#[stable(feature = "net2_mutators", since = "1.9.0")]
408+
pub fn ttl(&self) -> io::Result<u32> {
409+
self.0.ttl()
410+
}
411+
412+
/// Sets the value for the `IPV6_V6ONLY` option on this socket.
413+
///
414+
/// If this is set to `true` then the socket is restricted to sending and
415+
/// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
416+
/// can bind the same port at the same time.
417+
///
418+
/// If this is set to `false` then the socket can be used to send and
419+
/// receive packets from an IPv4-mapped IPv6 address.
420+
#[stable(feature = "net2_mutators", since = "1.9.0")]
421+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
422+
self.0.set_only_v6(only_v6)
423+
}
424+
425+
/// Gets the value of the `IPV6_V6ONLY` option for this socket.
426+
///
427+
/// For more information about this option, see [`set_only_v6`][link].
428+
///
429+
/// [link]: #tymethod.set_only_v6
430+
#[stable(feature = "net2_mutators", since = "1.9.0")]
431+
pub fn only_v6(&self) -> io::Result<bool> {
432+
self.0.only_v6()
433+
}
434+
435+
/// Get the value of the `SO_ERROR` option on this socket.
436+
///
437+
/// This will retrieve the stored error in the underlying socket, clearing
438+
/// the field in the process. This can be useful for checking errors between
439+
/// calls.
440+
#[stable(feature = "net2_mutators", since = "1.9.0")]
441+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
442+
self.0.take_error()
443+
}
444+
445+
/// Moves this TCP stream into or out of nonblocking mode.
446+
///
447+
/// On Unix this corresponds to calling fcntl, and on Windows this
448+
/// corresponds to calling ioctlsocket.
449+
#[stable(feature = "net2_mutators", since = "1.9.0")]
450+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
451+
self.0.set_nonblocking(nonblocking)
452+
}
281453
}
282454

283455
#[stable(feature = "rust1", since = "1.0.0")]
@@ -969,4 +1141,63 @@ mod tests {
9691141
assert!(start.elapsed() > Duration::from_millis(400));
9701142
drop(listener);
9711143
}
1144+
1145+
#[test]
1146+
fn nodelay() {
1147+
let addr = next_test_ip4();
1148+
let _listener = t!(TcpListener::bind(&addr));
1149+
1150+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1151+
1152+
assert_eq!(false, t!(stream.nodelay()));
1153+
t!(stream.set_nodelay(true));
1154+
assert_eq!(true, t!(stream.nodelay()));
1155+
t!(stream.set_nodelay(false));
1156+
assert_eq!(false, t!(stream.nodelay()));
1157+
}
1158+
1159+
#[test]
1160+
fn keepalive() {
1161+
let addr = next_test_ip4();
1162+
let _listener = t!(TcpListener::bind(&addr));
1163+
1164+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1165+
let dur = Duration::new(15410, 0);
1166+
1167+
assert_eq!(None, t!(stream.keepalive()));
1168+
t!(stream.set_keepalive(Some(dur)));
1169+
assert_eq!(Some(dur), t!(stream.keepalive()));
1170+
t!(stream.set_keepalive(None));
1171+
assert_eq!(None, t!(stream.keepalive()));
1172+
}
1173+
1174+
#[test]
1175+
fn ttl() {
1176+
let ttl = 100;
1177+
1178+
let addr = next_test_ip4();
1179+
let listener = t!(TcpListener::bind(&addr));
1180+
1181+
t!(listener.set_ttl(ttl));
1182+
assert_eq!(ttl, t!(listener.ttl()));
1183+
1184+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1185+
1186+
t!(stream.set_ttl(ttl));
1187+
assert_eq!(ttl, t!(stream.ttl()));
1188+
}
1189+
1190+
#[test]
1191+
fn set_nonblocking() {
1192+
let addr = next_test_ip4();
1193+
let listener = t!(TcpListener::bind(&addr));
1194+
1195+
t!(listener.set_nonblocking(true));
1196+
t!(listener.set_nonblocking(false));
1197+
1198+
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1199+
1200+
t!(stream.set_nonblocking(true));
1201+
t!(stream.set_nonblocking(false));
1202+
}
9721203
}

src/libstd/sys/common/net.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,54 @@ impl TcpStream {
228228
pub fn duplicate(&self) -> io::Result<TcpStream> {
229229
self.inner.duplicate().map(|s| TcpStream { inner: s })
230230
}
231+
232+
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
233+
setsockopt(&self.inner, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c_int)
234+
}
235+
236+
pub fn nodelay(&self) -> io::Result<bool> {
237+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_TCP, c::TCP_NODELAY));
238+
Ok(raw != 0)
239+
}
240+
241+
pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
242+
self.inner.set_keepalive(keepalive)
243+
}
244+
245+
pub fn keepalive(&self) -> io::Result<Option<Duration>> {
246+
self.inner.keepalive()
247+
}
248+
249+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
250+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
251+
}
252+
253+
pub fn ttl(&self) -> io::Result<u32> {
254+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL));
255+
Ok(raw as u32)
256+
}
257+
258+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
259+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
260+
}
261+
262+
pub fn only_v6(&self) -> io::Result<bool> {
263+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
264+
Ok(raw != 0)
265+
}
266+
267+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
268+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR));
269+
if raw == 0 {
270+
Ok(None)
271+
} else {
272+
Ok(Some(io::Error::from_raw_os_error(raw as i32)))
273+
}
274+
}
275+
276+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
277+
self.inner.set_nonblocking(nonblocking)
278+
}
231279
}
232280

233281
impl FromInner<Socket> for TcpStream {
@@ -307,6 +355,37 @@ impl TcpListener {
307355
pub fn duplicate(&self) -> io::Result<TcpListener> {
308356
self.inner.duplicate().map(|s| TcpListener { inner: s })
309357
}
358+
359+
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
360+
setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
361+
}
362+
363+
pub fn ttl(&self) -> io::Result<u32> {
364+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL));
365+
Ok(raw as u32)
366+
}
367+
368+
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
369+
setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
370+
}
371+
372+
pub fn only_v6(&self) -> io::Result<bool> {
373+
let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
374+
Ok(raw != 0)
375+
}
376+
377+
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
378+
let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR));
379+
if raw == 0 {
380+
Ok(None)
381+
} else {
382+
Ok(Some(io::Error::from_raw_os_error(raw as i32)))
383+
}
384+
}
385+
386+
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
387+
self.inner.set_nonblocking(nonblocking)
388+
}
310389
}
311390

312391
impl FromInner<Socket> for TcpListener {

0 commit comments

Comments
 (0)