1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 Bindings to libuv, along with the default implementation of `std::rt::rtio`.
15 UV types consist of the event loop (Loop), Watchers, Requests and
18 Watchers and Requests encapsulate pointers to uv *handles*, which have
19 subtyping relationships with each other. This subtyping is reflected
20 in the bindings with explicit or implicit coercions. For example, an
21 upcast from TcpWatcher to StreamWatcher is done with
22 `tcp_watcher.as_stream()`. In other cases a callback on a specific
23 type of watcher will be passed a watcher of a supertype.
25 Currently all use of Request types (connect/write requests) are
26 encapsulated in the bindings and don't need to be dealt with by the
31 Due to the complex lifecycle of uv handles, as well as compiler bugs,
32 this module is not memory safe and requires explicit memory management,
33 via `close` and `delete` methods.
37 use container::Container;
39 use str::raw::from_c_str;
43 use vec::ImmutableVector;
46 use libc::{c_void, c_int, size_t, malloc, free};
49 use unstable::finally::Finally;
50 use rt::io::net::ip::SocketAddr;
54 //#[cfg(test)] use unstable::run_in_bare_thread;
56 pub use self::file::{FsRequest};
57 pub use self::net::{StreamWatcher, TcpWatcher, UdpWatcher};
58 pub use self::idle::IdleWatcher;
59 pub use self::timer::TimerWatcher;
60 pub use self::async::AsyncWatcher;
62 /// The implementation of `rtio` for libuv
65 /// C bindings to libuv
75 /// XXX: Loop(*handle) is buggy with destructors. Normal structs
76 /// with dtors may not be destructured, but tuple structs can,
77 /// but the results are not correct.
79 handle: *uvll::uv_loop_t
82 /// The trait implemented by uv 'watchers' (handles). Watchers are
83 /// non-owning wrappers around the uv handles and are not completely
84 /// safe - there may be multiple instances for a single underlying
85 /// handle. Watchers are generally created, then `start`ed, `stop`ed
86 /// and `close`ed, but due to their complex life cycle may not be
87 /// entirely memory safe if used in unanticipated patterns.
92 /// A type that wraps a native handle
93 pub trait NativeHandle<T> {
94 fn from_native_handle(T) -> Self;
95 fn native_handle(&self) -> T;
99 pub fn new() -> Loop {
100 let handle = unsafe { uvll::loop_new() };
101 assert!(handle.is_not_null());
102 NativeHandle::from_native_handle(handle)
105 pub fn run(&mut self) {
106 unsafe { uvll::run(self.native_handle()) };
109 pub fn close(&mut self) {
110 unsafe { uvll::loop_delete(self.native_handle()) };
114 impl NativeHandle<*uvll::uv_loop_t> for Loop {
115 fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
116 Loop { handle: handle }
118 fn native_handle(&self) -> *uvll::uv_loop_t {
123 // XXX: The uv alloc callback also has a *uv_handle_t arg
124 pub type AllocCallback = ~fn(uint) -> Buf;
125 pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option<UvError>);
126 pub type NullCallback = ~fn();
127 pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
128 pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
129 pub type FsCallback = ~fn(&mut FsRequest, Option<UvError>);
130 pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
131 pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
132 pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, SocketAddr, uint, Option<UvError>);
133 pub type UdpSendCallback = ~fn(UdpWatcher, Option<UvError>);
136 /// Callbacks used by StreamWatchers, set as custom data on the foreign handle.
137 /// XXX: Would be better not to have all watchers allocate room for all callback types.
139 read_cb: Option<ReadCallback>,
140 write_cb: Option<ConnectionCallback>,
141 connect_cb: Option<ConnectionCallback>,
142 close_cb: Option<NullCallback>,
143 alloc_cb: Option<AllocCallback>,
144 idle_cb: Option<IdleCallback>,
145 timer_cb: Option<TimerCallback>,
146 async_cb: Option<AsyncCallback>,
147 udp_recv_cb: Option<UdpReceiveCallback>,
148 udp_send_cb: Option<UdpSendCallback>
151 pub trait WatcherInterop {
152 fn event_loop(&self) -> Loop;
153 fn install_watcher_data(&mut self);
154 fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData;
155 fn drop_watcher_data(&mut self);
158 impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
159 /// Get the uv event loop from a Watcher
160 fn event_loop(&self) -> Loop {
162 let handle = self.native_handle();
163 let loop_ = uvll::get_loop_for_uv_handle(handle);
164 NativeHandle::from_native_handle(loop_)
168 fn install_watcher_data(&mut self) {
170 let data = ~WatcherData {
182 let data = transmute::<~WatcherData, *c_void>(data);
183 uvll::set_data_for_uv_handle(self.native_handle(), data);
187 fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData {
189 let data = uvll::get_data_for_uv_handle(self.native_handle());
190 let data = transmute::<&*c_void, &mut ~WatcherData>(&data);
195 fn drop_watcher_data(&mut self) {
197 let data = uvll::get_data_for_uv_handle(self.native_handle());
198 let _data = transmute::<*c_void, ~WatcherData>(data);
199 uvll::set_data_for_uv_handle(self.native_handle(), null::<()>());
204 // XXX: Need to define the error constants like EOF so they can be
205 // compared to the UvError type
207 pub struct UvError(uvll::uv_err_t);
210 pub fn name(&self) -> ~str {
212 let inner = match self { &UvError(ref a) => a };
213 let name_str = uvll::err_name(inner);
214 assert!(name_str.is_not_null());
219 pub fn desc(&self) -> ~str {
221 let inner = match self { &UvError(ref a) => a };
222 let desc_str = uvll::strerror(inner);
223 assert!(desc_str.is_not_null());
228 pub fn is_eof(&self) -> bool {
229 self.code == uvll::EOF
233 impl ToStr for UvError {
234 fn to_str(&self) -> ~str {
235 fmt!("%s: %s", self.name(), self.desc())
240 fn error_smoke_test() {
241 let err = uvll::uv_err_t { code: 1, sys_errno_: 1 };
242 let err: UvError = UvError(err);
243 assert_eq!(err.to_str(), ~"EOF: end of file");
246 pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
248 let loop_ = watcher.event_loop();
249 UvError(uvll::last_error(loop_.native_handle()))
253 pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
255 // Importing error constants
259 // uv error descriptions are static
260 let c_desc = uvll::strerror(&*uverr);
261 let desc = str::raw::c_str_to_static_slice(c_desc);
263 let kind = match uverr.code {
264 UNKNOWN => OtherIoError,
267 EACCES => PermissionDenied,
268 ECONNREFUSED => ConnectionRefused,
269 ECONNRESET => ConnectionReset,
272 rtdebug!("uverr.code %u", uverr.code as uint);
273 // XXX: Need to map remaining uv error types
286 /// Given a uv handle, convert a callback status to a UvError
287 pub fn status_to_maybe_uv_error_with_loop(
288 loop_: *uvll::uv_loop_t,
289 status: c_int) -> Option<UvError> {
294 rtdebug!("loop: %x", loop_ as uint);
295 let err = uvll::last_error(loop_);
300 /// Given a uv handle, convert a callback status to a UvError
301 pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
302 status: c_int) -> Option<UvError> {
307 rtdebug!("handle: %x", handle.native_handle() as uint);
308 let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
309 status_to_maybe_uv_error_with_loop(loop_, status)
314 /// The uv buffer type
315 pub type Buf = uvll::uv_buf_t;
317 /// Borrow a slice to a Buf
318 pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
319 let data = vec::raw::to_ptr(v);
320 unsafe { uvll::buf_init(data, v.len()) }
323 // XXX: Do these conversions without copying
325 /// Transmute an owned vector to a Buf
326 pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
327 #[fixed_stack_segment]; #[inline(never)];
330 let data = malloc(v.len() as size_t) as *u8;
331 assert!(data.is_not_null());
332 do v.as_imm_buf |b, l| {
333 let data = data as *mut u8;
334 ptr::copy_memory(data, b, l)
336 uvll::buf_init(data, v.len())
340 /// Transmute a Buf that was once a ~[u8] back to ~[u8]
341 pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> {
342 #[fixed_stack_segment]; #[inline(never)];
344 if !(buf.len == 0 && buf.base.is_null()) {
345 let v = unsafe { vec::from_buf(buf.base, buf.len as uint) };
346 unsafe { free(buf.base as *c_void) };
350 rtdebug!("No buffer!");
356 fn test_slice_to_uv_buf() {
357 let slice = [0, .. 20];
358 let buf = slice_to_uv_buf(slice);
360 assert!(buf.len == 20);
363 let base = transmute::<*u8, *mut u8>(buf.base);
365 (*ptr::mut_offset(base, 1)) = 2;
368 assert!(slice[0] == 1);
369 assert!(slice[1] == 2);
374 fn loop_smoke_test() {
375 do run_in_bare_thread {
376 let mut loop_ = Loop::new();