|
3 | 3 | //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
|
4 | 4 | use {Error, Errno, Result};
|
5 | 5 | use features;
|
6 |
| -use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; |
7 |
| -use fcntl::FcntlArg::{F_SETFD, F_SETFL}; |
8 | 6 | use libc::{self, c_void, c_int, socklen_t, size_t, pid_t, uid_t, gid_t};
|
9 | 7 | use std::{mem, ptr, slice};
|
10 | 8 | use std::os::unix::io::RawFd;
|
@@ -92,13 +90,46 @@ pub enum SockProtocol {
|
92 | 90 | KextControl = libc::SYSPROTO_CONTROL,
|
93 | 91 | }
|
94 | 92 |
|
95 |
| -bitflags!( |
96 |
| - /// Extra flags - Supported by Linux 2.6.27, normalized on other platforms |
| 93 | +// FIXME: Replace these two separate declarations with one once https://github.com/rust-lang-nursery/bitflags/issues/113 |
| 94 | +// is resolved. |
| 95 | +#[cfg(not(any(target_os = "mac", target_os = "ios")))] |
| 96 | +libc_bitflags!{ |
| 97 | + /// Additional socket options |
| 98 | + pub flags SockFlag: c_int { |
| 99 | + /// Set non-blocking mode on the new socket |
| 100 | + #[cfg(any(target_os = "android", |
| 101 | + target_os = "dragonfly", |
| 102 | + target_os = "freebsd", |
| 103 | + target_os = "linux", |
| 104 | + target_os = "netbsd", |
| 105 | + target_os = "openbsd"))] |
| 106 | + SOCK_NONBLOCK, |
| 107 | + /// Set close-on-exec on the new descriptor |
| 108 | + #[cfg(any(target_os = "android", |
| 109 | + target_os = "dragonfly", |
| 110 | + target_os = "freebsd", |
| 111 | + target_os = "linux", |
| 112 | + target_os = "netbsd", |
| 113 | + target_os = "openbsd"))] |
| 114 | + SOCK_CLOEXEC, |
| 115 | + /// Return `EPIPE` instead of raising `SIGPIPE` |
| 116 | + #[cfg(target_os = "netbsd")] |
| 117 | + SOCK_NOSIGPIPE, |
| 118 | + /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)` |
| 119 | + /// to the DNS port (typically 53) |
| 120 | + #[cfg(target_os = "openbsd")] |
| 121 | + SOCK_DNS, |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +#[cfg(any(target_os = "mac", target_os = "ios"))] |
| 126 | +bitflags!{ |
| 127 | + /// Additional socket options |
97 | 128 | pub struct SockFlag: c_int {
|
98 |
| - const SOCK_NONBLOCK = 0o0004000; |
99 |
| - const SOCK_CLOEXEC = 0o2000000; |
| 129 | + /// Empty placeholder |
| 130 | + const EMPTY = 0; |
100 | 131 | }
|
101 |
| -); |
| 132 | +} |
102 | 133 |
|
103 | 134 | libc_bitflags!{
|
104 | 135 | /// Flags for send/recv and their relatives
|
@@ -449,13 +480,24 @@ pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType
|
449 | 480 | // TODO: Check the kernel version
|
450 | 481 | let res = try!(Errno::result(unsafe { ffi::socket(domain as c_int, ty, protocol) }));
|
451 | 482 |
|
452 |
| - if !feat_atomic { |
453 |
| - if flags.contains(SOCK_CLOEXEC) { |
454 |
| - try!(fcntl(res, F_SETFD(FD_CLOEXEC))); |
455 |
| - } |
| 483 | + #[cfg(any(target_os = "android", |
| 484 | + target_os = "dragonfly", |
| 485 | + target_os = "freebsd", |
| 486 | + target_os = "linux", |
| 487 | + target_os = "netbsd", |
| 488 | + target_os = "openbsd"))] |
| 489 | + { |
| 490 | + use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; |
| 491 | + use fcntl::FcntlArg::{F_SETFD, F_SETFL}; |
456 | 492 |
|
457 |
| - if flags.contains(SOCK_NONBLOCK) { |
458 |
| - try!(fcntl(res, F_SETFL(O_NONBLOCK))); |
| 493 | + if !feat_atomic { |
| 494 | + if flags.contains(SOCK_CLOEXEC) { |
| 495 | + try!(fcntl(res, F_SETFD(FD_CLOEXEC))); |
| 496 | + } |
| 497 | + |
| 498 | + if flags.contains(SOCK_NONBLOCK) { |
| 499 | + try!(fcntl(res, F_SETFL(O_NONBLOCK))); |
| 500 | + } |
459 | 501 | }
|
460 | 502 | }
|
461 | 503 |
|
@@ -483,15 +525,26 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: Sock
|
483 | 525 | };
|
484 | 526 | try!(Errno::result(res));
|
485 | 527 |
|
486 |
| - if !feat_atomic { |
487 |
| - if flags.contains(SOCK_CLOEXEC) { |
488 |
| - try!(fcntl(fds[0], F_SETFD(FD_CLOEXEC))); |
489 |
| - try!(fcntl(fds[1], F_SETFD(FD_CLOEXEC))); |
490 |
| - } |
| 528 | + #[cfg(any(target_os = "android", |
| 529 | + target_os = "dragonfly", |
| 530 | + target_os = "freebsd", |
| 531 | + target_os = "linux", |
| 532 | + target_os = "netbsd", |
| 533 | + target_os = "openbsd"))] |
| 534 | + { |
| 535 | + use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; |
| 536 | + use fcntl::FcntlArg::{F_SETFD, F_SETFL}; |
491 | 537 |
|
492 |
| - if flags.contains(SOCK_NONBLOCK) { |
493 |
| - try!(fcntl(fds[0], F_SETFL(O_NONBLOCK))); |
494 |
| - try!(fcntl(fds[1], F_SETFL(O_NONBLOCK))); |
| 538 | + if !feat_atomic { |
| 539 | + if flags.contains(SOCK_CLOEXEC) { |
| 540 | + try!(fcntl(fds[0], F_SETFD(FD_CLOEXEC))); |
| 541 | + try!(fcntl(fds[1], F_SETFD(FD_CLOEXEC))); |
| 542 | + } |
| 543 | + |
| 544 | + if flags.contains(SOCK_NONBLOCK) { |
| 545 | + try!(fcntl(fds[0], F_SETFL(O_NONBLOCK))); |
| 546 | + try!(fcntl(fds[1], F_SETFL(O_NONBLOCK))); |
| 547 | + } |
495 | 548 | }
|
496 | 549 | }
|
497 | 550 | Ok((fds[0], fds[1]))
|
@@ -554,14 +607,37 @@ pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
|
554 | 607 | fn accept4_polyfill(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
|
555 | 608 | let res = try!(Errno::result(unsafe { ffi::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }));
|
556 | 609 |
|
557 |
| - if flags.contains(SOCK_CLOEXEC) { |
558 |
| - try!(fcntl(res, F_SETFD(FD_CLOEXEC))); |
| 610 | + #[cfg(any(target_os = "android", |
| 611 | + target_os = "dragonfly", |
| 612 | + target_os = "freebsd", |
| 613 | + target_os = "linux", |
| 614 | + target_os = "netbsd", |
| 615 | + target_os = "openbsd"))] |
| 616 | + { |
| 617 | + use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; |
| 618 | + use fcntl::FcntlArg::{F_SETFD, F_SETFL}; |
| 619 | + |
| 620 | + if flags.contains(SOCK_CLOEXEC) { |
| 621 | + try!(fcntl(res, F_SETFD(FD_CLOEXEC))); |
| 622 | + } |
| 623 | + |
| 624 | + if flags.contains(SOCK_NONBLOCK) { |
| 625 | + try!(fcntl(res, F_SETFL(O_NONBLOCK))); |
| 626 | + } |
559 | 627 | }
|
560 | 628 |
|
561 |
| - if flags.contains(SOCK_NONBLOCK) { |
562 |
| - try!(fcntl(res, F_SETFL(O_NONBLOCK))); |
| 629 | + // Disable unused variable warning on some platforms |
| 630 | + #[cfg(not(any(target_os = "android", |
| 631 | + target_os = "dragonfly", |
| 632 | + target_os = "freebsd", |
| 633 | + target_os = "linux", |
| 634 | + target_os = "netbsd", |
| 635 | + target_os = "openbsd")))] |
| 636 | + { |
| 637 | + let _ = flags; |
563 | 638 | }
|
564 | 639 |
|
| 640 | + |
565 | 641 | Ok(res)
|
566 | 642 | }
|
567 | 643 |
|
|
0 commit comments