Skip to content

Commit

Permalink
add SockProtocol type for third argument of socket and socketpair
Browse files Browse the repository at this point in the history
  • Loading branch information
ndusart committed Jul 26, 2017
1 parent 64ae507 commit e7d4720
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
37 changes: 35 additions & 2 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ pub enum SockType {
Rdm = libc::SOCK_RDM,
}

/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
/// to specify the protocol to use.
#[repr(i32)]
pub enum SockProtocol {
/// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
Tcp = libc::IPPROTO_TCP,
/// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
Udp = libc::IPPROTO_UDP,
/// Allows applications and other KEXTs to be notified when certain kernel events occur
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
#[cfg(any(target_os = "ios", target_os = "macos"))]
KextEvent = SYSPROTO_EVENT,
/// Allows applications to configure and control a KEXT
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
#[cfg(any(target_os = "ios", target_os = "macos"))]
KextControl = SYSPROTO_CONTROL,
}

// Extra flags - Supported by Linux 2.6.27, normalized on other platforms
bitflags!(
pub struct SockFlag: c_int {
Expand Down Expand Up @@ -382,9 +400,20 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&

/// Create an endpoint for communication
///
/// The `protocol` specifies a particular protocol to be used with the
/// socket. Normally only a single protocol exists to support a
/// particular socket type within a given protocol family, in which case
/// protocol can be specified as `None`. However, it is possible that many
/// protocols may exist, in which case a particular protocol must be
/// specified in this manner.
///
/// [Further reading](http://man7.org/linux/man-pages/man2/socket.2.html)
pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_int) -> Result<RawFd> {
pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
let mut ty = ty as c_int;
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
};
let feat_atomic = features::socket_atomic_cloexec();

if feat_atomic {
Expand All @@ -410,9 +439,13 @@ pub fn socket(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: c_
/// Create a pair of connected sockets
///
/// [Further reading](http://man7.org/linux/man-pages/man2/socketpair.2.html)
pub fn socketpair(domain: AddressFamily, ty: SockType, protocol: c_int,
pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
flags: SockFlag) -> Result<(RawFd, RawFd)> {
let mut ty = ty as c_int;
let protocol = match protocol.into() {
None => 0,
Some(p) => p as c_int,
};
let feat_atomic = features::socket_atomic_cloexec();

if feat_atomic {
Expand Down
8 changes: 4 additions & 4 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ mod test {
fn can_get_peercred_on_unix_socket() {
use super::super::*;

let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap();
let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
assert_eq!(a_cred, b_cred);
Expand All @@ -391,7 +391,7 @@ mod test {
use super::super::*;
use ::unistd::close;

let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, 0, SockFlag::empty()).unwrap();
let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
let a_type = getsockopt(a, super::SockType).unwrap();
assert!(a_type == SockType::Stream);
close(a).unwrap();
Expand All @@ -403,7 +403,7 @@ mod test {
use super::super::*;
use ::unistd::close;

let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), 0).unwrap();
let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
let s_type = getsockopt(s, super::SockType).unwrap();
assert!(s_type == SockType::Datagram);
close(s).unwrap();
Expand All @@ -417,7 +417,7 @@ mod test {
use super::super::*;
use ::unistd::close;

let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), 0).unwrap();
let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
let s_listening = getsockopt(s, super::AcceptConn).unwrap();
assert!(!s_listening);
listen(s, 10).unwrap();
Expand Down
27 changes: 12 additions & 15 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ pub fn test_getsockname() {

let tempdir = TempDir::new("test_getsockname").unwrap();
let sockname = tempdir.path().join("sock");
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(),
0).expect("socket failed");
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
.expect("socket failed");
let sockaddr = SockAddr::new_unix(&sockname).unwrap();
bind(sock, &sockaddr).expect("bind failed");
assert_eq!(sockaddr.to_str(),
Expand All @@ -82,8 +82,7 @@ pub fn test_socketpair() {
use nix::unistd::{read, write};
use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};

let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
SockFlag::empty())
let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();
write(fd1, b"hello").unwrap();
let mut buf = [0;5];
Expand All @@ -101,8 +100,7 @@ pub fn test_scm_rights() {
ControlMessage, CmsgSpace, MsgFlags,
MSG_TRUNC, MSG_CTRUNC};

let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
SockFlag::empty())
let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();
let (r, w) = pipe().unwrap();
let mut received_r: Option<RawFd> = None;
Expand Down Expand Up @@ -158,8 +156,7 @@ pub fn test_sendmsg_empty_cmsgs() {
CmsgSpace, MsgFlags,
MSG_TRUNC, MSG_CTRUNC};

let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, 0,
SockFlag::empty())
let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
.unwrap();

{
Expand Down Expand Up @@ -194,14 +191,14 @@ pub fn test_unixdomain() {
let tempdir = TempDir::new("test_unixdomain").unwrap();
let sockname = tempdir.path().join("sock");
let s1 = socket(AddressFamily::Unix, SockType::Stream,
SockFlag::empty(), 0).expect("socket failed");
SockFlag::empty(), None).expect("socket failed");
let sockaddr = SockAddr::new_unix(&sockname).unwrap();
bind(s1, &sockaddr).expect("bind failed");
listen(s1, 10).expect("listen failed");

let thr = thread::spawn(move || {
let s2 = socket(AddressFamily::Unix, SockType::Stream,
SockFlag::empty(), 0).expect("socket failed");
let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
.expect("socket failed");
connect(s2, &sockaddr).expect("connect failed");
write(s2, b"hello").expect("write failed");
close(s2).unwrap();
Expand All @@ -223,11 +220,11 @@ pub fn test_unixdomain() {
#[test]
pub fn test_syscontrol() {
use nix::{Errno, Error};
use nix::sys::socket::{AddressFamily, SockType, SockFlag};
use nix::sys::socket::{socket, SockAddr};
use nix::sys::socket::SYSPROTO_CONTROL;
use nix::sys::socket::{AddressFamily, socket, SockAddr, SockType, SockFlag, SockProtocol};

let fd = socket(AddressFamily::System, SockType::Datagram, SockFlag::empty(), SYSPROTO_CONTROL).expect("socket failed");
let fd = socket(AddressFamily::System, SockType::Datagram,
SockFlag::empty(), SockProtocol::KextControl)
.expect("socket failed");
let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));

Expand Down
5 changes: 3 additions & 2 deletions test/sys/test_sockopt.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use rand::{thread_rng, Rng};
use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockLevel};
use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};

#[test]
fn test_so_buf() {
let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockLevel::Udp as i32).unwrap();
let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
.unwrap();
let bufsize: usize = thread_rng().gen_range(4096, 131072);
setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
Expand Down

0 comments on commit e7d4720

Please sign in to comment.