Skip to content

Commit 979faf0

Browse files
committed
Improve ergonomics of getsockopt / setsockopt
1 parent 88988a3 commit 979faf0

File tree

3 files changed

+369
-125
lines changed

3 files changed

+369
-125
lines changed

src/sys/socket/consts.rs

Lines changed: 99 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -19,64 +19,62 @@ mod os {
1919
pub const SOCK_RAW: SockType = 3;
2020
pub const SOCK_RDM: SockType = 4;
2121

22-
pub type SockLevel = c_int;
23-
24-
pub const SOL_IP: SockLevel = 0;
25-
pub const IPPROTO_IP: SockLevel = SOL_IP;
26-
pub const SOL_SOCKET: SockLevel = 1;
27-
pub const SOL_TCP: SockLevel = 6;
28-
pub const IPPROTO_TCP: SockLevel = SOL_TCP;
29-
pub const SOL_UDP: SockLevel = 17;
30-
pub const SOL_IPV6: SockLevel = 41;
31-
32-
pub type SockOpt = c_int;
33-
34-
pub const SO_ACCEPTCONN: SockOpt = 30;
35-
pub const SO_BINDTODEVICE: SockOpt = 25;
36-
pub const SO_BROADCAST: SockOpt = 6;
37-
pub const SO_BSDCOMPAT: SockOpt = 14;
38-
pub const SO_DEBUG: SockOpt = 1;
39-
pub const SO_DOMAIN: SockOpt = 39;
40-
pub const SO_ERROR: SockOpt = 4;
41-
pub const SO_DONTROUTE: SockOpt = 5;
42-
pub const SO_KEEPALIVE: SockOpt = 9;
43-
pub const SO_LINGER: SockOpt = 13;
44-
pub const SO_MARK: SockOpt = 36;
45-
pub const SO_OOBINLINE: SockOpt = 10;
46-
pub const SO_PASSCRED: SockOpt = 16;
47-
pub const SO_PEEK_OFF: SockOpt = 42;
48-
pub const SO_PEERCRED: SockOpt = 17;
49-
pub const SO_PRIORITY: SockOpt = 12;
50-
pub const SO_PROTOCOL: SockOpt = 38;
51-
pub const SO_RCVBUF: SockOpt = 8;
52-
pub const SO_RCVBUFFORCE: SockOpt = 33;
53-
pub const SO_RCVLOWAT: SockOpt = 18;
54-
pub const SO_SNDLOWAT: SockOpt = 19;
55-
pub const SO_RCVTIMEO: SockOpt = 20;
56-
pub const SO_SNDTIMEO: SockOpt = 21;
57-
pub const SO_REUSEADDR: SockOpt = 2;
58-
pub const SO_REUSEPORT: SockOpt = 15;
59-
pub const SO_RXQ_OVFL: SockOpt = 40;
60-
pub const SO_SNDBUF: SockOpt = 7;
61-
pub const SO_SNDBUFFORCE: SockOpt = 32;
62-
pub const SO_TIMESTAMP: SockOpt = 29;
63-
pub const SO_TYPE: SockOpt = 3;
64-
pub const SO_BUSY_POLL: SockOpt = 46;
22+
pub const SOL_IP: c_int = 0;
23+
pub const SOL_SOCKET: c_int = 1;
24+
pub const SOL_TCP: c_int = 6;
25+
pub const SOL_UDP: c_int = 17;
26+
pub const SOL_IPV6: c_int = 41;
27+
pub const IPPROTO_IP: c_int = SOL_IP;
28+
pub const IPPROTO_IPV6: c_int = SOL_IPV6;
29+
pub const IPPROTO_TCP: c_int = SOL_TCP;
30+
pub const IPPROTO_UDP: c_int = SOL_UDP;
31+
32+
pub const SO_ACCEPTCONN: c_int = 30;
33+
pub const SO_BINDTODEVICE: c_int = 25;
34+
pub const SO_BROADCAST: c_int = 6;
35+
pub const SO_BSDCOMPAT: c_int = 14;
36+
pub const SO_DEBUG: c_int = 1;
37+
pub const SO_DOMAIN: c_int = 39;
38+
pub const SO_ERROR: c_int = 4;
39+
pub const SO_DONTROUTE: c_int = 5;
40+
pub const SO_KEEPALIVE: c_int = 9;
41+
pub const SO_LINGER: c_int = 13;
42+
pub const SO_MARK: c_int = 36;
43+
pub const SO_OOBINLINE: c_int = 10;
44+
pub const SO_PASSCRED: c_int = 16;
45+
pub const SO_PEEK_OFF: c_int = 42;
46+
pub const SO_PEERCRED: c_int = 17;
47+
pub const SO_PRIORITY: c_int = 12;
48+
pub const SO_PROTOCOL: c_int = 38;
49+
pub const SO_RCVBUF: c_int = 8;
50+
pub const SO_RCVBUFFORCE: c_int = 33;
51+
pub const SO_RCVLOWAT: c_int = 18;
52+
pub const SO_SNDLOWAT: c_int = 19;
53+
pub const SO_RCVTIMEO: c_int = 20;
54+
pub const SO_SNDTIMEO: c_int = 21;
55+
pub const SO_REUSEADDR: c_int = 2;
56+
pub const SO_REUSEPORT: c_int = 15;
57+
pub const SO_RXQ_OVFL: c_int = 40;
58+
pub const SO_SNDBUF: c_int = 7;
59+
pub const SO_SNDBUFFORCE: c_int = 32;
60+
pub const SO_TIMESTAMP: c_int = 29;
61+
pub const SO_TYPE: c_int = 3;
62+
pub const SO_BUSY_POLL: c_int = 46;
6563

6664
// Socket options for TCP sockets
67-
pub const TCP_NODELAY: SockOpt = 1;
68-
pub const TCP_MAXSEG: SockOpt = 2;
69-
pub const TCP_CORK: SockOpt = 3;
65+
pub const TCP_NODELAY: c_int = 1;
66+
pub const TCP_MAXSEG: c_int = 2;
67+
pub const TCP_CORK: c_int = 3;
7068

7169
// Socket options for the IP layer of the socket
72-
pub const IP_MULTICAST_IF: SockOpt = 32;
70+
pub const IP_MULTICAST_IF: c_int = 32;
7371

7472
pub type IpMulticastTtl = uint8_t;
7573

76-
pub const IP_MULTICAST_TTL: SockOpt = 33;
77-
pub const IP_MULTICAST_LOOP: SockOpt = 34;
78-
pub const IP_ADD_MEMBERSHIP: SockOpt = 35;
79-
pub const IP_DROP_MEMBERSHIP: SockOpt = 36;
74+
pub const IP_MULTICAST_TTL: c_int = 33;
75+
pub const IP_MULTICAST_LOOP: c_int = 34;
76+
pub const IP_ADD_MEMBERSHIP: c_int = 35;
77+
pub const IP_DROP_MEMBERSHIP: c_int = 36;
8078

8179
pub type InAddrT = u32;
8280

@@ -111,67 +109,64 @@ mod os {
111109
pub const SOCK_RAW: SockType = 3;
112110
pub const SOCK_RDM: SockType = 4;
113111

114-
pub type SockLevel = c_int;
115-
116-
pub const SOL_SOCKET: SockLevel = 0xffff;
117-
pub const IPPROTO_IP: SockLevel = 0;
118-
pub const IPPROTO_TCP: SockLevel = 6;
119-
pub const IPPROTO_UDP: SockLevel = 17;
120-
121-
pub type SockOpt = c_int;
122-
123-
pub const SO_ACCEPTCONN: SockOpt = 0x0002;
124-
pub const SO_BROADCAST: SockOpt = 0x0020;
125-
pub const SO_DEBUG: SockOpt = 0x0001;
126-
pub const SO_DONTTRUNC: SockOpt = 0x2000;
127-
pub const SO_ERROR: SockOpt = 0x1007;
128-
pub const SO_DONTROUTE: SockOpt = 0x0010;
129-
pub const SO_KEEPALIVE: SockOpt = 0x0008;
130-
pub const SO_LABEL: SockOpt = 0x1010;
131-
pub const SO_LINGER: SockOpt = 0x0080;
132-
pub const SO_NREAD: SockOpt = 0x1020;
133-
pub const SO_NKE: SockOpt = 0x1021;
134-
pub const SO_NOSIGPIPE: SockOpt = 0x1022;
135-
pub const SO_NOADDRERR: SockOpt = 0x1023;
136-
pub const SO_NOTIFYCONFLICT: SockOpt = 0x1026;
137-
pub const SO_NP_EXTENSIONS: SockOpt = 0x1083;
138-
pub const SO_NWRITE: SockOpt = 0x1024;
139-
pub const SO_OOBINLINE: SockOpt = 0x0100;
140-
pub const SO_PEERLABEL: SockOpt = 0x1011;
141-
pub const SO_RCVBUF: SockOpt = 0x1002;
142-
pub const SO_RCVLOWAT: SockOpt = 0x1004;
143-
pub const SO_SNDLOWAT: SockOpt = 0x1003;
144-
pub const SO_RCVTIMEO: SockOpt = 0x1006;
145-
pub const SO_SNDTIMEO: SockOpt = 0x1005;
146-
pub const SO_RANDOMPORT: SockOpt = 0x1082;
147-
pub const SO_RESTRICTIONS: SockOpt = 0x1081;
148-
pub const SO_RESTRICT_DENYIN: SockOpt = 0x00000001;
149-
pub const SO_RESTRICT_DENYOUT: SockOpt = 0x00000002;
150-
pub const SO_REUSEADDR: SockOpt = 0x0004;
151-
pub const SO_REUSEPORT: SockOpt = 0x0200;
152-
pub const SO_REUSESHAREUID: SockOpt = 0x1025;
153-
pub const SO_SNDBUF: SockOpt = 0x1001;
154-
pub const SO_TIMESTAMP: SockOpt = 0x0400;
155-
pub const SO_TIMESTAMP_MONOTONIC: SockOpt = 0x0800;
156-
pub const SO_TYPE: SockOpt = 0x1008;
157-
pub const SO_WANTMORE: SockOpt = 0x4000;
158-
pub const SO_WANTOOBFLAG: SockOpt = 0x8000;
112+
pub const SOL_SOCKET: c_int = 0xffff;
113+
pub const IPPROTO_IP: c_int = 0;
114+
pub const IPPROTO_IPV6: c_int = 41;
115+
pub const IPPROTO_TCP: c_int = 6;
116+
pub const IPPROTO_UDP: c_int = 17;
117+
118+
pub const SO_ACCEPTCONN: c_int = 0x0002;
119+
pub const SO_BROADCAST: c_int = 0x0020;
120+
pub const SO_DEBUG: c_int = 0x0001;
121+
pub const SO_DONTTRUNC: c_int = 0x2000;
122+
pub const SO_ERROR: c_int = 0x1007;
123+
pub const SO_DONTROUTE: c_int = 0x0010;
124+
pub const SO_KEEPALIVE: c_int = 0x0008;
125+
pub const SO_LABEL: c_int = 0x1010;
126+
pub const SO_LINGER: c_int = 0x0080;
127+
pub const SO_NREAD: c_int = 0x1020;
128+
pub const SO_NKE: c_int = 0x1021;
129+
pub const SO_NOSIGPIPE: c_int = 0x1022;
130+
pub const SO_NOADDRERR: c_int = 0x1023;
131+
pub const SO_NOTIFYCONFLICT: c_int = 0x1026;
132+
pub const SO_NP_EXTENSIONS: c_int = 0x1083;
133+
pub const SO_NWRITE: c_int = 0x1024;
134+
pub const SO_OOBINLINE: c_int = 0x0100;
135+
pub const SO_PEERLABEL: c_int = 0x1011;
136+
pub const SO_RCVBUF: c_int = 0x1002;
137+
pub const SO_RCVLOWAT: c_int = 0x1004;
138+
pub const SO_SNDLOWAT: c_int = 0x1003;
139+
pub const SO_RCVTIMEO: c_int = 0x1006;
140+
pub const SO_SNDTIMEO: c_int = 0x1005;
141+
pub const SO_RANDOMPORT: c_int = 0x1082;
142+
pub const SO_RESTRICTIONS: c_int = 0x1081;
143+
pub const SO_RESTRICT_DENYIN: c_int = 0x00000001;
144+
pub const SO_RESTRICT_DENYOUT: c_int = 0x00000002;
145+
pub const SO_REUSEADDR: c_int = 0x0004;
146+
pub const SO_REUSEPORT: c_int = 0x0200;
147+
pub const SO_REUSESHAREUID: c_int = 0x1025;
148+
pub const SO_SNDBUF: c_int = 0x1001;
149+
pub const SO_TIMESTAMP: c_int = 0x0400;
150+
pub const SO_TIMESTAMP_MONOTONIC: c_int = 0x0800;
151+
pub const SO_TYPE: c_int = 0x1008;
152+
pub const SO_WANTMORE: c_int = 0x4000;
153+
pub const SO_WANTOOBFLAG: c_int = 0x8000;
159154
#[allow(overflowing_literals)]
160-
pub const SO_RESTRICT_DENYSET: SockOpt = 0x80000000;
155+
pub const SO_RESTRICT_DENYSET: c_int = 0x80000000;
161156

162157
// Socket options for TCP sockets
163-
pub const TCP_NODELAY: SockOpt = 1;
164-
pub const TCP_MAXSEG: SockOpt = 2;
158+
pub const TCP_NODELAY: c_int = 1;
159+
pub const TCP_MAXSEG: c_int = 2;
165160

166161
// Socket options for the IP layer of the socket
167-
pub const IP_MULTICAST_IF: SockOpt = 9;
162+
pub const IP_MULTICAST_IF: c_int = 9;
168163

169164
pub type IpMulticastTtl = uint8_t;
170165

171-
pub const IP_MULTICAST_TTL: SockOpt = 10;
172-
pub const IP_MULTICAST_LOOP: SockOpt = 11;
173-
pub const IP_ADD_MEMBERSHIP: SockOpt = 12;
174-
pub const IP_DROP_MEMBERSHIP: SockOpt = 13;
166+
pub const IP_MULTICAST_TTL: c_int = 10;
167+
pub const IP_MULTICAST_LOOP: c_int = 11;
168+
pub const IP_ADD_MEMBERSHIP: c_int = 12;
169+
pub const IP_DROP_MEMBERSHIP: c_int = 13;
175170

176171
pub type InAddrT = u32;
177172

src/sys/socket/mod.rs

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::os::unix::prelude::*;
1010
mod addr;
1111
mod consts;
1212
mod ffi;
13+
pub mod sockopt;
1314

1415
/*
1516
*
@@ -264,34 +265,62 @@ pub struct linger {
264265
pub l_linger: c_int
265266
}
266267

267-
pub fn getsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &mut T) -> NixResult<usize> {
268-
let mut len = mem::size_of::<T>() as socklen_t;
268+
/*
269+
*
270+
* ===== Socket Options =====
271+
*
272+
*/
269273

270-
let res = unsafe {
271-
ffi::getsockopt(
272-
fd, level, opt,
273-
mem::transmute(val),
274-
&mut len as *mut socklen_t)
275-
};
274+
/// Represents a socket option that can be accessed or set
275+
pub trait SockOpt : Copy + fmt::Debug {
276+
/// Type of `getsockopt` return value
277+
type Get;
276278

277-
if res < 0 {
278-
return Err(NixError::Sys(Errno::last()));
279-
}
279+
/// Type of value used to set the socket option. Used as the argument to
280+
/// `setsockopt`.
281+
type Set;
280282

281-
Ok(len as usize)
283+
#[doc(hidden)]
284+
fn get(&self, fd: Fd, level: c_int) -> NixResult<Self::Get>;
285+
286+
#[doc(hidden)]
287+
fn set(&self, fd: Fd, level: c_int, val: Self::Set) -> NixResult<()>;
282288
}
283289

284-
pub fn setsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &T) -> NixResult<()> {
285-
let len = mem::size_of::<T>() as socklen_t;
290+
pub enum SockLevel {
291+
Socket,
292+
Tcp,
293+
Ip,
294+
Ipv6,
295+
Udp
296+
}
286297

287-
let res = unsafe {
288-
ffi::setsockopt(
289-
fd, level, opt,
290-
mem::transmute(val),
291-
len)
292-
};
298+
impl SockLevel {
299+
fn as_cint(&self) -> c_int {
300+
use self::SockLevel::*;
293301

294-
from_ffi(res)
302+
match *self {
303+
Socket => consts::SOL_SOCKET,
304+
Tcp => consts::IPPROTO_TCP,
305+
Ip => consts::IPPROTO_IP,
306+
Ipv6 => consts::IPPROTO_IPV6,
307+
Udp => consts::IPPROTO_UDP,
308+
}
309+
}
310+
}
311+
312+
/// Get the current value for the requested socket option
313+
///
314+
/// [Further reading](http://man7.org/linux/man-pages/man2/setsockopt.2.html)
315+
pub fn getsockopt<O: SockOpt>(fd: Fd, level: SockLevel, opt: O) -> NixResult<O::Get> {
316+
opt.get(fd, level.as_cint())
317+
}
318+
319+
/// Sets the value for the requested socket option
320+
///
321+
/// [Further reading](http://man7.org/linux/man-pages/man2/setsockopt.2.html)
322+
pub fn setsockopt<O: SockOpt>(fd: Fd, level: SockLevel, opt: O, val: O::Set) -> NixResult<()> {
323+
opt.set(fd, level.as_cint(), val)
295324
}
296325

297326
fn getpeername_sockaddr<T>(sockfd: Fd, addr: &T) -> NixResult<bool> {

0 commit comments

Comments
 (0)