1use std::net;
2use std::io;
3use std::mem;
4use std::ptr;
5use std::cmp;
6
7mod libc {
8 extern crate libc;
9
10 pub use self::libc::{
12 c_int,
13 c_void,
14 c_char,
15 c_long,
16 c_ulong,
17 ssize_t,
18 socklen_t,
19 size_t,
20 sockaddr,
21 sockaddr_storage,
22 sa_family_t,
23 in_port_t,
24 fd_set,
25 timeval,
26 time_t,
27 suseconds_t
28 };
29
30 #[cfg(target_env = "musl")]
31 pub type IoctlRequestT = c_int;
32 #[cfg(not(target_env = "musl"))]
33 pub type IoctlRequestT = c_ulong;
34
35 pub use self::libc::{
36 sockaddr_in,
37 sockaddr_in6,
38
39 in_addr,
40 in6_addr
41 };
42
43 pub type SOCKET = c_int;
44 pub const SOCKET_ERROR: c_int = -1;
45 pub const SOCKET_SHUTDOWN: c_int = libc::ESHUTDOWN;
46
47 pub use self::libc::{
49 EINVAL,
50 FIONBIO,
51 F_GETFD,
52 F_SETFD,
53 FD_CLOEXEC
54 };
55
56 #[cfg(target_os = "macos")]
57 pub use self::libc::{
58 AF_UNIX,
59 AF_INET,
60 AF_INET6,
61 SOCK_STREAM,
62 SOCK_DGRAM,
63 SOCK_RAW,
64 SOCK_SEQPACKET,
65 };
66
67 #[cfg(target_os = "macos")]
68 pub const AF_UNSPEC: c_int = 0;
69 #[cfg(target_os = "macos")]
70 pub const SOCK_NONBLOCK: c_int = 0o0004000;
71 #[cfg(target_os = "macos")]
72 pub const SOCK_CLOEXEC: c_int = 0o2000000;
73
74 #[cfg(not(target_os = "macos"))]
75 pub use self::libc::{
76 AF_UNSPEC,
77 AF_UNIX,
78 AF_INET,
79 AF_INET6,
80 SOCK_STREAM,
81 SOCK_DGRAM,
82 SOCK_RAW,
83 SOCK_SEQPACKET,
84 SOCK_NONBLOCK,
85 SOCK_CLOEXEC
86 };
87
88 #[cfg(target_os = "linux")]
89 pub use self::libc::{
90 AF_NETLINK,
91 AF_PACKET,
92 };
93
94 pub use self::libc::{
96 socket,
97 getsockname,
98 bind,
99 listen,
100 recv,
101 recvfrom,
102 send,
103 sendto,
104 accept,
105 connect,
106 getsockopt,
107 setsockopt,
108 fcntl,
109 ioctl,
110 shutdown,
111 close,
112 select,
113 FD_SET
114 };
115
116 #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd", target_os = "dragonflybsd"))]
117 pub use self::libc::{
118 accept4
119 };
120}
121
122use self::libc::*;
123
124macro_rules! impl_into_trait {
125 ($($t:ty), +) => {
126 $(
127 impl Into<c_int> for $t {
128 fn into(self) -> c_int {
129 self as c_int
130 }
131 }
132 )+
133 };
134}
135
136#[allow(non_snake_case, non_upper_case_globals)]
137pub mod Family {
139 use super::libc::*;
140 pub const UNSPECIFIED: c_int = AF_UNSPEC;
141 pub const UNIX: c_int = AF_UNIX;
142 pub const IPv4: c_int = AF_INET;
143 pub const IPv6: c_int = AF_INET6;
144 #[cfg(target_os = "linux")]
145 pub const NETLINK: c_int = AF_NETLINK;
146 #[cfg(target_os = "linux")]
147 pub const PACKET: c_int = AF_PACKET;
148}
149
150#[allow(non_snake_case)]
151pub mod Type {
153 use super::libc::*;
154 pub const STREAM: c_int = SOCK_STREAM;
155 pub const DATAGRAM: c_int = SOCK_DGRAM;
156 pub const RAW: c_int = SOCK_RAW;
157 pub const SEQPACKET: c_int = SOCK_SEQPACKET;
158 #[cfg(not(target_os = "macos"))]
159 pub const NONBLOCK: c_int = SOCK_NONBLOCK;
161 #[cfg(not(target_os = "macos"))]
162 pub const CLOEXEC: c_int = SOCK_CLOEXEC;
164}
165
166#[allow(non_snake_case, non_upper_case_globals)]
167pub mod Protocol {
169 use super::libc::*;
170 pub const NONE: c_int = 0;
171 pub const ICMPv4: c_int = 1;
172 pub const TCP: c_int = 6;
173 pub const UDP: c_int = 17;
174 pub const ICMPv6: c_int = 58;
175}
176
177#[allow(non_snake_case)]
178bitflags! (pub flags AcceptFlags: c_int {
180 const NON_BLOCKING = SOCK_NONBLOCK,
181 const NON_INHERITABLE = SOCK_CLOEXEC,
182});
183
184#[repr(i32)]
185#[derive(Copy, Clone)]
186pub enum ShutdownType {
188 Receive = 0,
190 Send = 1,
192 Both = 2
194}
195
196impl_into_trait!(ShutdownType);
197
198pub struct Socket {
200 inner: SOCKET
201}
202
203impl Socket {
204 pub fn new(family: c_int, _type: c_int, protocol: c_int) -> io::Result<Socket> {
208 unsafe {
209 match socket(family, _type, protocol) {
210 SOCKET_ERROR => Err(io::Error::last_os_error()),
211 fd => Ok(Socket {
212 inner: fd
213 }),
214 }
215 }
216 }
217
218 pub fn raw(&self) -> SOCKET {
222 self.inner
223 }
224
225 pub fn name(&self) -> io::Result<net::SocketAddr> {
231 unsafe {
232 let mut storage: sockaddr_storage = mem::zeroed();
233 let mut len = mem::size_of_val(&storage) as socklen_t;
234
235 match getsockname(self.inner, &mut storage as *mut _ as *mut _, &mut len) {
236 SOCKET_ERROR => Err(io::Error::last_os_error()),
237 _ => sockaddr_to_addr(&storage, len)
238 }
239 }
240 }
241
242 pub fn bind(&self, addr: &net::SocketAddr) -> io::Result<()> {
244 let (addr, len) = get_raw_addr(addr);
245
246 unsafe {
247 match bind(self.inner, addr, len) {
248 0 => Ok(()),
249 _ => Err(io::Error::last_os_error())
250 }
251 }
252 }
253
254 pub fn listen(&self, backlog: c_int) -> io::Result<()> {
256 unsafe {
257 match listen(self.inner, backlog) {
258 0 => Ok(()),
259 _ => Err(io::Error::last_os_error())
260 }
261 }
262 }
263
264 pub fn recv(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
268 let len = buf.len();
269
270 unsafe {
271 match recv(self.inner, buf.as_mut_ptr() as *mut c_void, len, flags) {
272 -1 => Err(io::Error::last_os_error()),
273 n => Ok(n as usize)
274 }
275 }
276 }
277
278 pub fn recv_from(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, net::SocketAddr)> {
282 let len = buf.len();
283
284 unsafe {
285 let mut storage: sockaddr_storage = mem::zeroed();
286 let mut storage_len = mem::size_of_val(&storage) as socklen_t;
287
288 match recvfrom(self.inner, buf.as_mut_ptr() as *mut c_void, len, flags, &mut storage as *mut _ as *mut _, &mut storage_len) {
289 -1 => Err(io::Error::last_os_error()),
290 n => {
291 let peer_addr = sockaddr_to_addr(&storage, storage_len)?;
292 Ok((n as usize, peer_addr))
293 }
294 }
295 }
296 }
297
298 pub fn send(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
302 let len = buf.len();
303
304 unsafe {
305 match send(self.inner, buf.as_ptr() as *const c_void, len, flags) {
306 -1 => {
307 let error = io::Error::last_os_error();
308 let raw_code = error.raw_os_error().unwrap();
309
310 if raw_code == SOCKET_SHUTDOWN {
311 Ok(0)
312 }
313 else {
314 Err(error)
315 }
316 },
317 n => Ok(n as usize)
318 }
319 }
320 }
321
322 pub fn send_to(&self, buf: &[u8], peer_addr: &net::SocketAddr, flags: c_int) -> io::Result<usize> {
329 let len = buf.len();
330 let (addr, addr_len) = get_raw_addr(peer_addr);
331
332 unsafe {
333 match sendto(self.inner, buf.as_ptr() as *const c_void, len, flags, addr, addr_len) {
334 -1 => {
335 let error = io::Error::last_os_error();
336 let raw_code = error.raw_os_error().unwrap();
337
338 if raw_code == SOCKET_SHUTDOWN {
339 Ok(0)
340 }
341 else {
342 Err(error)
343 }
344 },
345 n => Ok(n as usize)
346 }
347 }
348 }
349
350 pub fn accept4(&self, flags: AcceptFlags) -> io::Result<(Socket, net::SocketAddr)> {
361 #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd", target_os = "dragonflybsd"))]
362 unsafe {
363 let mut storage: sockaddr_storage = mem::zeroed();
364 let mut len = mem::size_of_val(&storage) as socklen_t;
365
366 match accept4(self.inner, &mut storage as *mut _ as *mut _, &mut len, flags.bits()) {
367 SOCKET_ERROR => Err(io::Error::last_os_error()),
368 sock @ _ => {
369 let addr = sockaddr_to_addr(&storage, len)?;
370 Ok((Socket { inner: sock, }, addr))
371 }
372 }
373 }
374
375 #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd", target_os = "dragonflybsd")))]
376 {
377 self.accept().map(|(sock, addr)| {
378 sock.set_blocking(!flags.contains(NON_BLOCKING)).expect("Setting newly obtained client socket blocking mode");
388 sock.set_inheritable(!flags.contains(NON_INHERITABLE)).expect("Setting newly obtained client socket inheritance mode");
389
390 (sock, addr)
391 })
392 }
393 }
394
395
396 pub fn accept(&self) -> io::Result<(Socket, net::SocketAddr)> {
402 unsafe {
403 let mut storage: sockaddr_storage = mem::zeroed();
404 let mut len = mem::size_of_val(&storage) as socklen_t;
405
406 match accept(self.inner, &mut storage as *mut _ as *mut _, &mut len) {
407 SOCKET_ERROR => Err(io::Error::last_os_error()),
408 sock @ _ => {
409 let addr = sockaddr_to_addr(&storage, len)?;
410 Ok((Socket { inner: sock }, addr))
411 }
412 }
413 }
414 }
415
416
417 pub fn connect(&self, addr: &net::SocketAddr) -> io::Result<()> {
419 let (addr, len) = get_raw_addr(addr);
420
421 unsafe {
422 match connect(self.inner, addr, len) {
423 0 => Ok(()),
424 _ => Err(io::Error::last_os_error())
425 }
426 }
427 }
428
429 pub fn get_opt<T>(&self, level: c_int, name: c_int) -> io::Result<T> {
431 unsafe {
432 let mut value: T = mem::zeroed();
433 let value_ptr = &mut value as *mut T as *mut c_void;
434 let mut value_len = mem::size_of::<T>() as socklen_t;
435
436 match getsockopt(self.inner, level, name, value_ptr, &mut value_len) {
437 0 => Ok(value),
438 _ => Err(io::Error::last_os_error())
439 }
440 }
441 }
442
443 pub fn set_opt<T>(&self, level: c_int, name: c_int, value: T) -> io::Result<()> {
447 unsafe {
448 let value = &value as *const T as *const c_void;
449
450 match setsockopt(self.inner, level, name, value, mem::size_of::<T>() as socklen_t) {
451 0 => Ok(()),
452 _ => Err(io::Error::last_os_error())
453 }
454 }
455 }
456
457 pub fn ioctl(&self, request: IoctlRequestT, value: c_ulong) -> io::Result<()> {
459 unsafe {
460 let mut value = value;
461 let value = &mut value as *mut c_ulong;
462
463 match ioctl(self.inner, request, value) {
464 0 => Ok(()),
465 _ => Err(io::Error::last_os_error())
466 }
467 }
468 }
469
470 pub fn set_blocking(&self, value: bool) -> io::Result<()> {
472 self.ioctl(FIONBIO, (!value) as c_ulong)
473 }
474
475
476 pub fn set_inheritable(&self, value: bool) -> io::Result<()> {
488 unsafe {
493 let mut flags: libc::c_int = libc::fcntl(self.inner, libc::F_GETFD);
494 if flags < 0 {
495 return Err(io::Error::last_os_error());
496 }
497
498 if value == true {
499 flags &= !libc::FD_CLOEXEC;
500 } else {
501 flags |= libc::FD_CLOEXEC;
502 }
503
504 if libc::fcntl(self.inner, libc::F_SETFD, flags) < 0 {
505 return Err(io::Error::last_os_error());
506 }
507 }
508
509 Ok(())
510 }
511
512 pub fn get_inheritable(&self) -> io::Result<bool> {
516 unsafe {
517 let flags = libc::fcntl(self.inner, libc::F_GETFD);
518 if flags < 0 {
519 return Err(io::Error::last_os_error());
520 }
521
522 Ok((flags & libc::FD_CLOEXEC) == 0)
523 }
524 }
525
526
527 pub fn shutdown(&self, direction: ShutdownType) -> io::Result<()> {
529 unsafe {
530 match shutdown(self.inner, direction.into()) {
531 0 => Ok(()),
532 _ => Err(io::Error::last_os_error())
533 }
534 }
535 }
536
537 pub fn close(&self) -> io::Result<()> {
542 unsafe {
543 match close(self.inner) {
544 0 => Ok(()),
545 _ => Err(io::Error::last_os_error())
546 }
547 }
548 }
549}
550
551fn get_raw_addr(addr: &net::SocketAddr) -> (*const sockaddr, socklen_t) {
552 match *addr {
553 net::SocketAddr::V4(ref a) => {
554 (a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
555 }
556 net::SocketAddr::V6(ref a) => {
557 (a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
558 }
559 }
560}
561
562fn sockaddr_to_addr(storage: &sockaddr_storage, len: socklen_t) -> io::Result<net::SocketAddr> {
563 match storage.ss_family as c_int {
564 AF_INET => {
565 assert!(len as usize >= mem::size_of::<sockaddr_in>());
566 let storage = unsafe { *(storage as *const _ as *const sockaddr_in) };
567 let address = unsafe { *(&storage.sin_addr.s_addr as *const _ as *const [u8; 4]) };
568 let ip = net::Ipv4Addr::from(address);
569
570 Ok(net::SocketAddr::V4(net::SocketAddrV4::new(ip, storage.sin_port.to_be())))
573 }
574 AF_INET6 => {
575 assert!(len as usize >= mem::size_of::<sockaddr_in6>());
576 let storage = unsafe { *(storage as *const _ as *const sockaddr_in6) };
577 let ip = net::Ipv6Addr::from(storage.sin6_addr.s6_addr.clone());
578
579 Ok(net::SocketAddr::V6(net::SocketAddrV6::new(ip, storage.sin6_port.to_be(), storage.sin6_flowinfo, storage.sin6_scope_id)))
580 }
581 _ => {
582 Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid addr type."))
583 }
584 }
585}
586
587impl Drop for Socket {
588 fn drop(&mut self) {
589 let _ = self.shutdown(ShutdownType::Both);
590 let _ = self.close();
591 }
592}
593
594use std::os::unix::io::{
595 AsRawFd,
596 FromRawFd,
597 IntoRawFd,
598};
599
600impl AsRawFd for Socket {
601 fn as_raw_fd(&self) -> SOCKET {
602 self.inner
603 }
604}
605
606impl FromRawFd for Socket {
607 unsafe fn from_raw_fd(sock: SOCKET) -> Self {
608 Socket {inner: sock}
609 }
610}
611
612impl IntoRawFd for Socket {
613 fn into_raw_fd(self) -> SOCKET {
614 let result = self.inner;
615 mem::forget(self);
616 result
617 }
618}
619
620#[inline]
621fn ms_to_timeval(timeout_ms: u64) -> timeval {
622 timeval {
623 tv_sec: timeout_ms as time_t / 1000,
624 tv_usec: (timeout_ms as suseconds_t % 1000) * 1000
625 }
626}
627
628fn sockets_to_fd_set(sockets: &[&Socket]) -> (c_int, fd_set) {
629 let mut max_fd: c_int = 0;
630 let mut raw_fds: fd_set = unsafe { mem::zeroed() };
631
632 for socket in sockets {
633 max_fd = cmp::max(max_fd, socket.inner);
634 unsafe {
635 FD_SET(socket.inner, &mut raw_fds);
636 }
637 }
638
639 (max_fd, raw_fds)
640}
641
642pub fn select(read_fds: &[&Socket], write_fds: &[&Socket], except_fds: &[&Socket], timeout_ms: Option<u64>) -> io::Result<c_int> {
648 let (max_read_fd, mut raw_read_fds) = sockets_to_fd_set(read_fds);
649 let (max_write_fd, mut raw_write_fds) = sockets_to_fd_set(write_fds);
650 let (max_except_fd, mut raw_except_fds) = sockets_to_fd_set(except_fds);
651
652 let nfds = cmp::max(max_read_fd, cmp::max(max_write_fd, max_except_fd)) + 1;
653
654 unsafe {
655 match libc::select(nfds,
656 if max_read_fd > 0 { &mut raw_read_fds } else { ptr::null_mut() },
657 if max_write_fd > 0 { &mut raw_write_fds } else { ptr::null_mut() },
658 if max_except_fd > 0 { &mut raw_except_fds } else { ptr::null_mut() },
659 if let Some(timeout_ms) = timeout_ms { &mut ms_to_timeval(timeout_ms) } else { ptr::null_mut() } ) {
660 SOCKET_ERROR => Err(io::Error::last_os_error()),
661 result @ _ => Ok(result)
662
663 }
664 }
665}