]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/uv/mod.rs
Add externfn macro and correctly label fixed_stack_segments
[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
74 /// XXX: Loop(*handle) is buggy with destructors. Normal structs
75 /// with dtors may not be destructured, but tuple structs can,
76 /// but the results are not correct.
77 pub struct Loop {
78     handle: *uvll::uv_loop_t
79 }
80
81 /// The trait implemented by uv 'watchers' (handles). Watchers are
82 /// non-owning wrappers around the uv handles and are not completely
83 /// safe - there may be multiple instances for a single underlying
84 /// handle.  Watchers are generally created, then `start`ed, `stop`ed
85 /// and `close`ed, but due to their complex life cycle may not be
86 /// entirely memory safe if used in unanticipated patterns.
87 pub trait Watcher { }
88
89 pub trait Request { }
90
91 /// A type that wraps a native handle
92 pub trait NativeHandle<T> {
93     fn from_native_handle(T) -> Self;
94     fn native_handle(&self) -> T;
95 }
96
97 impl Loop {
98     pub fn new() -> Loop {
99         let handle = unsafe { uvll::loop_new() };
100         assert!(handle.is_not_null());
101         NativeHandle::from_native_handle(handle)
102     }
103
104     pub fn run(&mut self) {
105         unsafe { uvll::run(self.native_handle()) };
106     }
107
108     pub fn close(&mut self) {
109         unsafe { uvll::loop_delete(self.native_handle()) };
110     }
111 }
112
113 impl NativeHandle<*uvll::uv_loop_t> for Loop {
114     fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
115         Loop { handle: handle }
116     }
117     fn native_handle(&self) -> *uvll::uv_loop_t {
118         self.handle
119     }
120 }
121
122 // XXX: The uv alloc callback also has a *uv_handle_t arg
123 pub type AllocCallback = ~fn(uint) -> Buf;
124 pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option<UvError>);
125 pub type NullCallback = ~fn();
126 pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
127 pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
128 pub type FsCallback = ~fn(FsRequest, Option<UvError>);
129 pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
130 pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
131 pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, SocketAddr, uint, Option<UvError>);
132 pub type UdpSendCallback = ~fn(UdpWatcher, Option<UvError>);
133
134
135 /// Callbacks used by StreamWatchers, set as custom data on the foreign handle
136 struct WatcherData {
137     read_cb: Option<ReadCallback>,
138     write_cb: Option<ConnectionCallback>,
139     connect_cb: Option<ConnectionCallback>,
140     close_cb: Option<NullCallback>,
141     alloc_cb: Option<AllocCallback>,
142     idle_cb: Option<IdleCallback>,
143     timer_cb: Option<TimerCallback>,
144     async_cb: Option<AsyncCallback>,
145     udp_recv_cb: Option<UdpReceiveCallback>,
146     udp_send_cb: Option<UdpSendCallback>
147 }
148
149 pub trait WatcherInterop {
150     fn event_loop(&self) -> Loop;
151     fn install_watcher_data(&mut self);
152     fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData;
153     fn drop_watcher_data(&mut self);
154 }
155
156 impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
157     /// Get the uv event loop from a Watcher
158     fn event_loop(&self) -> Loop {
159         unsafe {
160             let handle = self.native_handle();
161             let loop_ = uvll::get_loop_for_uv_handle(handle);
162             NativeHandle::from_native_handle(loop_)
163         }
164     }
165
166     fn install_watcher_data(&mut self) {
167         unsafe {
168             let data = ~WatcherData {
169                 read_cb: None,
170                 write_cb: None,
171                 connect_cb: None,
172                 close_cb: None,
173                 alloc_cb: None,
174                 idle_cb: None,
175                 timer_cb: None,
176                 async_cb: None,
177                 udp_recv_cb: None,
178                 udp_send_cb: None
179             };
180             let data = transmute::<~WatcherData, *c_void>(data);
181             uvll::set_data_for_uv_handle(self.native_handle(), data);
182         }
183     }
184
185     fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData {
186         unsafe {
187             let data = uvll::get_data_for_uv_handle(self.native_handle());
188             let data = transmute::<&*c_void, &mut ~WatcherData>(&data);
189             return &mut **data;
190         }
191     }
192
193     fn drop_watcher_data(&mut self) {
194         unsafe {
195             let data = uvll::get_data_for_uv_handle(self.native_handle());
196             let _data = transmute::<*c_void, ~WatcherData>(data);
197             uvll::set_data_for_uv_handle(self.native_handle(), null::<()>());
198         }
199     }
200 }
201
202 // XXX: Need to define the error constants like EOF so they can be
203 // compared to the UvError type
204
205 pub struct UvError(uvll::uv_err_t);
206
207 impl UvError {
208     pub fn name(&self) -> ~str {
209         unsafe {
210             let inner = match self { &UvError(ref a) => a };
211             let name_str = uvll::err_name(inner);
212             assert!(name_str.is_not_null());
213             from_c_str(name_str)
214         }
215     }
216
217     pub fn desc(&self) -> ~str {
218         unsafe {
219             let inner = match self { &UvError(ref a) => a };
220             let desc_str = uvll::strerror(inner);
221             assert!(desc_str.is_not_null());
222             from_c_str(desc_str)
223         }
224     }
225
226     pub fn is_eof(&self) -> bool {
227         self.code == uvll::EOF
228     }
229 }
230
231 impl ToStr for UvError {
232     fn to_str(&self) -> ~str {
233         fmt!("%s: %s", self.name(), self.desc())
234     }
235 }
236
237 #[test]
238 fn error_smoke_test() {
239     let err = uvll::uv_err_t { code: 1, sys_errno_: 1 };
240     let err: UvError = UvError(err);
241     assert_eq!(err.to_str(), ~"EOF: end of file");
242 }
243
244 pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
245     unsafe {
246         let loop_ = watcher.event_loop();
247         UvError(uvll::last_error(loop_.native_handle()))
248     }
249 }
250
251 pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
252     unsafe {
253         // Importing error constants
254         use rt::uv::uvll::*;
255         use rt::io::*;
256
257         // uv error descriptions are static
258         let c_desc = uvll::strerror(&*uverr);
259         let desc = str::raw::c_str_to_static_slice(c_desc);
260
261         let kind = match uverr.code {
262             UNKNOWN => OtherIoError,
263             OK => OtherIoError,
264             EOF => EndOfFile,
265             EACCES => PermissionDenied,
266             ECONNREFUSED => ConnectionRefused,
267             ECONNRESET => ConnectionReset,
268             EPIPE => BrokenPipe,
269             _ => {
270                 rtdebug!("uverr.code %u", uverr.code as uint);
271                 // XXX: Need to map remaining uv error types
272                 OtherIoError
273             }
274         };
275
276         IoError {
277             kind: kind,
278             desc: desc,
279             detail: None
280         }
281     }
282 }
283
284 /// Given a uv handle, convert a callback status to a UvError
285 pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
286                                                                  status: c_int) -> Option<UvError> {
287     if status != -1 {
288         None
289     } else {
290         unsafe {
291             rtdebug!("handle: %x", handle.native_handle() as uint);
292             let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
293             rtdebug!("loop: %x", loop_ as uint);
294             let err = uvll::last_error(loop_);
295             Some(UvError(err))
296         }
297     }
298 }
299
300 /// The uv buffer type
301 pub type Buf = uvll::uv_buf_t;
302
303 /// Borrow a slice to a Buf
304 pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
305     let data = vec::raw::to_ptr(v);
306     unsafe { uvll::buf_init(data, v.len()) }
307 }
308
309 // XXX: Do these conversions without copying
310
311 /// Transmute an owned vector to a Buf
312 pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
313     #[fixed_stack_segment]; #[inline(never)];
314
315     unsafe {
316         let data = malloc(v.len() as size_t) as *u8;
317         assert!(data.is_not_null());
318         do v.as_imm_buf |b, l| {
319             let data = data as *mut u8;
320             ptr::copy_memory(data, b, l)
321         }
322         uvll::buf_init(data, v.len())
323     }
324 }
325
326 /// Transmute a Buf that was once a ~[u8] back to ~[u8]
327 pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> {
328     #[fixed_stack_segment]; #[inline(never)];
329
330     if !(buf.len == 0 && buf.base.is_null()) {
331         let v = unsafe { vec::from_buf(buf.base, buf.len as uint) };
332         unsafe { free(buf.base as *c_void) };
333         return Some(v);
334     } else {
335         // No buffer
336         rtdebug!("No buffer!");
337         return None;
338     }
339 }
340 /*
341 #[test]
342 fn test_slice_to_uv_buf() {
343     let slice = [0, .. 20];
344     let buf = slice_to_uv_buf(slice);
345
346     assert!(buf.len == 20);
347
348     unsafe {
349         let base = transmute::<*u8, *mut u8>(buf.base);
350         (*base) = 1;
351         (*ptr::mut_offset(base, 1)) = 2;
352     }
353
354     assert!(slice[0] == 1);
355     assert!(slice[1] == 2);
356 }
357
358
359 #[test]
360 fn loop_smoke_test() {
361     do run_in_bare_thread {
362         let mut loop_ = Loop::new();
363         loop_.run();
364         loop_.close();
365     }
366 }
367 */