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