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 {}