1
1
use { Result , Error , from_ffi} ;
2
- use super :: { ffi, consts, SockOpt } ;
2
+ use super :: { ffi, consts, GetSockOpt , SetSockOpt } ;
3
3
use errno:: Errno ;
4
4
use sys:: time:: TimeVal ;
5
5
use libc:: { c_int, uint8_t, c_void, socklen_t} ;
6
6
use std:: mem;
7
7
use std:: os:: unix:: io:: RawFd ;
8
8
9
- // Helper to generate the sockopt accessors
10
- // TODO: Figure out how to ommit gets when not supported by opt
11
- macro_rules! sockopt_impl {
12
- ( $name: ident, $flag: path, bool ) => {
13
- sockopt_impl!( $name, $flag, bool , GetBool , SetBool ) ;
14
- } ;
15
-
16
- ( $name: ident, $flag: path, u8 ) => {
17
- sockopt_impl!( $name, $flag, u8 , GetU8 , SetU8 ) ;
18
- } ;
9
+ macro_rules! setsockopt_impl {
10
+ ( $name: ident, $level: path, $flag: path, $ty: ty, $setter: ty) => {
11
+ impl SetSockOpt for $name {
12
+ type Val = $ty;
19
13
20
- ( $name : ident , $flag : path , $ty: ty ) = > {
21
- sockopt_impl! ( $name , $flag , $ty , GetStruct <$ty> , SetStruct <$ty> ) ;
22
- } ;
14
+ fn set ( & self , fd : RawFd , val : & $ty) -> Result < ( ) > {
15
+ unsafe {
16
+ let setter : $setter = Set :: new ( val ) ;
23
17
24
- ( $name: ident, $flag: path, $ty: ty, $getter: ty, $setter: ty) => {
25
- #[ derive( Clone , Copy , Debug ) ]
26
- pub struct $name;
18
+ let res = ffi:: setsockopt( fd, $level, $flag,
19
+ setter. ffi_ptr( ) ,
20
+ setter. ffi_len( ) ) ;
21
+ from_ffi( res)
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
27
28
- impl SockOpt for $name {
28
+ macro_rules! getsockopt_impl {
29
+ ( $name: ident, $level: path, $flag: path, $ty: ty, $getter: ty) => {
30
+ impl GetSockOpt for $name {
29
31
type Val = $ty;
30
32
31
- fn get( & self , fd: RawFd , level : c_int ) -> Result <$ty> {
33
+ fn get( & self , fd: RawFd ) -> Result <$ty> {
32
34
unsafe {
33
35
let mut getter: $getter = Get :: blank( ) ;
34
36
35
- let res = ffi:: getsockopt(
36
- fd, level, $flag,
37
- getter. ffi_ptr( ) ,
38
- getter. ffi_len( ) ) ;
39
-
37
+ let res = ffi:: getsockopt( fd, $level, $flag,
38
+ getter. ffi_ptr( ) ,
39
+ getter. ffi_len( ) ) ;
40
40
if res < 0 {
41
41
return Err ( Error :: Sys ( Errno :: last( ) ) ) ;
42
42
}
43
43
44
44
Ok ( getter. unwrap( ) )
45
45
}
46
46
}
47
+ }
48
+ }
49
+ }
47
50
48
- fn set( & self , fd: RawFd , level: c_int, val: & $ty) -> Result <( ) > {
49
- unsafe {
50
- let setter: $setter = Set :: new( val) ;
51
+ // Helper to generate the sockopt accessors
52
+ macro_rules! sockopt_impl {
53
+ ( GetOnly , $name: ident, $level: path, $flag: path, $ty: ty) => {
54
+ sockopt_impl!( GetOnly , $name, $level, $flag, $ty, GetStruct <$ty>) ;
55
+ } ;
51
56
52
- let res = ffi:: setsockopt(
53
- fd, level, $flag,
54
- setter. ffi_ptr( ) ,
55
- setter. ffi_len( ) ) ;
57
+ ( GetOnly , $name: ident, $level: path, $flag: path, bool ) => {
58
+ sockopt_impl!( GetOnly , $name, $level, $flag, bool , GetBool ) ;
59
+ } ;
56
60
57
- from_ffi( res)
58
- }
59
- }
60
- }
61
+ ( GetOnly , $name: ident, $level: path, $flag: path, u8 ) => {
62
+ sockopt_impl!( GetOnly , $name, $level, $flag, u8 , GetU8 ) ;
63
+ } ;
64
+
65
+ ( GetOnly , $name: ident, $level: path, $flag: path, $ty: ty, $getter: ty) => {
66
+ #[ derive( Copy , Clone , Debug ) ]
67
+ pub struct $name;
68
+
69
+ getsockopt_impl!( $name, $level, $flag, $ty, $getter) ;
70
+ } ;
71
+
72
+ ( SetOnly , $name: ident, $level: path, $flag: path, $ty: ty) => {
73
+ sockopt_impl!( SetOnly , $name, $level, $flag, $ty, SetStruct <$ty>) ;
74
+ } ;
75
+
76
+ ( SetOnly , $name: ident, $level: path, $flag: path, bool ) => {
77
+ sockopt_impl!( SetOnly , $name, $level, $flag, bool , SetBool ) ;
78
+ } ;
79
+
80
+ ( SetOnly , $name: ident, $level: path, $flag: path, u8 ) => {
81
+ sockopt_impl!( SetOnly , $name, $level, $flag, u8 , SetU8 ) ;
82
+ } ;
83
+
84
+ ( SetOnly , $name: ident, $level: path, $flag: path, $ty: ty, $setter: ty) => {
85
+ #[ derive( Copy , Clone , Debug ) ]
86
+ pub struct $name;
87
+
88
+ setsockopt_impl!( $name, $level, $flag, $ty, $setter) ;
89
+ } ;
90
+
91
+ ( Both , $name: ident, $level: path, $flag: path, $ty: ty, $getter: ty, $setter: ty) => {
92
+ #[ derive( Copy , Clone , Debug ) ]
93
+ pub struct $name;
94
+
95
+ setsockopt_impl!( $name, $level, $flag, $ty, $setter) ;
96
+ getsockopt_impl!( $name, $level, $flag, $ty, $getter) ;
97
+ } ;
98
+
99
+ ( Both , $name: ident, $level: path, $flag: path, bool ) => {
100
+ sockopt_impl!( Both , $name, $level, $flag, bool , GetBool , SetBool ) ;
101
+ } ;
102
+
103
+ ( Both , $name: ident, $level: path, $flag: path, u8 ) => {
104
+ sockopt_impl!( Both , $name, $level, $flag, u8 , GetU8 , SetU8 ) ;
105
+ } ;
106
+
107
+ ( Both , $name: ident, $level: path, $flag: path, $ty: ty) => {
108
+ sockopt_impl!( Both , $name, $level, $flag, $ty, GetStruct <$ty>, SetStruct <$ty>) ;
61
109
} ;
62
110
}
63
111
@@ -67,20 +115,31 @@ macro_rules! sockopt_impl {
67
115
*
68
116
*/
69
117
70
- sockopt_impl ! ( ReuseAddr , consts:: SO_REUSEADDR , bool ) ;
71
- sockopt_impl ! ( ReusePort , consts:: SO_REUSEPORT , bool ) ;
72
- sockopt_impl ! ( TcpNoDelay , consts:: TCP_NODELAY , bool ) ;
73
- sockopt_impl ! ( Linger , consts:: SO_LINGER , super :: linger) ;
74
- sockopt_impl ! ( IpAddMembership , consts:: IP_ADD_MEMBERSHIP , super :: ip_mreq) ;
75
- sockopt_impl ! ( IpDropMembership , consts:: IP_DROP_MEMBERSHIP , super :: ip_mreq) ;
76
- sockopt_impl ! ( Ipv6AddMembership , consts:: IPV6_ADD_MEMBERSHIP , super :: ipv6_mreq) ;
77
- sockopt_impl ! ( Ipv6DropMembership , consts:: IPV6_DROP_MEMBERSHIP , super :: ipv6_mreq) ;
78
- sockopt_impl ! ( IpMulticastTtl , consts:: IP_MULTICAST_TTL , u8 ) ;
79
- sockopt_impl ! ( IpMulticastLoop , consts:: IP_MULTICAST_LOOP , bool ) ;
80
- sockopt_impl ! ( ReceiveTimeout , consts:: SO_RCVTIMEO , TimeVal ) ;
81
- sockopt_impl ! ( SendTimeout , consts:: SO_SNDTIMEO , TimeVal ) ;
82
- sockopt_impl ! ( Broadcast , consts:: SO_BROADCAST , bool ) ;
83
- sockopt_impl ! ( OobInline , consts:: SO_OOBINLINE , bool ) ;
118
+ sockopt_impl ! ( Both , ReuseAddr , consts:: SOL_SOCKET , consts:: SO_REUSEADDR , bool ) ;
119
+ sockopt_impl ! ( Both , ReusePort , consts:: SOL_SOCKET , consts:: SO_REUSEPORT , bool ) ;
120
+ sockopt_impl ! ( Both , TcpNoDelay , consts:: SOL_SOCKET , consts:: TCP_NODELAY , bool ) ;
121
+ sockopt_impl ! ( Both , Linger , consts:: SOL_SOCKET , consts:: SO_LINGER , super :: linger) ;
122
+ sockopt_impl ! ( SetOnly , IpAddMembership , consts:: IPPROTO_IP , consts:: IP_ADD_MEMBERSHIP , super :: ip_mreq) ;
123
+ sockopt_impl ! ( SetOnly , IpDropMembership , consts:: IPPROTO_IP , consts:: IP_DROP_MEMBERSHIP , super :: ip_mreq) ;
124
+ sockopt_impl ! ( SetOnly , Ipv6AddMembership , consts:: IPPROTO_IPV6 , consts:: IPV6_ADD_MEMBERSHIP , super :: ipv6_mreq) ;
125
+ sockopt_impl ! ( SetOnly , Ipv6DropMembership , consts:: IPPROTO_IPV6 , consts:: IPV6_DROP_MEMBERSHIP , super :: ipv6_mreq) ;
126
+ sockopt_impl ! ( Both , IpMulticastTtl , consts:: IPPROTO_IP , consts:: IP_MULTICAST_TTL , u8 ) ;
127
+ sockopt_impl ! ( Both , IpMulticastLoop , consts:: IPPROTO_IP , consts:: IP_MULTICAST_LOOP , bool ) ;
128
+ sockopt_impl ! ( Both , ReceiveTimeout , consts:: SOL_SOCKET , consts:: SO_RCVTIMEO , TimeVal ) ;
129
+ sockopt_impl ! ( Both , SendTimeout , consts:: SOL_SOCKET , consts:: SO_SNDTIMEO , TimeVal ) ;
130
+ sockopt_impl ! ( Both , Broadcast , consts:: SOL_SOCKET , consts:: SO_BROADCAST , bool ) ;
131
+ sockopt_impl ! ( Both , OobInline , consts:: SOL_SOCKET , consts:: SO_OOBINLINE , bool ) ;
132
+ sockopt_impl ! ( GetOnly , SocketError , consts:: SOL_SOCKET , consts:: SO_ERROR , i32 ) ;
133
+ sockopt_impl ! ( Both , KeepAlive , consts:: SOL_SOCKET , consts:: SO_KEEPALIVE , bool ) ;
134
+ #[ cfg( any( target_os = "macos" ,
135
+ target_os = "ios" ) ) ]
136
+ sockopt_impl ! ( Both , TcpKeepAlive , consts:: IPPROTO_TCP , consts:: TCP_KEEPALIVE , u32 ) ;
137
+ #[ cfg( any( target_os = "freebsd" ,
138
+ target_os = "dragonfly" ,
139
+ target_os = "linux" ,
140
+ target_os = "android" ,
141
+ target_os = "nacl" ) ) ]
142
+ sockopt_impl ! ( Both , TcpKeepIdle , consts:: IPPROTO_TCP , consts:: TCP_KEEPIDLE , u32 ) ;
84
143
85
144
/*
86
145
*
@@ -108,7 +167,10 @@ struct GetStruct<T> {
108
167
109
168
impl < T > Get < T > for GetStruct < T > {
110
169
unsafe fn blank ( ) -> Self {
111
- mem:: zeroed ( )
170
+ GetStruct {
171
+ len : mem:: size_of :: < T > ( ) as socklen_t ,
172
+ val : mem:: zeroed ( ) ,
173
+ }
112
174
}
113
175
114
176
unsafe fn ffi_ptr ( & mut self ) -> * mut c_void {
@@ -150,7 +212,10 @@ struct GetBool {
150
212
151
213
impl Get < bool > for GetBool {
152
214
unsafe fn blank ( ) -> Self {
153
- mem:: zeroed ( )
215
+ GetBool {
216
+ len : mem:: size_of :: < c_int > ( ) as socklen_t ,
217
+ val : mem:: zeroed ( ) ,
218
+ }
154
219
}
155
220
156
221
unsafe fn ffi_ptr ( & mut self ) -> * mut c_void {
@@ -192,7 +257,10 @@ struct GetU8 {
192
257
193
258
impl Get < u8 > for GetU8 {
194
259
unsafe fn blank ( ) -> Self {
195
- mem:: zeroed ( )
260
+ GetU8 {
261
+ len : mem:: size_of :: < uint8_t > ( ) as socklen_t ,
262
+ val : mem:: zeroed ( ) ,
263
+ }
196
264
}
197
265
198
266
unsafe fn ffi_ptr ( & mut self ) -> * mut c_void {
0 commit comments