]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/uv/mod.rs
b85b223468e86e617beb1b81f5099f18c459b8ff
[rust.git] / src / libstd / rt / uv / mod.rs
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.
4 //
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.
10
11 /*!
12
13 Bindings to libuv, along with the default implementation of `std::rt::rtio`.
14
15 UV types consist of the event loop (Loop), Watchers, Requests and
16 Callbacks.
17
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.
24
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
27 caller.
28
29 # Safety note
30
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.
34
35 */
36
37 use container::Container;
38 use option::*;
39 use str::raw::from_c_str;
40 use to_str::ToStr;
41 use ptr::RawPtr;
42 use vec;
43 use vec::ImmutableVector;
44 use ptr;
45 use str;
46 use libc::{c_void, c_int, size_t, malloc, free};
47 use cast::transmute;
48 use ptr::null;
49 use unstable::finally::Finally;
50 use rt::io::net::ip::SocketAddr;
51
52 use rt::io::IoError;
53
54 //#[cfg(test)] use unstable::run_in_bare_thread;
55
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;
61
62 /// The implementation of `rtio` for libuv
63 pub mod uvio;
64
65 /// C bindings to libuv
66 pub mod uvll;
67
68 pub mod file;
69 pub mod net;
70 pub mod idle;
71 pub mod timer;
72 pub mod async;
73 pub mod addrinfo;
74
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.
78 pub struct Loop {
79     handle: *uvll::uv_loop_t
80 }
81
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.
88 pub trait Watcher { }
89
90 pub trait Request { }
91
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;
96 }
97
98 impl Loop {
99     pub fn new() -> Loop {
100         let handle = unsafe { uvll::loop_new() };
101         assert!(handle.is_not_null());
102         NativeHandle::from_native_handle(handle)
103     }
104
105     pub fn run(&mut self) {
106         unsafe { uvll::run(self.native_handle()) };
107     }
108
109     pub fn close(&mut self) {
110         unsafe { uvll::loop_delete(self.native_handle()) };
111     }
112 }
113
114 impl NativeHandle<*uvll::uv_loop_t> for Loop {
115     fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
116         Loop { handle: handle }
117     }
118     fn native_handle(&self) -> *uvll::uv_loop_t {
119         self.handle
120     }
121 }
122
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>);
134
135
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.
138 struct WatcherData {
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>
149 }
150
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);
156 }
157
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 {
161         unsafe {
162             let handle = self.native_handle();
163             let loop_ = uvll::get_loop_for_uv_handle(handle);
164             NativeHandle::from_native_handle(loop_)
165         }
166     }
167
168     fn install_watcher_data(&mut self) {
169         unsafe {
170             let data = ~WatcherData {
171                 read_cb: None,
172                 write_cb: None,
173                 connect_cb: None,
174                 close_cb: None,
175                 alloc_cb: None,
176                 idle_cb: None,
177                 timer_cb: None,
178                 async_cb: None,
179                 udp_recv_cb: None,
180                 udp_send_cb: None
181             };
182             let data = transmute::<~WatcherData, *c_void>(data);
183             uvll::set_data_for_uv_handle(self.native_handle(), data);
184         }
185     }
186
187     fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData {
188         unsafe {
189             let data = uvll::get_data_for_uv_handle(self.native_handle());
190             let data = transmute::<&*c_void, &mut ~WatcherData>(&data);
191             return &mut **data;
192         }
193     }
194
195     fn drop_watcher_data(&mut self) {
196         unsafe {
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::<()>());
200         }
201     }
202 }
203
204 // XXX: Need to define the error constants like EOF so they can be
205 // compared to the UvError type
206
207 pub struct UvError(uvll::uv_err_t);
208
209 impl UvError {
210     pub fn name(&self) -> ~str {
211         unsafe {
212             let inner = match self { &UvError(ref a) => a };
213             let name_str = uvll::err_name(inner);
214             assert!(name_str.is_not_null());
215             from_c_str(name_str)
216         }
217     }
218
219     pub fn desc(&self) -> ~str {
220         unsafe {
221             let inner = match self { &UvError(ref a) => a };
222             let desc_str = uvll::strerror(inner);
223             assert!(desc_str.is_not_null());
224             from_c_str(desc_str)
225         }
226     }
227
228     pub fn is_eof(&self) -> bool {
229         self.code == uvll::EOF
230     }
231 }
232
233 impl ToStr for UvError {
234     fn to_str(&self) -> ~str {
235         fmt!("%s: %s", self.name(), self.desc())
236     }
237 }
238
239 #[test]
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");
244 }
245
246 pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
247     unsafe {
248         let loop_ = watcher.event_loop();
249         UvError(uvll::last_error(loop_.native_handle()))
250     }
251 }
252
253 pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
254     unsafe {
255         // Importing error constants
256         use rt::uv::uvll::*;
257         use rt::io::*;
258
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);
262
263         let kind = match uverr.code {
264             UNKNOWN => OtherIoError,
265             OK => OtherIoError,
266             EOF => EndOfFile,
267             EACCES => PermissionDenied,
268             ECONNREFUSED => ConnectionRefused,
269             ECONNRESET => ConnectionReset,
270             EPIPE => BrokenPipe,
271             _ => {
272                 rtdebug!("uverr.code %u", uverr.code as uint);
273                 // XXX: Need to map remaining uv error types
274                 OtherIoError
275             }
276         };
277
278         IoError {
279             kind: kind,
280             desc: desc,
281             detail: None
282         }
283     }
284 }
285
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> {
290     if status != -1 {
291         None
292     } else {
293         unsafe {
294             rtdebug!("loop: %x", loop_ as uint);
295             let err = uvll::last_error(loop_);
296             Some(UvError(err))
297         }
298     }
299 }
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> {
303     if status != -1 {
304         None
305     } else {
306         unsafe {
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)
310         }
311     }
312 }
313
314 /// The uv buffer type
315 pub type Buf = uvll::uv_buf_t;
316
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()) }
321 }
322
323 // XXX: Do these conversions without copying
324
325 /// Transmute an owned vector to a Buf
326 pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
327     #[fixed_stack_segment]; #[inline(never)];
328
329     unsafe {
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)
335         }
336         uvll::buf_init(data, v.len())
337     }
338 }
339
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)];
343
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) };
347         return Some(v);
348     } else {
349         // No buffer
350         rtdebug!("No buffer!");
351         return None;
352     }
353 }
354 /*
355 #[test]
356 fn test_slice_to_uv_buf() {
357     let slice = [0, .. 20];
358     let buf = slice_to_uv_buf(slice);
359
360     assert!(buf.len == 20);
361
362     unsafe {
363         let base = transmute::<*u8, *mut u8>(buf.base);
364         (*base) = 1;
365         (*ptr::mut_offset(base, 1)) = 2;
366     }
367
368     assert!(slice[0] == 1);
369     assert!(slice[1] == 2);
370 }
371
372
373 #[test]
374 fn loop_smoke_test() {
375     do run_in_bare_thread {
376         let mut loop_ = Loop::new();
377         loop_.run();
378         loop_.close();
379     }
380 }
381 */