@@ -20,6 +20,11 @@ use libc as c;
20
20
#[ cfg( windows) ]
21
21
use winapi:: shared:: ws2def as c;
22
22
23
+ #[ cfg( any( unix, target_os = "redox" ) ) ]
24
+ use libc:: MSG_OOB ;
25
+ #[ cfg( windows) ]
26
+ use winapi:: um:: winsock2:: MSG_OOB ;
27
+
23
28
use crate :: sys;
24
29
use crate :: { Domain , Protocol , SockAddr , Socket , Type } ;
25
30
@@ -213,7 +218,26 @@ impl Socket {
213
218
///
214
219
/// [`connect`]: #method.connect
215
220
pub fn recv ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
216
- self . inner . recv ( buf)
221
+ self . inner . recv ( buf, 0 )
222
+ }
223
+
224
+ /// Identical to [`recv`] but allows for specification of arbitrary flags to the underlying
225
+ /// `recv` call.
226
+ ///
227
+ /// [`recv`]: #method.recv
228
+ pub fn recv_with_flags ( & self , buf : & mut [ u8 ] , flags : i32 ) -> io:: Result < usize > {
229
+ self . inner . recv ( buf, flags)
230
+ }
231
+
232
+ /// Receives out-of-band (OOB) data on the socket from the remote address to
233
+ /// which it is connected by setting the `MSG_OOB` flag for this call.
234
+ ///
235
+ /// For more information, see [`recv`], [`out_of_band_inline`].
236
+ ///
237
+ /// [`recv`]: #method.recv
238
+ /// [`out_of_band_inline`]: #method.out_of_band_inline
239
+ pub fn recv_out_of_band ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
240
+ self . inner . recv ( buf, MSG_OOB )
217
241
}
218
242
219
243
/// Receives data on the socket from the remote adress to which it is
@@ -229,7 +253,15 @@ impl Socket {
229
253
/// Receives data from the socket. On success, returns the number of bytes
230
254
/// read and the address from whence the data came.
231
255
pub fn recv_from ( & self , buf : & mut [ u8 ] ) -> io:: Result < ( usize , SockAddr ) > {
232
- self . inner . recv_from ( buf)
256
+ self . inner . recv_from ( buf, 0 )
257
+ }
258
+
259
+ /// Identical to [`recv_from`] but allows for specification of arbitrary flags to the underlying
260
+ /// `recvfrom` call.
261
+ ///
262
+ /// [`recv_from`]: #method.recv_from
263
+ pub fn recv_from_with_flags ( & self , buf : & mut [ u8 ] , flags : i32 ) -> io:: Result < usize > {
264
+ self . inner . recv ( buf, flags)
233
265
}
234
266
235
267
/// Receives data from the socket, without removing it from the queue.
@@ -250,7 +282,26 @@ impl Socket {
250
282
///
251
283
/// On success returns the number of bytes that were sent.
252
284
pub fn send ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
253
- self . inner . send ( buf)
285
+ self . inner . send ( buf, 0 )
286
+ }
287
+
288
+ /// Identical to [`send`] but allows for specification of arbitrary flags to the underlying
289
+ /// `send` call.
290
+ ///
291
+ /// [`send`]: #method.send
292
+ pub fn send_with_flags ( & self , buf : & mut [ u8 ] , flags : i32 ) -> io:: Result < usize > {
293
+ self . inner . send ( buf, flags)
294
+ }
295
+
296
+ /// Sends out-of-band (OOB) data on the socket to connected peer
297
+ /// by setting the `MSG_OOB` flag for this call.
298
+ ///
299
+ /// For more information, see [`send`], [`out_of_band_inline`].
300
+ ///
301
+ /// [`send`]: #method.send
302
+ /// [`out_of_band_inline`]: #method.out_of_band_inline
303
+ pub fn send_out_of_band ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
304
+ self . inner . send ( buf, MSG_OOB )
254
305
}
255
306
256
307
/// Sends data on the socket to the given address. On success, returns the
@@ -259,7 +310,15 @@ impl Socket {
259
310
/// This is typically used on UDP or datagram-oriented sockets. On success
260
311
/// returns the number of bytes that were sent.
261
312
pub fn send_to ( & self , buf : & [ u8 ] , addr : & SockAddr ) -> io:: Result < usize > {
262
- self . inner . send_to ( buf, addr)
313
+ self . inner . send_to ( buf, 0 , addr)
314
+ }
315
+
316
+ /// Identical to [`send_to`] but allows for specification of arbitrary flags to the underlying
317
+ /// `sendto` call.
318
+ ///
319
+ /// [`send_to`]: #method.send_to
320
+ pub fn send_to_with_flags ( & self , buf : & mut [ u8 ] , flags : i32 ) -> io:: Result < usize > {
321
+ self . inner . recv ( buf, flags)
263
322
}
264
323
265
324
// ================================================
@@ -628,6 +687,24 @@ impl Socket {
628
687
self . inner . set_keepalive ( keepalive)
629
688
}
630
689
690
+ /// Returns the value of the `SO_OOBINLINE` flag of the underlying socket.
691
+ /// For more information about this option, see [`set_out_of_band_inline`][link].
692
+ ///
693
+ /// [link]: #method.set_out_of_band_inline
694
+ pub fn out_of_band_inline ( & self ) -> io:: Result < bool > {
695
+ self . inner . out_of_band_inline ( )
696
+ }
697
+
698
+ /// Sets the `SO_OOBINLINE` flag of the underlying socket.
699
+ /// as per RFC6093, TCP sockets using the Urgent mechanism
700
+ /// are encouraged to set this flag.
701
+ ///
702
+ /// If this flag is not set, the `MSG_OOB` flag is needed
703
+ /// while `recv`ing to aquire the out-of-band data.
704
+ pub fn set_out_of_band_inline ( & self , oob_inline : bool ) -> io:: Result < ( ) > {
705
+ self . inner . set_out_of_band_inline ( oob_inline)
706
+ }
707
+
631
708
/// Check the value of the `SO_REUSEPORT` option on this socket.
632
709
///
633
710
/// This function is only available on Unix when the `reuseport` feature is
@@ -1003,4 +1080,57 @@ mod test {
1003
1080
assert ! ( result. is_ok( ) ) ;
1004
1081
assert ! ( result. unwrap( ) ) ;
1005
1082
}
1083
+
1084
+ #[ test]
1085
+ fn out_of_band_inline ( ) {
1086
+ let socket = Socket :: new ( Domain :: ipv4 ( ) , Type :: stream ( ) , None ) . unwrap ( ) ;
1087
+
1088
+ assert_eq ! ( socket. out_of_band_inline( ) . unwrap( ) , false ) ;
1089
+
1090
+ socket. set_out_of_band_inline ( true ) . unwrap ( ) ;
1091
+ assert_eq ! ( socket. out_of_band_inline( ) . unwrap( ) , true ) ;
1092
+ }
1093
+
1094
+ #[ test]
1095
+ #[ cfg( any( target_os = "windows" , target_os = "linux" ) ) ]
1096
+ fn out_of_band_send_recv ( ) {
1097
+ let s1 = Socket :: new ( Domain :: ipv4 ( ) , Type :: stream ( ) , None ) . unwrap ( ) ;
1098
+ s1. bind ( & "127.0.0.1:0" . parse :: < SocketAddr > ( ) . unwrap ( ) . into ( ) )
1099
+ . unwrap ( ) ;
1100
+ let s1_addr = s1. local_addr ( ) . unwrap ( ) ;
1101
+ s1. listen ( 1 ) . unwrap ( ) ;
1102
+
1103
+ let s2 = Socket :: new ( Domain :: ipv4 ( ) , Type :: stream ( ) , None ) . unwrap ( ) ;
1104
+ s2. connect ( & s1_addr) . unwrap ( ) ;
1105
+
1106
+ let ( s3, _) = s1. accept ( ) . unwrap ( ) ;
1107
+
1108
+ let mut buf = [ 0 ; 10 ] ;
1109
+ // send some plain inband data
1110
+ s2. send ( & mut buf) . unwrap ( ) ;
1111
+ // send a single out of band byte
1112
+ assert_eq ! ( s2. send_out_of_band( & mut [ b"!" [ 0 ] ] ) . unwrap( ) , 1 ) ;
1113
+ // recv the OOB data first
1114
+ assert_eq ! ( s3. recv_out_of_band( & mut buf) . unwrap( ) , 1 ) ;
1115
+ assert_eq ! ( buf[ 0 ] , b"!" [ 0 ] ) ;
1116
+ assert_eq ! ( s3. recv( & mut buf) . unwrap( ) , 10 ) ;
1117
+ }
1118
+
1119
+ #[ test]
1120
+ fn tcp ( ) {
1121
+ let s1 = Socket :: new ( Domain :: ipv4 ( ) , Type :: stream ( ) , None ) . unwrap ( ) ;
1122
+ s1. bind ( & "127.0.0.1:0" . parse :: < SocketAddr > ( ) . unwrap ( ) . into ( ) )
1123
+ . unwrap ( ) ;
1124
+ let s1_addr = s1. local_addr ( ) . unwrap ( ) ;
1125
+ s1. listen ( 1 ) . unwrap ( ) ;
1126
+
1127
+ let s2 = Socket :: new ( Domain :: ipv4 ( ) , Type :: stream ( ) , None ) . unwrap ( ) ;
1128
+ s2. connect ( & s1_addr) . unwrap ( ) ;
1129
+
1130
+ let ( s3, _) = s1. accept ( ) . unwrap ( ) ;
1131
+
1132
+ let mut buf = [ 0 ; 11 ] ;
1133
+ assert_eq ! ( s2. send( & mut buf) . unwrap( ) , 11 ) ;
1134
+ assert_eq ! ( s3. recv( & mut buf) . unwrap( ) , 11 ) ;
1135
+ }
1006
1136
}
0 commit comments