1 use {io, Ready, PollOpt};
2 use libc;
3 use zircon;
4 use std::mem;
5 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
6 use std::ops::{Deref, DerefMut};
7 use std::os::unix::io::RawFd;
8 
9 mod awakener;
10 mod handles;
11 mod eventedfd;
12 mod net;
13 mod ready;
14 mod selector;
15 
16 use self::eventedfd::{EventedFd, EventedFdInner};
17 use self::ready::assert_fuchsia_ready_repr;
18 
new(token: Token, raw_handle: sys::zx_handle_t, rereg_signals: Option<(zircon::Signals, zircon::WaitAsyncOpts)>, ) -> Self19 pub use self::awakener::Awakener;
20 pub use self::handles::EventedHandle;
21 pub use self::net::{TcpListener, TcpStream, UdpSocket};
22 pub use self::selector::{Events, Selector};
23 pub use self::ready::{FuchsiaReady, zx_signals_t};
24 
25 // Set non-blocking (workaround since the std version doesn't work in fuchsia)
26 // TODO: fix the std version and replace this
27 pub fn set_nonblock(fd: RawFd) -> io::Result<()> {
28     cvt(unsafe { libc::fcntl(fd, libc::F_SETFL, libc::O_NONBLOCK) }).map(|_| ())
29 }
30 
rereg_signals(&self) -> Option<(zircon::Signals, zircon::WaitAsyncOpts)>31 /// Workaround until fuchsia's recv_from is fixed
32 unsafe fn recv_from(fd: RawFd, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
33     let flags = 0;
34 
35     let n = cvt(
36         libc::recv(fd,
37                    buf.as_mut_ptr() as *mut libc::c_void,
38                    buf.len(),
39                    flags)
40     )?;
41 
42     // random address-- we don't use it
43     let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
44     Ok((n as usize, addr))
45 }
46 
47 mod sys {
48     #![allow(non_camel_case_types)]
49     use std::os::unix::io::RawFd;
50     pub use zircon_sys::{zx_handle_t, zx_signals_t};
51 
rereg_for_level(&self, port: &zircon::Port)52     // 17 fn pointers we don't need for mio :)
53     pub type fdio_ops_t = [usize; 17];
54 
55     pub type atomic_int_fast32_t = usize; // TODO: https://github.com/rust-lang/libc/issues/631
56 
57     #[repr(C)]
58     pub struct fdio_t {
59         pub ops: *const fdio_ops_t,
60         pub magic: u32,
61         pub refcount: atomic_int_fast32_t,
62         pub dupcount: u32,
63         pub flags: u32,
64     }
65 
66     #[link(name="fdio")]
67     extern {
registration(&self) -> &Mutex<Option<EventedFdRegistration>>68         pub fn __fdio_fd_to_io(fd: RawFd) -> *const fdio_t;
69         pub fn __fdio_release(io: *const fdio_t);
70 
71         pub fn __fdio_wait_begin(
fdio(&self) -> &sys::fdio_t72             io: *const fdio_t,
73             events: u32,
74             handle_out: &mut zx_handle_t,
75             signals_out: &mut zx_signals_t,
76         );
77         pub fn __fdio_wait_end(
drop(&mut self)78             io: *const fdio_t,
79             signals: zx_signals_t,
80             events_out: &mut u32,
81         );
82     }
83 }
84 
85 fn epoll_event_to_ready(epoll: u32) -> Ready {
86     let epoll = epoll as i32; // casts the bits directly
87     let mut kind = Ready::empty();
88 
89     if (epoll & libc::EPOLLIN) != 0 || (epoll & libc::EPOLLPRI) != 0 {
90         kind = kind | Ready::readable();
91     }
92 
93     if (epoll & libc::EPOLLOUT) != 0 {
94         kind = kind | Ready::writable();
95     }
96 
97     kind
98 
99     /* TODO: support?
100     // EPOLLHUP - Usually means a socket error happened
101     if (epoll & libc::EPOLLERR) != 0 {
new(fd: RawFd) -> Self102         kind = kind | UnixReady::error();
103     }
104 
105     if (epoll & libc::EPOLLRDHUP) != 0 || (epoll & libc::EPOLLHUP) != 0 {
106         kind = kind | UnixReady::hup();
107     }
108     */
109 }
110 
111 fn poll_opts_to_wait_async(poll_opts: PollOpt) -> zircon::WaitAsyncOpts {
112     if poll_opts.is_oneshot() {
113         zircon::WaitAsyncOpts::Once
114     } else {
115         zircon::WaitAsyncOpts::Repeating
116     }
117 }
118 
119 trait IsMinusOne {
120     fn is_minus_one(&self) -> bool;
121 }
122 
123 impl IsMinusOne for i32 {
124     fn is_minus_one(&self) -> bool { *self == -1 }
125 }
126 
127 impl IsMinusOne for isize {
128     fn is_minus_one(&self) -> bool { *self == -1 }
register_with_lock( &self, registration: &mut Option<EventedFdRegistration>, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()>129 }
130 
131 fn cvt<T: IsMinusOne>(t: T) -> ::io::Result<T> {
132     use std::io;
133 
134     if t.is_minus_one() {
135         Err(io::Error::last_os_error())
136     } else {
137         Ok(t)
138     }
139 }
140 
141 /// Utility type to prevent the type inside of it from being dropped.
142 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
143 struct DontDrop<T>(Option<T>);
144 
145 impl<T> DontDrop<T> {
146     fn new(t: T) -> DontDrop<T> {
147         DontDrop(Some(t))
148     }
149 
150     fn inner_ref(&self) -> &T {
151         self.0.as_ref().unwrap()
152     }
153 
154     fn inner_mut(&mut self) -> &mut T {
155         self.0.as_mut().unwrap()
156     }
157 }
158 
159 impl<T> Deref for DontDrop<T> {
160     type Target = T;
161     fn deref(&self) -> &Self::Target {
162         self.inner_ref()
163     }
164 }
165 
166 impl<T> DerefMut for DontDrop<T> {
167     fn deref_mut(&mut self) -> &mut Self::Target {
168         self.inner_mut()
169     }
170 }
171 
172 impl<T> Drop for DontDrop<T> {
deregister_with_lock( &self, registration: &mut Option<EventedFdRegistration>, poll: &Poll) -> io::Result<()>173     fn drop(&mut self) {
174         let inner = self.0.take();
175         mem::forget(inner);
176     }
177 }
178