libsocket/
lib.rs

1// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
2//
3// This Source Code Form is subject to the terms of the
4// Mozilla Public License, v. 2.0. If a copy of the MPL was not
5// distributed with this file, You can obtain one at
6// http://mozilla.org/MPL/2.0/.
7
8
9#[macro_use]
10extern crate bitflags;
11extern crate libc;
12extern crate errno;
13
14
15use std::mem;
16use std::ffi::CString;
17use std::os::unix::io::{RawFd, AsRawFd};
18use std::io::{Read, Write, Error, ErrorKind};
19
20use libc::{c_int, c_void};
21use errno::errno;
22
23
24bitflags! {
25    pub flags SocketType: libc::c_int {
26        const SOCK_STREAM   = libc::SOCK_STREAM,
27        const SOCK_DGRAM    = libc::SOCK_DGRAM,
28        const SOCK_RAW      = libc::SOCK_RAW,
29        const SOCK_CLOEXEC  = libc::SOCK_CLOEXEC,
30        const SOCK_NONBLOCK = libc::SOCK_NONBLOCK
31    }
32}
33
34bitflags! {
35    pub flags IoFlags: libc::c_int {
36        const MSG_CMSG_DONTWAIT = 0x0040,
37        const MSG_ERRQUEUE      = 0x2000,
38        const MSG_OOB           = 0x0001,
39        const MSG_PEEK          = 0x0002,
40        const MSG_TRUNC         = 0x0020,
41        const MSG_WAITALL       = 0x0100,
42        const MSG_CONFIRM       = 0x0800,
43        const MSG_DONTROUTE     = 0x0004,
44        const MSG_EOR           = 0x0080,
45        const MSG_MORE          = 0x8000,
46        const MSG_NOSIGNAL      = 0x4000
47    }
48}
49
50pub enum Domain {
51    Unix,
52    Inet,
53    Inet6,
54    Netlink,
55    Packet
56}
57
58pub enum Shutdown {
59    Read,
60    Write,
61    Both
62}
63
64pub struct Socket {
65    fd: c_int
66}
67
68impl Domain {
69    fn to_cint(&self) -> c_int {
70        match *self {
71            Domain::Unix => libc::AF_UNIX,
72            Domain::Inet => libc::AF_INET,
73            Domain::Inet6 => libc::AF_INET6,
74            Domain::Netlink => libc::AF_NETLINK,
75            Domain::Packet => libc::AF_PACKET,
76        }
77    }
78}
79
80impl Shutdown {
81    fn to_cint(&self) -> c_int {
82        match *self {
83            Shutdown::Read => libc::SHUT_RD,
84            Shutdown::Write => libc::SHUT_WR,
85            Shutdown::Both => libc::SHUT_RDWR
86        }
87    }
88}
89
90impl Socket {
91    /// Creates a new socket with the passed options.
92    pub fn new(domain: Domain,
93               sock_type: c_int,
94               protocol: c_int)
95               -> Result<Socket, Error>
96    {
97        let result = unsafe {
98            libc::socket(domain.to_cint(), sock_type, protocol)
99        };
100
101        if result < 0 {
102            return Err(Error::from_raw_os_error(errno().0 as i32));
103        }
104
105        return Ok(Socket {
106            fd: result
107        });
108    }
109
110    /// Creates a socket from an already established socket fd.
111    pub fn from_fd(fd: c_int) -> Socket {
112        return Socket {
113            fd: fd
114        };
115    }
116
117    /// Assigns the address specified by `address` to the socket
118    pub fn bind(&self,
119                address: *const libc::sockaddr,
120                address_len: libc::socklen_t)
121                -> Result<(), Error>
122    {
123        let result = unsafe {
124            libc::bind(self.fd, address, address_len)
125        };
126
127        if result < 0 {
128            return Err(Error::from_raw_os_error(errno().0 as i32));
129        }
130
131        return Ok(());
132    }
133
134    /// Connects the socket to `address`.
135    pub fn connect(&self,
136                   address: *const libc::sockaddr,
137                   address_len: libc::socklen_t)
138                   -> Result<(), Error>
139    {
140        let result = unsafe {
141            libc::connect(self.fd, address, address_len)
142        };
143
144        if result < 0 {
145            return Err(Error::from_raw_os_error(errno().0 as i32));
146        }
147
148        return Ok(());
149    }
150
151    /// Marks the socket as a socket that will be used to accept incoming connections.
152    pub fn listen(&self, backlog: usize) -> Result<(), Error> {
153        let result = unsafe {
154            libc::listen(self.fd, backlog as c_int)
155        };
156
157        if result < 0 {
158            return Err(Error::from_raw_os_error(errno().0 as i32));
159        }
160
161        return Ok(());
162    }
163
164    /// Extracts the first connection from the backlog queue of pending connections and creates
165    /// and returns a new `Socket`.
166    pub fn accept(&self,
167                  address: *mut libc::sockaddr,
168                  address_len: *mut libc::socklen_t)
169                  -> Result<Socket, Error>
170    {
171        let result = unsafe {
172            libc::accept(self.fd, address, address_len)
173        };
174
175        if result < 0 {
176            return Err(Error::from_raw_os_error(errno().0 as i32));
177        }
178
179        return Ok(Socket{
180            fd: result
181        });
182    }
183
184    /// If no messages are available at the socket, the call waits for a message to arrive, unless
185    /// the socket is nonblocking, in which case `ErrorKind::WouldBlock` is returned. The call
186    /// normally returns any data available, up to the requested amount, rather than waiting for
187    /// receipt of the full amount requested.
188    pub fn recv(&self, buf: &mut [u8], flags: libc::c_int) -> Result<usize, Error> {
189        let len = buf.len() as libc::size_t;
190        let buf_ptr = buf.as_mut_ptr() as *mut _ as *mut libc::c_void;
191        
192        let result = unsafe {
193            libc::recv(self.fd, buf_ptr, len, flags)
194        };
195
196        if result < 0 {
197            return Err(Error::from_raw_os_error(errno().0 as i32));
198        }
199
200        if result == 0 {
201            return Err(Error::new(ErrorKind::UnexpectedEof, "Unexpected end of file"))
202        }
203
204        let num_read = result as usize;
205        return Ok(num_read);
206    }
207
208    /// If the message is too long to pass atomically through the underlying protocol, the error
209    /// `EMSGSIZE` is returned, and the message is not transmitted. No indication of failure
210    /// to deliver is implicit in a send(). Locally detected errors are indicated by an Error
211    /// returned. When the message does not fit into the send buffer of the socket, send()
212    /// normally blocks, unless the socket has been placed in nonblocking I/O mode.
213    /// In nonblocking mode it would fail with the error `ErrorKind::WouldBlock` in this case.
214    pub fn send(&self, buf: &[u8], flags: libc::c_int) -> Result<usize, Error> {
215        let len = buf.len() as libc::size_t;
216        let buf_ptr = buf.as_ptr() as *const _ as *const libc::c_void;
217
218        let result = unsafe {
219            libc::send(self.fd, buf_ptr, len, flags)
220        };
221
222        if result < 0 {
223            return Err(Error::from_raw_os_error(errno().0 as i32));
224        }
225
226        if result == 0 && len > 0 {
227            return Err(Error::new(ErrorKind::Other, "Send returned zero (0)"));
228        }
229
230        let num_sent = result as usize;
231        return Ok(num_sent);
232    }
233
234    /// Disables subsequent send and/or receive operations on a socket, depending on the value
235    /// of the how argument.
236    pub fn shutdown(&self, how: Shutdown) -> Result<(), Error> {
237        let result = unsafe {
238            libc::shutdown(self.fd, how.to_cint())
239        };
240
241        if result < 0 {
242            return Err(Error::from_raw_os_error(errno().0 as i32));
243        }
244
245        return Ok(());
246    }
247
248    /// Closes the underlying file descriptor of the socket.
249    pub fn close(&self) -> Result<(), Error> {
250        let result = unsafe {
251            libc::close(self.fd)
252        };
253
254        if result < 0 {
255            return Err(Error::from_raw_os_error(errno().0 as i32));
256        }
257
258        return Ok(());
259    }
260
261    /// If set, disable the Nagle algorithm. This means that segments are always sent as soon as
262    /// possible, even if there is only a small amount of data. When not set, data is buffered
263    /// until there is a sufficient amount to send out, thereby avoiding the frequent sending of
264    /// small packets, which results in poor utilization of the network. This option is
265    /// overridden by TCP_CORK; however, setting this option forces an explicit flush of pending
266    /// output, even if TCP_CORK is currently set.
267    pub fn set_tcp_nodelay(&mut self, nodelay: bool) -> Result<(), Error> {
268        let optval: c_int = match nodelay {
269            true => 1,
270            false => 0
271        };
272        let opt_result = unsafe {
273            libc::setsockopt(self.fd,
274                             libc::IPPROTO_TCP,
275                             libc::TCP_NODELAY,
276                             &optval as *const _ as *const c_void,
277                             mem::size_of::<c_int>() as u32)
278        };
279        if opt_result < 0 {
280            return Err(Error::from_raw_os_error(errno().0 as i32));
281        }
282
283        Ok(())
284    }
285
286    /// Sets the `O_NONBLOCK` flag on the underlying fd
287    pub fn set_nonblocking(&mut self) -> Result<(), Error> {
288        let result = unsafe {
289            libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0)
290        };
291        if result < 0 {
292            return Err(Error::from_raw_os_error(errno().0 as i32));
293        }
294
295        let flags = result | libc::O_NONBLOCK;
296        let result = unsafe {
297            libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags)
298        };
299        if result < 0 {
300            return Err(Error::from_raw_os_error(errno().0 as i32));
301        }
302
303        Ok(())
304    }
305
306    /// Bind this socket to a particular device like "eth0", as specified in the passed
307    /// interface name. If the name is an empty string or the option length is zero, the socket
308    /// device binding is removed. The passed option is a variable-length null-terminated
309    /// interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an
310    /// interface, only packets received from that particular interface are processed by the
311    /// socket. Note that this only works for some socket types, particularly AF_INET sockets.
312    /// It is not supported for packet sockets (use normal bind(2) there).
313    ///
314    /// Before Linux 3.8, this socket option could be set, but could not retrieved with
315    /// getsockopt(2). Since Linux 3.8, it is readable. The optlen argument should contain the
316    /// buffer size available to receive the device name and is recommended to be IFNAMSZ bytes.
317    /// The real device name length is reported back in the optlen argument.
318    pub fn set_bindtodevice(&mut self, interface: String) -> Result<(), Error> {
319        const SO_BINDTODEVICE: i32 = 25;
320        let cstr_result = CString::new(interface);
321        if cstr_result.is_err() {
322            return Err(Error::new(ErrorKind::Other, "Null Byte"));
323        }
324
325        let cstr = cstr_result.unwrap();
326        unsafe {
327            if libc::strlen(cstr.as_ptr()) > libc::IF_NAMESIZE {
328                return Err(Error::new(ErrorKind::Other, "strlen(interface) > IFNAMSIZ"));
329            }
330        }
331
332        let opt_result = unsafe {
333            libc::setsockopt(self.fd,
334                             libc::SOL_SOCKET,
335                             SO_BINDTODEVICE,
336                             cstr.as_ptr() as *const c_void,
337                             libc::strlen(cstr.as_ptr()) as u32)
338        };
339        if opt_result < 0 {
340            return Err(Error::from_raw_os_error(errno().0 as i32));
341        }
342
343        Ok(())
344    }
345
346    /// When enabled, datagram sockets are allowed to send packets to a broadcast address.
347    /// This option has no effect on stream-oriented sockets.
348    pub fn set_broadcast(&mut self, option: bool) -> Result<(), Error> {
349        let optval: c_int = match option {
350            true => 1,
351            false => 0
352        };
353        let opt_result = unsafe {
354            libc::setsockopt(self.fd,
355                             libc::SOL_SOCKET,
356                             libc::SO_BROADCAST,
357                             &optval as *const _ as *const c_void,
358                             mem::size_of::<c_int>() as u32)
359        };
360        if opt_result < 0 {
361            return Err(Error::from_raw_os_error(errno().0 as i32));
362        }
363
364        Ok(())
365    }
366
367    /// Enable BSD bug-to-bug compatibility. This is used by the UDP protocol module in
368    /// Linux 2.0 and 2.2. If enabled ICMP errors received for a UDP socket will not be passed
369    /// to the user program. In later kernel versions, support for this option has been phased
370    /// out: Linux 2.4 silently ignores it, and Linux 2.6 generates a kernel warning
371    /// (printk()) if a program uses this option. Linux 2.0 also enabled BSD bug-to-bug
372    /// compatibility options (random header changing, skipping of the broadcast flag) for raw
373    /// sockets with this option, but that was removed in Linux 2.2.
374    pub fn set_bsdcompat(&mut self, option: bool) -> Result<(), Error> {
375        const SO_BSDCOMPAT: i32 = 14;
376        let optval: c_int = match option {
377            true => 1,
378            false => 0
379        };
380        let opt_result = unsafe {
381            libc::setsockopt(self.fd,
382                             libc::SOL_SOCKET,
383                             SO_BSDCOMPAT,
384                             &optval as *const _ as *const c_void,
385                             mem::size_of::<c_int>() as u32)
386        };
387        if opt_result < 0 {
388            return Err(Error::from_raw_os_error(errno().0 as i32));
389        }
390
391        Ok(())
392    }
393
394    /// Enable socket debugging. Only allowed for processes with the CAP_NET_ADMIN capability
395    /// or an effective user ID of 0.
396    pub fn set_debug(&mut self, option: bool) -> Result<(), Error> {
397        let optval: c_int = match option {
398            true => 1,
399            false => 0
400        };
401        let opt_result = unsafe {
402            libc::setsockopt(self.fd,
403                             libc::SOL_SOCKET,
404                             libc::SO_DEBUG,
405                             &optval as *const _ as *const c_void,
406                             mem::size_of::<c_int>() as u32)
407        };
408        if opt_result < 0 {
409            return Err(Error::from_raw_os_error(errno().0 as i32));
410        }
411
412        Ok(())
413    }
414
415    /// Don't send via a gateway, only send to directly connected hosts. The same effect can be
416    /// achieved by setting the MSG_DONTROUTE flag on a socket send(2) operation. Expects an
417    /// integer boolean flag.
418    pub fn set_dontroute(&mut self, option: bool) -> Result<(), Error> {
419        let optval: c_int = match option {
420            true => 1,
421            false => 0
422        };
423        let opt_result = unsafe {
424            libc::setsockopt(self.fd,
425                             libc::SOL_SOCKET,
426                             libc::SO_DONTROUTE,
427                             &optval as *const _ as *const c_void,
428                             mem::size_of::<c_int>() as u32)
429        };
430        if opt_result < 0 {
431            return Err(Error::from_raw_os_error(errno().0 as i32));
432        }
433
434        Ok(())
435    }
436
437    /// Enable sending of keep-alive messages on connection-oriented sockets. Expects an integer
438    /// boolean flag.
439    pub fn set_keepalive(&mut self, option: bool) -> Result<(), Error> {
440        let optval: c_int = match option {
441            true => 1,
442            false => 0
443        };
444        let opt_result = unsafe {
445            libc::setsockopt(self.fd,
446                             libc::SOL_SOCKET,
447                             libc::SO_KEEPALIVE,
448                             &optval as *const _ as *const c_void,
449                             mem::size_of::<c_int>() as u32)
450        };
451        if opt_result < 0 {
452            return Err(Error::from_raw_os_error(errno().0 as i32));
453        }
454
455        Ok(())
456    }
457
458    /// Sets or gets the SO_LINGER option. When enabled, a close(2) or shutdown(2) will not return
459    /// until all queued messages for the socket have been successfully sent or the linger timeout
460    /// has been reached. Otherwise, the call returns immediately and the closing is done in the
461    /// background. When the socket is closed as part of exit(2), it always lingers in the
462    /// background.
463    pub fn set_linger(&mut self, option: bool, sec: u32) -> Result<(), Error> {
464        #[repr(C, packed)]
465        struct Linger {
466            l_onoff: c_int,
467            l_linger: c_int
468        };
469
470        let optval: c_int = match option {
471            true => 1,
472            false => 0
473        };
474        let data = Linger {
475            l_onoff: optval,
476            l_linger: sec as i32
477        };
478
479        let opt_result = unsafe {
480            libc::setsockopt(self.fd,
481                             libc::SOL_SOCKET,
482                             libc::SO_LINGER,
483                             &data as *const _ as *const c_void,
484                             mem::size_of::<Linger>() as u32)
485        };
486        if opt_result < 0 {
487            return Err(Error::from_raw_os_error(errno().0 as i32));
488        }
489
490        Ok(())
491    }
492
493    /// Set the mark for each packet sent through this socket (similar to the netfilter MARK
494    /// target but socket-based). Changing the mark can be used for mark-based routing without
495    /// netfilter or for packet filtering. Setting this option requires the CAP_NET_ADMIN
496    /// capability.
497    pub fn set_mark(&mut self, option: bool) -> Result<(), Error> {
498        const SO_MARK: i32 = 36;
499        let optval: c_int = match option {
500            true => 1,
501            false => 0
502        };
503        let opt_result = unsafe {
504            libc::setsockopt(self.fd,
505                             libc::SOL_SOCKET,
506                             SO_MARK,
507                             &optval as *const _ as *const c_void,
508                             mem::size_of::<c_int>() as u32)
509        };
510        if opt_result < 0 {
511            return Err(Error::from_raw_os_error(errno().0 as i32));
512        }
513
514        Ok(())
515    }
516
517    /// If this option is enabled, out-of-band data is directly placed into the receive data
518    /// stream. Otherwise out-of-band data is only passed when the MSG_OOB flag is set during
519    /// receiving.
520    pub fn set_oobinline(&mut self, option: bool) -> Result<(), Error> {
521        let optval: c_int = match option {
522            true => 1,
523            false => 0
524        };
525        let opt_result = unsafe {
526            libc::setsockopt(self.fd,
527                             libc::SOL_SOCKET,
528                             libc::SO_OOBINLINE,
529                             &optval as *const _ as *const c_void,
530                             mem::size_of::<c_int>() as u32)
531        };
532        if opt_result < 0 {
533            return Err(Error::from_raw_os_error(errno().0 as i32));
534        }
535
536        Ok(())
537    }
538
539    /// Enable or disable the receiving of the SCM_CREDENTIALS control message. For more
540    /// information see unix(7).
541    pub fn set_passcred(&mut self, option: bool) -> Result<(), Error> {
542        const SO_PASSCRED: i32 = 16;
543        let optval: c_int = match option {
544            true => 1,
545            false => 0
546        };
547        let opt_result = unsafe {
548            libc::setsockopt(self.fd,
549                             libc::SOL_SOCKET,
550                             SO_PASSCRED,
551                             &optval as *const _ as *const c_void,
552                             mem::size_of::<c_int>() as u32)
553        };
554        if opt_result < 0 {
555            return Err(Error::from_raw_os_error(errno().0 as i32));
556        }
557
558        Ok(())
559    }
560
561    /// Set the protocol-defined priority for all packets to be sent on this socket. Linux uses
562    /// this value to order the networking queues: packets with a higher priority may be processed
563    /// first depending on the selected device queueing discipline. For ip(7), this also sets the
564    /// IP type-of-service (TOS) field for outgoing packets. Setting a priority outside the
565    /// range 0 to 6 requires the CAP_NET_ADMIN capability.
566    pub fn set_priority(&mut self, priority: u32) -> Result<(), Error> {
567        const SO_PRIORITY: i32 = 12;
568        let opt_result = unsafe {
569            libc::setsockopt(self.fd,
570                             libc::SOL_SOCKET,
571                             SO_PRIORITY,
572                             &priority as *const _ as *const c_void,
573                             mem::size_of::<u32>() as u32)
574        };
575        if opt_result < 0 {
576            return Err(Error::from_raw_os_error(errno().0 as i32));
577        }
578
579        Ok(())
580    }
581
582    /// Sets or gets the maximum socket receive buffer in bytes. The kernel doubles this value
583    /// (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this
584    /// doubled value is returned by getsockopt(2). The default value is set by
585    /// the /proc/sys/net/core/rmem_default file, and the maximum allowed value is set by
586    /// the /proc/sys/net/core/rmem_max file. The minimum (doubled) value for this option is 256.
587    pub fn set_rcvbuf(&mut self, size: usize) -> Result<(), Error> {
588        let opt_result = unsafe {
589            libc::setsockopt(self.fd,
590                             libc::SOL_SOCKET,
591                             libc::SO_RCVBUF,
592                             &size as *const _ as *const c_void,
593                             mem::size_of::<usize>() as u32)
594        };
595        if opt_result < 0 {
596            return Err(Error::from_raw_os_error(errno().0 as i32));
597        }
598
599        Ok(())
600    }
601
602    /// Using this socket option, a privileged (CAP_NET_ADMIN) process can perform the same task
603    /// as SO_RCVBUF, but the rmem_max limit can be overridden.
604    pub fn set_rcvbufforce(&mut self, size: usize) -> Result<(), Error> {
605        self.set_rcvbuf(size)
606    }
607
608    /// Specify the minimum number of bytes in the buffer until the socket layer will pass the
609    /// data to the protocol (SO_SNDLOWAT) or the user on receiving (SO_RCVLOWAT). These two
610    /// values are initialized to 1. SO_SNDLOWAT is not changeable on Linux (setsockopt(2) fails
611    /// with the error ENOPROTOOPT). SO_RCVLOWAT is changeable only since Linux 2.4. The select(2)
612    /// and poll(2) system calls currently do not respect the SO_RCVLOWAT setting on Linux, and
613    /// mark a socket readable when even a single byte of data is available. A subsequent read
614    /// from the socket will block until SO_RCVLOWAT bytes are available.
615    pub fn set_rcvlowat(&mut self, bytes: usize) -> Result<(), Error> {
616        let opt_result = unsafe {
617            libc::setsockopt(self.fd,
618                             libc::SOL_SOCKET,
619                             libc::SO_RCVLOWAT,
620                             &bytes as *const _ as *const c_void,
621                             mem::size_of::<usize>() as u32)
622        };
623        if opt_result < 0 {
624            return Err(Error::from_raw_os_error(errno().0 as i32));
625        }
626
627        Ok(())
628    }
629
630    /// Specify the minimum number of bytes in the buffer until the socket layer will pass the
631    /// data to the protocol (SO_SNDLOWAT) or the user on receiving (SO_RCVLOWAT). These two
632    /// values are initialized to 1. SO_SNDLOWAT is not changeable on Linux (setsockopt(2) fails
633    /// with the error ENOPROTOOPT). SO_RCVLOWAT is changeable only since Linux 2.4. The select(2)
634    /// and poll(2) system calls currently do not respect the SO_RCVLOWAT setting on Linux, and
635    /// mark a socket readable when even a single byte of data is available. A subsequent read
636    /// from the socket will block until SO_RCVLOWAT bytes are available.
637    pub fn set_sndlowat(&mut self, bytes: usize) -> Result<(), Error> {
638        let opt_result = unsafe {
639            libc::setsockopt(self.fd,
640                             libc::SOL_SOCKET,
641                             libc::SO_SNDLOWAT,
642                             &bytes as *const _ as *const c_void,
643                             mem::size_of::<usize>() as u32)
644        };
645        if opt_result < 0 {
646            return Err(Error::from_raw_os_error(errno().0 as i32));
647        }
648
649        Ok(())
650    }
651
652    /// Specify the receiving or sending timeouts until reporting an error. The argument is a
653    /// struct timeval. If an input or output function blocks for this period of time, and data
654    /// has been sent or received, the return value of that function will be the amount of data
655    /// transferred; if no data has been transferred and the timeout has been reached then -1 is
656    /// returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as
657    /// if the socket was specified to be nonblocking. If the timeout is set to zero (the default)
658    /// then the operation will never timeout. Timeouts only have effect for system calls that
659    /// perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no
660    /// effect for select(2), poll(2), epoll_wait(2), and so on.
661    pub fn set_rcvtimeo(&mut self,
662                        sec: libc::time_t,
663                        micro_sec: libc::suseconds_t)
664                        -> Result<(), Error>
665    {
666        #[repr(C, packed)]
667        struct Timeval {
668            tv_sec: libc::time_t,
669            tv_usec: libc::suseconds_t
670        };
671        let data = Timeval {
672            tv_sec: sec,
673            tv_usec: micro_sec
674        };
675
676        let opt_result = unsafe {
677            libc::setsockopt(self.fd,
678                             libc::SOL_SOCKET,
679                             libc::SO_RCVTIMEO,
680                             &data as *const _ as *const c_void,
681                             mem::size_of::<Timeval>() as u32)
682        };
683        if opt_result < 0 {
684            return Err(Error::from_raw_os_error(errno().0 as i32));
685        }
686
687        Ok(())
688    }
689
690    /// Specify the receiving or sending timeouts until reporting an error. The argument is a
691    /// struct timeval. If an input or output function blocks for this period of time, and data
692    /// has been sent or received, the return value of that function will be the amount of data
693    /// transferred; if no data has been transferred and the timeout has been reached then -1 is
694    /// returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as
695    /// if the socket was specified to be nonblocking. If the timeout is set to zero (the default)
696    /// then the operation will never timeout. Timeouts only have effect for system calls that
697    /// perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no
698    /// effect for select(2), poll(2), epoll_wait(2), and so on.
699    pub fn set_sndtimeo(&mut self,
700                        sec: libc::time_t,
701                        micro_sec: libc::suseconds_t)
702                        -> Result<(), Error>
703    {
704        #[repr(C, packed)]
705        struct Timeval {
706            tv_sec: libc::time_t,
707            tv_usec: libc::suseconds_t
708        };
709        let data = Timeval {
710            tv_sec: sec,
711            tv_usec: micro_sec
712        };
713
714        let opt_result = unsafe {
715            libc::setsockopt(self.fd,
716                             libc::SOL_SOCKET,
717                             libc::SO_SNDTIMEO,
718                             &data as *const _ as *const c_void,
719                             mem::size_of::<Timeval>() as u32)
720        };
721        if opt_result < 0 {
722            return Err(Error::from_raw_os_error(errno().0 as i32));
723        }
724
725        Ok(())
726    }
727
728    /// Indicates that the rules used in validating addresses supplied in a bind(2) call should
729    /// allow reuse of local addresses. For AF_INET sockets this means that a socket may bind,
730    /// except when there is an active listening socket bound to the address. When the listening
731    /// socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this
732    /// port for any local address. Argument is an integer boolean flag.
733    pub fn set_reuseaddr(&mut self, option: bool) -> Result<(), Error> {
734        let optval: c_int = match option {
735            true => 1,
736            false => 0
737        };
738        let opt_result = unsafe {
739            libc::setsockopt(self.fd,
740                             libc::SOL_SOCKET,
741                             libc::SO_REUSEADDR,
742                             &optval as *const _ as *const c_void,
743                             mem::size_of::<c_int>() as u32)
744        };
745        if opt_result < 0 {
746            return Err(Error::from_raw_os_error(errno().0 as i32));
747        }
748
749        Ok(())
750    }
751
752    /// Sets or gets the maximum socket send buffer in bytes. The kernel doubles this value
753    /// (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this
754    /// doubled value is returned by getsockopt(2). The default value is set by
755    /// the /proc/sys/net/core/wmem_default file and the maximum allowed value is set by
756    /// the /proc/sys/net/core/wmem_max file. The minimum (doubled) value for this option is 2048.
757    pub fn set_sndbuf(&mut self, size: usize) -> Result<(), Error> {
758        let opt_result = unsafe {
759            libc::setsockopt(self.fd,
760                             libc::SOL_SOCKET,
761                             libc::SO_SNDBUF,
762                             &size as *const _ as *const c_void,
763                             mem::size_of::<usize>() as u32)
764        };
765        if opt_result < 0 {
766            return Err(Error::from_raw_os_error(errno().0 as i32));
767        }
768
769        Ok(())
770    }
771
772    /// Using this socket option, a privileged (CAP_NET_ADMIN) process can perform the same task
773    /// as SO_SNDBUF, but the wmem_max limit can be overridden.
774    pub fn set_sndbufforce(&mut self, size: usize) -> Result<(), Error> {
775        self.set_sndbuf(size)
776    }
777
778    /// Enable or disable the receiving of the SO_TIMESTAMP control message. The timestamp control
779    /// message is sent with level SOL_SOCKET and the cmsg_data field is a struct timeval
780    /// indicating the reception time of the last packet passed to the user in this call.
781    /// See cmsg(3) for details on control messages.
782    pub fn set_timestamp(&mut self, option: bool) -> Result<(), Error> {
783        const SO_TIMESTAMP: i32 = 29;
784        let optval: c_int = match option {
785            true => 1,
786            false => 0
787        };
788        let opt_result = unsafe {
789            libc::setsockopt(self.fd,
790                             libc::SOL_SOCKET,
791                             SO_TIMESTAMP,
792                             &optval as *const _ as *const c_void,
793                             mem::size_of::<c_int>() as u32)
794        };
795        if opt_result < 0 {
796            return Err(Error::from_raw_os_error(errno().0 as i32));
797        }
798
799        Ok(())
800    }
801}
802
803impl Read for Socket {
804    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
805        return self.recv(buf, 0);
806    }
807}
808
809impl Write for Socket {
810    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
811        return self.send(buf, 0);
812    }
813    fn flush(&mut self) -> Result<(), Error> {
814        return Ok(());
815    }
816}
817
818impl AsRawFd for Socket {
819    fn as_raw_fd(&self) -> RawFd {
820        self.fd
821    }
822}
823
824unsafe impl Send for Socket {}
825unsafe impl Sync for Socket {}