1#![allow(bad_style, dead_code)]
12
13use std::io;
14use std::mem;
15use std::net::{TcpStream, TcpListener, UdpSocket, Ipv4Addr, Ipv6Addr};
16use std::net::ToSocketAddrs;
17
18use {TcpBuilder, UdpBuilder, FromInner};
19use sys;
20use sys::c;
21use socket;
22
23cfg_if! {
24 if #[cfg(any(target_os = "dragonfly",
25 target_os = "freebsd",
26 target_os = "haiku",
27 target_os = "ios",
28 target_os = "macos",
29 target_os = "netbsd",
30 target_os = "openbsd",
31 target_os = "solaris",
32 target_os = "illumos",
33 target_env = "uclibc"))] {
34 use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
35 use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
36 } else {
37 }
39}
40
41use std::time::Duration;
42
43#[cfg(any(unix, target_os = "wasi"))] use libc::*;
44#[cfg(any(unix))] use std::os::unix::prelude::*;
45#[cfg(target_os = "wasi")] use std::os::wasi::prelude::*;
46#[cfg(unix)] pub type Socket = c_int;
47#[cfg(target_os = "wasi")] pub type Socket = std::os::wasi::io::RawFd;
48#[cfg(windows)] pub type Socket = SOCKET;
49#[cfg(windows)] use std::os::windows::prelude::*;
50#[cfg(any(windows, target_os = "wasi"))] use sys::c::*;
51
52#[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004;
53#[cfg(windows)]
54#[repr(C)]
55struct tcp_keepalive {
56 onoff: c_ulong,
57 keepalivetime: c_ulong,
58 keepaliveinterval: c_ulong,
59}
60
61#[cfg(any(unix, target_os = "wasi"))] fn v(opt: c_int) -> c_int { opt }
62#[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int }
63
64#[cfg(target_os = "wasi")]
65pub fn set_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int,
66 _payload: T) -> io::Result<()> {
67 Ok(())
68}
69
70#[cfg(not(target_os = "wasi"))]
71pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
72 payload: T) -> io::Result<()> {
73 unsafe {
74 let payload = &payload as *const T as *const c_void;
75 try!(::cvt(setsockopt(sock, opt, val, payload as *const _,
76 mem::size_of::<T>() as socklen_t)));
77 }
78 Ok(())
79}
80
81#[cfg(target_os = "wasi")]
82pub fn get_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result<T> {
83 unimplemented!()
84}
85#[cfg(not(target_os = "wasi"))]
86pub fn get_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int) -> io::Result<T> {
87 unsafe {
88 let mut slot: T = mem::zeroed();
89 let mut len = mem::size_of::<T>() as socklen_t;
90 try!(::cvt(getsockopt(sock, opt, val,
91 &mut slot as *mut _ as *mut _,
92 &mut len)));
93 assert_eq!(len as usize, mem::size_of::<T>());
94 Ok(slot)
95 }
96}
97
98pub trait TcpStreamExt {
102 fn set_nodelay(&self, nodelay: bool) -> io::Result<()>;
110
111 fn nodelay(&self) -> io::Result<bool>;
117
118 fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
122
123 fn recv_buffer_size(&self) -> io::Result<usize>;
129
130 fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
134
135 fn send_buffer_size(&self) -> io::Result<usize>;
141
142 fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()>;
155
156 fn keepalive_ms(&self) -> io::Result<Option<u32>>;
163
164 fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()>;
177
178 fn keepalive(&self) -> io::Result<Option<Duration>>;
185
186 fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
193
194 fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
201
202 fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
208
209 fn read_timeout(&self) -> io::Result<Option<Duration>>;
215
216 fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
223
224 fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
231
232 fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
238
239 fn write_timeout(&self) -> io::Result<Option<Duration>>;
245
246 fn set_ttl(&self, ttl: u32) -> io::Result<()>;
251
252 fn ttl(&self) -> io::Result<u32>;
258
259 fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
268
269 fn only_v6(&self) -> io::Result<bool>;
275
276 fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()>;
286
287 fn take_error(&self) -> io::Result<Option<io::Error>>;
293
294 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
299
300 fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
302
303 fn linger(&self) -> io::Result<Option<Duration>>;
305}
306
307pub trait TcpListenerExt {
311 fn set_ttl(&self, ttl: u32) -> io::Result<()>;
317
318 fn ttl(&self) -> io::Result<u32>;
325
326 fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
333
334 fn only_v6(&self) -> io::Result<bool>;
341
342 fn take_error(&self) -> io::Result<Option<io::Error>>;
348
349 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
356
357 fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
359
360 fn linger(&self) -> io::Result<Option<Duration>>;
362}
363
364pub trait UdpSocketExt {
368 fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
372
373 fn recv_buffer_size(&self) -> io::Result<usize>;
379
380 fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
384
385 fn send_buffer_size(&self) -> io::Result<usize>;
391
392 fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
397
398 fn broadcast(&self) -> io::Result<bool>;
405
406 fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>;
411
412 fn multicast_loop_v4(&self) -> io::Result<bool>;
419
420 fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>;
428
429 fn multicast_ttl_v4(&self) -> io::Result<u32>;
436
437 fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>;
439
440 fn multicast_hops_v6(&self) -> io::Result<u32>;
442
443 fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>;
448
449 fn multicast_loop_v6(&self) -> io::Result<bool>;
456
457 fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>;
461
462 fn multicast_if_v4(&self) -> io::Result<Ipv4Addr>;
466
467
468 fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()>;
472
473 fn multicast_if_v6(&self) -> io::Result<u32>;
477
478 fn set_ttl(&self, ttl: u32) -> io::Result<()>;
484
485 fn ttl(&self) -> io::Result<u32>;
492
493 fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()>;
497
498 fn unicast_hops_v6(&self) -> io::Result<u32>;
502
503 fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
510
511 fn only_v6(&self) -> io::Result<bool>;
518
519 fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
527 -> io::Result<()>;
528
529 fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
535 -> io::Result<()>;
536
537 fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
544 -> io::Result<()>;
545
546 fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
553 -> io::Result<()>;
554
555 fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
562
563 fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
570
571 fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
577
578 fn read_timeout(&self) -> io::Result<Option<Duration>>;
584
585 fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
592
593 fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
600
601 fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
607
608 fn write_timeout(&self) -> io::Result<Option<Duration>>;
614
615 fn take_error(&self) -> io::Result<Option<io::Error>>;
621
622 fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()>;
626
627 fn send(&self, buf: &[u8]) -> io::Result<usize>;
632
633 fn recv(&self, buf: &mut [u8]) -> io::Result<usize>;
639
640 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
647}
648
649#[doc(hidden)]
650pub trait AsSock {
651 fn as_sock(&self) -> Socket;
652}
653
654#[cfg(any(unix, target_os = "wasi"))]
655impl<T: AsRawFd> AsSock for T {
656 fn as_sock(&self) -> Socket { self.as_raw_fd() }
657}
658#[cfg(windows)]
659impl<T: AsRawSocket> AsSock for T {
660 fn as_sock(&self) -> Socket { self.as_raw_socket() as Socket }
661}
662
663cfg_if! {
664 if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "nto"))] {
665 use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
666 } else if #[cfg(any(target_os = "haiku", target_os = "netbsd", target_os = "openbsd"))] {
667 use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
668 } else if #[cfg(unix)] {
669 use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
670 } else {
671 }
673}
674
675impl TcpStreamExt for TcpStream {
676
677 fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
678 set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
680 }
681
682 fn recv_buffer_size(&self) -> io::Result<usize> {
683 get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
684 }
685
686 fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
687 set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
688 }
689
690 fn send_buffer_size(&self) -> io::Result<usize> {
691 get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
692 }
693
694 fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
695 set_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY,
696 nodelay as c_int)
697 }
698 fn nodelay(&self) -> io::Result<bool> {
699 get_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY)
700 .map(int2bool)
701 }
702
703 fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
704 self.set_keepalive_ms(keepalive.map(dur2ms))
705 }
706
707 fn keepalive(&self) -> io::Result<Option<Duration>> {
708 self.keepalive_ms().map(|o| o.map(ms2dur))
709 }
710
711 #[cfg(unix)]
712 fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
713 try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE,
714 keepalive.is_some() as c_int));
715 if let Some(dur) = keepalive {
716 try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION,
717 (dur / 1000) as c_int));
718 }
719 Ok(())
720 }
721
722 #[cfg(unix)]
723 fn keepalive_ms(&self) -> io::Result<Option<u32>> {
724 let keepalive = try!(get_opt::<c_int>(self.as_sock(), SOL_SOCKET,
725 SO_KEEPALIVE));
726 if keepalive == 0 {
727 return Ok(None)
728 }
729 let secs = try!(get_opt::<c_int>(self.as_sock(), v(IPPROTO_TCP),
730 KEEPALIVE_OPTION));
731 Ok(Some((secs as u32) * 1000))
732 }
733
734 #[cfg(target_os = "wasi")]
735 fn set_keepalive_ms(&self, _keepalive: Option<u32>) -> io::Result<()> {
736 unimplemented!()
737 }
738
739 #[cfg(target_os = "wasi")]
740 fn keepalive_ms(&self) -> io::Result<Option<u32>> {
741 unimplemented!()
742 }
743
744 #[cfg(windows)]
745 fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
746 let ms = keepalive.unwrap_or(INFINITE);
747 let ka = tcp_keepalive {
748 onoff: keepalive.is_some() as c_ulong,
749 keepalivetime: ms as c_ulong,
750 keepaliveinterval: ms as c_ulong,
751 };
752 unsafe {
753 ::cvt_win(WSAIoctl(self.as_sock(),
754 SIO_KEEPALIVE_VALS,
755 &ka as *const _ as *mut _,
756 mem::size_of_val(&ka) as DWORD,
757 0 as *mut _,
758 0,
759 0 as *mut _,
760 0 as *mut _,
761 None)).map(|_| ())
762 }
763 }
764
765 #[cfg(windows)]
766 fn keepalive_ms(&self) -> io::Result<Option<u32>> {
767 let mut ka = tcp_keepalive {
768 onoff: 0,
769 keepalivetime: 0,
770 keepaliveinterval: 0,
771 };
772 unsafe {
773 try!(::cvt_win(WSAIoctl(self.as_sock(),
774 SIO_KEEPALIVE_VALS,
775 0 as *mut _,
776 0,
777 &mut ka as *mut _ as *mut _,
778 mem::size_of_val(&ka) as DWORD,
779 0 as *mut _,
780 0 as *mut _,
781 None)));
782 }
783 Ok({
784 if ka.onoff == 0 {
785 None
786 } else {
787 timeout2ms(ka.keepaliveinterval as DWORD)
788 }
789 })
790 }
791
792 fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
793 set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
794 ms2timeout(dur))
795 }
796
797 fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
798 get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
799 .map(timeout2ms)
800 }
801
802 fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
803 set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
804 ms2timeout(dur))
805 }
806
807 fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
808 get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
809 .map(timeout2ms)
810 }
811
812 fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
813 self.set_read_timeout_ms(dur.map(dur2ms))
814 }
815
816 fn read_timeout(&self) -> io::Result<Option<Duration>> {
817 self.read_timeout_ms().map(|o| o.map(ms2dur))
818 }
819
820 fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
821 self.set_write_timeout_ms(dur.map(dur2ms))
822 }
823
824 fn write_timeout(&self) -> io::Result<Option<Duration>> {
825 self.write_timeout_ms().map(|o| o.map(ms2dur))
826 }
827
828 fn set_ttl(&self, ttl: u32) -> io::Result<()> {
829 set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
830 }
831
832 fn ttl(&self) -> io::Result<u32> {
833 get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
834 .map(|b| b as u32)
835 }
836
837 fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
838 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
839 }
840
841 fn only_v6(&self) -> io::Result<bool> {
842 get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
843 }
844
845 fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()> {
846 do_connect(self.as_sock(), addr)
847 }
848
849 fn take_error(&self) -> io::Result<Option<io::Error>> {
850 get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
851 }
852
853 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
854 set_nonblocking(self.as_sock(), nonblocking)
855 }
856
857 fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
858 set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
859 }
860
861 fn linger(&self) -> io::Result<Option<Duration>> {
862 get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
863 }
864}
865
866#[cfg(any(unix, target_os = "wasi"))]
867fn ms2timeout(dur: Option<u32>) -> timeval {
868 match dur {
870 Some(d) => timeval {
871 tv_sec: (d / 1000) as time_t,
872 tv_usec: (d % 1000) as suseconds_t,
873 },
874 None => timeval { tv_sec: 0, tv_usec: 0 },
875 }
876}
877
878#[cfg(any(unix, target_os = "wasi"))]
879fn timeout2ms(dur: timeval) -> Option<u32> {
880 if dur.tv_sec == 0 && dur.tv_usec == 0 {
881 None
882 } else {
883 Some(dur.tv_sec as u32 * 1000 + dur.tv_usec as u32 / 1000)
884 }
885}
886
887#[cfg(windows)]
888fn ms2timeout(dur: Option<u32>) -> DWORD {
889 dur.unwrap_or(0)
890}
891
892#[cfg(windows)]
893fn timeout2ms(dur: DWORD) -> Option<u32> {
894 if dur == 0 {
895 None
896 } else {
897 Some(dur)
898 }
899}
900
901fn linger2dur(linger_opt: linger) -> Option<Duration> {
902 if linger_opt.l_onoff == 0 {
903 None
904 }
905 else {
906 Some(Duration::from_secs(linger_opt.l_linger as u64))
907 }
908}
909
910#[cfg(windows)]
911fn dur2linger(dur: Option<Duration>) -> linger {
912 match dur {
913 Some(d) => {
914 linger {
915 l_onoff: 1,
916 l_linger: d.as_secs() as u16,
917 }
918 },
919 None => linger { l_onoff: 0, l_linger: 0 },
920 }
921}
922
923#[cfg(any(unix, target_os = "wasi"))]
924fn dur2linger(dur: Option<Duration>) -> linger {
925 match dur {
926 Some(d) => {
927 linger {
928 l_onoff: 1,
929 l_linger: d.as_secs() as c_int,
930 }
931 },
932 None => linger { l_onoff: 0, l_linger: 0 },
933 }
934}
935
936fn ms2dur(ms: u32) -> Duration {
937 Duration::new((ms as u64) / 1000, (ms as u32) % 1000 * 1_000_000)
938}
939
940fn dur2ms(dur: Duration) -> u32 {
941 (dur.as_secs() as u32 * 1000) + (dur.subsec_nanos() / 1_000_000)
942}
943
944pub fn int2bool(n: c_int) -> bool {
945 if n == 0 {false} else {true}
946}
947
948pub fn int2usize(n: c_int) -> usize {
949 n as usize
951}
952
953pub fn int2err(n: c_int) -> Option<io::Error> {
954 if n == 0 {
955 None
956 } else {
957 Some(io::Error::from_raw_os_error(n as i32))
958 }
959}
960
961impl UdpSocketExt for UdpSocket {
962
963 fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
964 set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
965 }
966
967 fn recv_buffer_size(&self) -> io::Result<usize> {
968 get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
969 }
970
971 fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
972 set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
973 }
974
975 fn send_buffer_size(&self) -> io::Result<usize> {
976 get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
977 }
978
979 fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
980 set_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST,
981 broadcast as c_int)
982 }
983 fn broadcast(&self) -> io::Result<bool> {
984 get_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST)
985 .map(int2bool)
986 }
987 fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
988 set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP,
989 multicast_loop_v4 as c_int)
990 }
991 fn multicast_loop_v4(&self) -> io::Result<bool> {
992 get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP)
993 .map(int2bool)
994 }
995
996 fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
997 set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
998 multicast_ttl_v4 as c_int)
999 }
1000
1001 fn multicast_ttl_v4(&self) -> io::Result<u32> {
1002 get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL)
1003 .map(|b| b as u32)
1004 }
1005
1006 fn set_multicast_hops_v6(&self, _hops: u32) -> io::Result<()> {
1007 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS,
1008 _hops as c_int)
1009 }
1010
1011 fn multicast_hops_v6(&self) -> io::Result<u32> {
1012 get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS)
1013 .map(|b| b as u32)
1014 }
1015
1016 fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
1017 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP,
1018 multicast_loop_v6 as c_int)
1019 }
1020 fn multicast_loop_v6(&self) -> io::Result<bool> {
1021 get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP)
1022 .map(int2bool)
1023 }
1024
1025 fn set_multicast_if_v4(&self, _interface: &Ipv4Addr) -> io::Result<()> {
1026 set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF, ip2in_addr(_interface))
1027 }
1028
1029 fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
1030 get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF).map(in_addr2ip)
1031 }
1032
1033 fn set_multicast_if_v6(&self, _interface: u32) -> io::Result<()> {
1034 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF, to_ipv6mr_interface(_interface))
1035 }
1036
1037 fn multicast_if_v6(&self) -> io::Result<u32> {
1038 get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF).map(|b| b as u32)
1039 }
1040
1041 fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1042 set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1043 }
1044
1045 fn ttl(&self) -> io::Result<u32> {
1046 get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
1047 .map(|b| b as u32)
1048 }
1049
1050 fn set_unicast_hops_v6(&self, _ttl: u32) -> io::Result<()> {
1051 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_UNICAST_HOPS, _ttl as c_int)
1052 }
1053
1054 fn unicast_hops_v6(&self) -> io::Result<u32> {
1055 get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IPV6_UNICAST_HOPS)
1056 .map(|b| b as u32)
1057 }
1058
1059 fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1060 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1061 }
1062
1063 fn only_v6(&self) -> io::Result<bool> {
1064 get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
1065 }
1066
1067 fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
1068 -> io::Result<()> {
1069 let mreq = ip_mreq {
1070 imr_multiaddr: ip2in_addr(multiaddr),
1071 imr_interface: ip2in_addr(interface),
1072 };
1073 set_opt(self.as_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
1074 }
1075
1076 #[cfg(not(target_os = "nto"))]
1077 fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
1078 -> io::Result<()> {
1079 let mreq = ipv6_mreq {
1080 ipv6mr_multiaddr: ip2in6_addr(multiaddr),
1081 ipv6mr_interface: to_ipv6mr_interface(interface),
1082 };
1083 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_ADD_MEMBERSHIP,
1084 mreq)
1085 }
1086
1087 #[cfg(target_os = "nto")]
1088 fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
1089 -> io::Result<()> {
1090 Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform"))
1091 }
1092
1093 fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
1094 -> io::Result<()> {
1095 let mreq = ip_mreq {
1096 imr_multiaddr: ip2in_addr(multiaddr),
1097 imr_interface: ip2in_addr(interface),
1098 };
1099 set_opt(self.as_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)
1100 }
1101
1102 #[cfg(not(target_os = "nto"))]
1103 fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
1104 -> io::Result<()> {
1105 let mreq = ipv6_mreq {
1106 ipv6mr_multiaddr: ip2in6_addr(multiaddr),
1107 ipv6mr_interface: to_ipv6mr_interface(interface),
1108 };
1109 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_DROP_MEMBERSHIP,
1110 mreq)
1111 }
1112
1113 #[cfg(target_os = "nto")]
1114 fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
1115 -> io::Result<()> {
1116 Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform"))
1117 }
1118
1119 fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
1120 set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
1121 ms2timeout(dur))
1122 }
1123
1124 fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
1125 get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
1126 .map(timeout2ms)
1127 }
1128
1129 fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
1130 set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
1131 ms2timeout(dur))
1132 }
1133
1134 fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
1135 get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
1136 .map(timeout2ms)
1137 }
1138
1139 fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1140 self.set_read_timeout_ms(dur.map(dur2ms))
1141 }
1142
1143 fn read_timeout(&self) -> io::Result<Option<Duration>> {
1144 self.read_timeout_ms().map(|o| o.map(ms2dur))
1145 }
1146
1147 fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1148 self.set_write_timeout_ms(dur.map(dur2ms))
1149 }
1150
1151 fn write_timeout(&self) -> io::Result<Option<Duration>> {
1152 self.write_timeout_ms().map(|o| o.map(ms2dur))
1153 }
1154
1155 fn take_error(&self) -> io::Result<Option<io::Error>> {
1156 get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1157 }
1158
1159 fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
1160 do_connect(self.as_sock(), addr)
1161 }
1162
1163 #[cfg(unix)]
1164 fn send(&self, buf: &[u8]) -> io::Result<usize> {
1165 unsafe {
1166 ::cvt(send(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len(), 0)).map(|n| n as usize)
1167 }
1168 }
1169
1170 #[cfg(target_os = "wasi")]
1171 fn send(&self, buf: &[u8]) -> io::Result<usize> {
1172 let _so_datalen: *mut sys::c::size_t = &mut 0;
1173 unsafe {
1174 let _errno = libc::__wasi_sock_send(
1175 self.as_sock() as libc::__wasi_fd_t,
1176 buf.as_ptr() as *const _,
1177 buf.len(),
1178 0,
1179 _so_datalen,
1180 );
1181 Ok((*_so_datalen) as usize)
1183 }
1184 }
1185
1186 #[cfg(windows)]
1187 fn send(&self, buf: &[u8]) -> io::Result<usize> {
1188 let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
1189 let buf = &buf[..len];
1190 unsafe {
1191 ::cvt(send(self.as_sock(), buf.as_ptr() as *const _, len as c_int, 0))
1192 .map(|n| n as usize)
1193 }
1194 }
1195
1196 #[cfg(unix)]
1197 fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1198 unsafe {
1199 ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0))
1200 .map(|n| n as usize)
1201 }
1202 }
1203
1204 #[cfg(target_os = "wasi")]
1205 fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1206 let _ro_datalen: *mut sys::c::size_t = &mut 0;
1207 let _ro_flags: *mut sys::c::__wasi_roflags_t = &mut 0;
1208 unsafe {
1209 let _errno = __wasi_sock_recv(
1210 self.as_sock(),
1211 buf.as_mut_ptr() as *mut _,
1212 buf.len(),
1213 0,
1214 _ro_datalen,
1215 _ro_flags,
1216 );
1217 Ok((*_ro_datalen) as usize)
1219 }
1220 }
1221
1222 #[cfg(windows)]
1223 fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1224 let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
1225 let buf = &mut buf[..len];
1226 unsafe {
1227 ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len() as c_int, 0))
1228 .map(|n| n as usize)
1229 }
1230 }
1231
1232 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1233 set_nonblocking(self.as_sock(), nonblocking)
1234 }
1235}
1236
1237fn do_connect<A: ToSocketAddrs>(sock: Socket, addr: A) -> io::Result<()> {
1238 let err = io::Error::new(io::ErrorKind::Other,
1239 "no socket addresses resolved");
1240 let addrs = try!(addr.to_socket_addrs());
1241 let sys = sys::Socket::from_inner(sock);
1242 let sock = socket::Socket::from_inner(sys);
1243 let ret = addrs.fold(Err(err), |prev, addr| {
1244 prev.or_else(|_| sock.connect(&addr))
1245 });
1246 mem::forget(sock);
1247 return ret
1248}
1249
1250#[cfg(unix)]
1251fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
1252 let mut nonblocking = nonblocking as c_ulong;
1253 ::cvt(unsafe {
1254 ioctl(sock, FIONBIO, &mut nonblocking)
1255 }).map(|_| ())
1256}
1257
1258#[cfg(target_os = "wasi")]
1259fn set_nonblocking(_sock: Socket, _nonblocking: bool) -> io::Result<()> {
1260 Ok(())
1261}
1262
1263#[cfg(windows)]
1264fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
1265 let mut nonblocking = nonblocking as c_ulong;
1266 ::cvt(unsafe {
1267 ioctlsocket(sock, FIONBIO as c_int, &mut nonblocking)
1268 }).map(|_| ())
1269}
1270
1271#[cfg(any(unix, target_os = "wasi"))]
1272fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
1273 let oct = ip.octets();
1274 in_addr {
1275 s_addr: ::hton(((oct[0] as u32) << 24) |
1276 ((oct[1] as u32) << 16) |
1277 ((oct[2] as u32) << 8) |
1278 ((oct[3] as u32) << 0)),
1279 }
1280}
1281
1282#[cfg(windows)]
1283fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
1284 let oct = ip.octets();
1285 unsafe {
1286 let mut S_un: in_addr_S_un = mem::zeroed();
1287 *S_un.S_addr_mut() = ::hton(((oct[0] as u32) << 24) |
1288 ((oct[1] as u32) << 16) |
1289 ((oct[2] as u32) << 8) |
1290 ((oct[3] as u32) << 0));
1291 in_addr {
1292 S_un: S_un,
1293 }
1294 }
1295}
1296
1297fn in_addr2ip(ip: &in_addr) -> Ipv4Addr {
1298 let h_addr = c::in_addr_to_u32(ip);
1299
1300 let a: u8 = (h_addr >> 24) as u8;
1301 let b: u8 = (h_addr >> 16) as u8;
1302 let c: u8 = (h_addr >> 8) as u8;
1303 let d: u8 = (h_addr >> 0) as u8;
1304
1305 Ipv4Addr::new(a,b,c,d)
1306}
1307
1308#[cfg(target_os = "android")]
1309fn to_ipv6mr_interface(value: u32) -> c_int {
1310 value as c_int
1311}
1312
1313#[cfg(not(target_os = "android"))]
1314fn to_ipv6mr_interface(value: u32) -> c_uint {
1315 value as c_uint
1316}
1317
1318fn ip2in6_addr(ip: &Ipv6Addr) -> in6_addr {
1319 let mut ret: in6_addr = unsafe { mem::zeroed() };
1320 let seg = ip.segments();
1321 let bytes = [
1322 (seg[0] >> 8) as u8,
1323 (seg[0] >> 0) as u8,
1324 (seg[1] >> 8) as u8,
1325 (seg[1] >> 0) as u8,
1326 (seg[2] >> 8) as u8,
1327 (seg[2] >> 0) as u8,
1328 (seg[3] >> 8) as u8,
1329 (seg[3] >> 0) as u8,
1330 (seg[4] >> 8) as u8,
1331 (seg[4] >> 0) as u8,
1332 (seg[5] >> 8) as u8,
1333 (seg[5] >> 0) as u8,
1334 (seg[6] >> 8) as u8,
1335 (seg[6] >> 0) as u8,
1336 (seg[7] >> 8) as u8,
1337 (seg[7] >> 0) as u8,
1338 ];
1339 #[cfg(windows)] unsafe { *ret.u.Byte_mut() = bytes; }
1340 #[cfg(not(windows))] { ret.s6_addr = bytes; }
1341
1342 return ret
1343}
1344
1345impl TcpListenerExt for TcpListener {
1346 fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1347 set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1348 }
1349
1350 fn ttl(&self) -> io::Result<u32> {
1351 get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
1352 .map(|b| b as u32)
1353 }
1354
1355 fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1356 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1357 }
1358
1359 fn only_v6(&self) -> io::Result<bool> {
1360 get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
1361 }
1362
1363 fn take_error(&self) -> io::Result<Option<io::Error>> {
1364 get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1365 }
1366
1367 fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1368 set_nonblocking(self.as_sock(), nonblocking)
1369 }
1370
1371 fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
1372 set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
1373 }
1374
1375 fn linger(&self) -> io::Result<Option<Duration>> {
1376 get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
1377 }
1378}
1379
1380impl TcpBuilder {
1381 pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
1387 set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1388 .map(|()| self)
1389 }
1390
1391 pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
1397 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1398 .map(|()| self)
1399 }
1400
1401 pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
1407 set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
1408 reuse as c_int).map(|()| self)
1409 }
1410
1411 pub fn get_reuse_address(&self) -> io::Result<bool> {
1413 get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
1414 }
1415
1416 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1422 get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1423 }
1424
1425 fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
1427 set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
1428 }
1429
1430 fn linger(&self) -> io::Result<Option<Duration>> {
1432 get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
1433 }
1434}
1435
1436impl UdpBuilder {
1437 pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
1443 set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1444 .map(|()| self)
1445 }
1446
1447 pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
1453 set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1454 .map(|()| self)
1455 }
1456
1457 pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
1463 set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
1464 reuse as c_int).map(|()| self)
1465 }
1466
1467 pub fn get_reuse_address(&self) -> io::Result<bool> {
1469 get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
1470 }
1471
1472 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1478 get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1479 }
1480}