]> git.lizzy.rs Git - rust.git/blob - src/librustuv/lib.rs
rand: Use fill() instead of read()
[rust.git] / src / librustuv / lib.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 #[crate_id = "rustuv#0.10-pre"];
38 #[license = "MIT/ASL2"];
39 #[crate_type = "rlib"];
40 #[crate_type = "dylib"];
41
42 #[feature(macro_rules)];
43 #[deny(unused_result, unused_must_use)];
44 #[allow(visible_private_types)];
45 #[allow(deprecated_owned_vector)]; // NOTE: remove after stage0
46
47 #[cfg(test)] extern crate green;
48 #[cfg(test)] extern crate realrustuv = "rustuv";
49
50 use std::cast;
51 use std::fmt;
52 use std::io::IoError;
53 use std::io;
54 use std::libc::{c_int, c_void};
55 use std::ptr::null;
56 use std::ptr;
57 use std::rt::local::Local;
58 use std::rt::task::{BlockedTask, Task};
59 use std::str::raw::from_c_str;
60 use std::str;
61 use std::task;
62
63 pub use self::async::AsyncWatcher;
64 pub use self::file::{FsRequest, FileWatcher};
65 pub use self::idle::IdleWatcher;
66 pub use self::net::{TcpWatcher, TcpListener, TcpAcceptor, UdpWatcher};
67 pub use self::pipe::{PipeWatcher, PipeListener, PipeAcceptor};
68 pub use self::process::Process;
69 pub use self::signal::SignalWatcher;
70 pub use self::timer::TimerWatcher;
71 pub use self::tty::TtyWatcher;
72
73 // Run tests with libgreen instead of libnative.
74 //
75 // FIXME: This egregiously hacks around starting the test runner in a different
76 //        threading mode than the default by reaching into the auto-generated
77 //        '__test' module.
78 #[cfg(test)] #[start]
79 fn start(argc: int, argv: **u8) -> int {
80     green::start(argc, argv, __test::main)
81 }
82
83 mod macros;
84
85 mod access;
86 mod homing;
87 mod queue;
88 mod rc;
89
90 /// The implementation of `rtio` for libuv
91 pub mod uvio;
92
93 /// C bindings to libuv
94 pub mod uvll;
95
96 pub mod file;
97 pub mod net;
98 pub mod idle;
99 pub mod timer;
100 pub mod async;
101 pub mod addrinfo;
102 pub mod process;
103 pub mod pipe;
104 pub mod tty;
105 pub mod signal;
106 pub mod stream;
107
108 /// A type that wraps a uv handle
109 pub trait UvHandle<T> {
110     fn uv_handle(&self) -> *T;
111
112     fn uv_loop(&self) -> Loop {
113         Loop::wrap(unsafe { uvll::get_loop_for_uv_handle(self.uv_handle()) })
114     }
115
116     // FIXME(#8888) dummy self
117     fn alloc(_: Option<Self>, ty: uvll::uv_handle_type) -> *T {
118         unsafe {
119             let handle = uvll::malloc_handle(ty);
120             assert!(!handle.is_null());
121             handle as *T
122         }
123     }
124
125     unsafe fn from_uv_handle<'a>(h: &'a *T) -> &'a mut Self {
126         cast::transmute(uvll::get_data_for_uv_handle(*h))
127     }
128
129     fn install(~self) -> ~Self {
130         unsafe {
131             let myptr = cast::transmute::<&~Self, &*u8>(&self);
132             uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
133         }
134         self
135     }
136
137     fn close_async_(&mut self) {
138         // we used malloc to allocate all handles, so we must always have at
139         // least a callback to free all the handles we allocated.
140         extern fn close_cb(handle: *uvll::uv_handle_t) {
141             unsafe { uvll::free_handle(handle) }
142         }
143
144         unsafe {
145             uvll::set_data_for_uv_handle(self.uv_handle(), null::<()>());
146             uvll::uv_close(self.uv_handle() as *uvll::uv_handle_t, close_cb)
147         }
148     }
149
150     fn close(&mut self) {
151         let mut slot = None;
152
153         unsafe {
154             uvll::uv_close(self.uv_handle() as *uvll::uv_handle_t, close_cb);
155             uvll::set_data_for_uv_handle(self.uv_handle(), ptr::null::<()>());
156
157             wait_until_woken_after(&mut slot, &self.uv_loop(), || {
158                 uvll::set_data_for_uv_handle(self.uv_handle(), &slot);
159             })
160         }
161
162         extern fn close_cb(handle: *uvll::uv_handle_t) {
163             unsafe {
164                 let data = uvll::get_data_for_uv_handle(handle);
165                 uvll::free_handle(handle);
166                 if data == ptr::null() { return }
167                 let slot: &mut Option<BlockedTask> = cast::transmute(data);
168                 wakeup(slot);
169             }
170         }
171     }
172 }
173
174 pub struct ForbidSwitch {
175     priv msg: &'static str,
176     priv io: uint,
177 }
178
179 impl ForbidSwitch {
180     fn new(s: &'static str) -> ForbidSwitch {
181         ForbidSwitch {
182             msg: s,
183             io: homing::local_id(),
184         }
185     }
186 }
187
188 impl Drop for ForbidSwitch {
189     fn drop(&mut self) {
190         assert!(self.io == homing::local_id(),
191                 "didnt want a scheduler switch: {}",
192                 self.msg);
193     }
194 }
195
196 pub struct ForbidUnwind {
197     msg: &'static str,
198     failing_before: bool,
199 }
200
201 impl ForbidUnwind {
202     fn new(s: &'static str) -> ForbidUnwind {
203         ForbidUnwind {
204             msg: s, failing_before: task::failing(),
205         }
206     }
207 }
208
209 impl Drop for ForbidUnwind {
210     fn drop(&mut self) {
211         assert!(self.failing_before == task::failing(),
212                 "didnt want an unwind during: {}", self.msg);
213     }
214 }
215
216 fn wait_until_woken_after(slot: *mut Option<BlockedTask>,
217                           loop_: &Loop,
218                           f: ||) {
219     let _f = ForbidUnwind::new("wait_until_woken_after");
220     unsafe {
221         assert!((*slot).is_none());
222         let task: ~Task = Local::take();
223         loop_.modify_blockers(1);
224         task.deschedule(1, |task| {
225             *slot = Some(task);
226             f();
227             Ok(())
228         });
229         loop_.modify_blockers(-1);
230     }
231 }
232
233 fn wakeup(slot: &mut Option<BlockedTask>) {
234     assert!(slot.is_some());
235     let _ = slot.take_unwrap().wake().map(|t| t.reawaken());
236 }
237
238 pub struct Request {
239     handle: *uvll::uv_req_t,
240     priv defused: bool,
241 }
242
243 impl Request {
244     pub fn new(ty: uvll::uv_req_type) -> Request {
245         unsafe {
246             let handle = uvll::malloc_req(ty);
247             uvll::set_data_for_req(handle, null::<()>());
248             Request::wrap(handle)
249         }
250     }
251
252     pub fn wrap(handle: *uvll::uv_req_t) -> Request {
253         Request { handle: handle, defused: false }
254     }
255
256     pub fn set_data<T>(&self, t: *T) {
257         unsafe { uvll::set_data_for_req(self.handle, t) }
258     }
259
260     pub unsafe fn get_data<T>(&self) -> &'static mut T {
261         let data = uvll::get_data_for_req(self.handle);
262         assert!(data != null());
263         cast::transmute(data)
264     }
265
266     // This function should be used when the request handle has been given to an
267     // underlying uv function, and the uv function has succeeded. This means
268     // that uv will at some point invoke the callback, and in the meantime we
269     // can't deallocate the handle because libuv could be using it.
270     //
271     // This is still a problem in blocking situations due to linked failure. In
272     // the connection callback the handle should be re-wrapped with the `wrap`
273     // function to ensure its destruction.
274     pub fn defuse(&mut self) {
275         self.defused = true;
276     }
277 }
278
279 impl Drop for Request {
280     fn drop(&mut self) {
281         if !self.defused {
282             unsafe { uvll::free_req(self.handle) }
283         }
284     }
285 }
286
287 /// FIXME: Loop(*handle) is buggy with destructors. Normal structs
288 /// with dtors may not be destructured, but tuple structs can,
289 /// but the results are not correct.
290 pub struct Loop {
291     priv handle: *uvll::uv_loop_t
292 }
293
294 impl Loop {
295     pub fn new() -> Loop {
296         let handle = unsafe { uvll::loop_new() };
297         assert!(handle.is_not_null());
298         unsafe { uvll::set_data_for_uv_loop(handle, 0 as *c_void) }
299         Loop::wrap(handle)
300     }
301
302     pub fn wrap(handle: *uvll::uv_loop_t) -> Loop { Loop { handle: handle } }
303
304     pub fn run(&mut self) {
305         assert_eq!(unsafe { uvll::uv_run(self.handle, uvll::RUN_DEFAULT) }, 0);
306     }
307
308     pub fn close(&mut self) {
309         unsafe { uvll::uv_loop_delete(self.handle) };
310     }
311
312     // The 'data' field of the uv_loop_t is used to count the number of tasks
313     // that are currently blocked waiting for I/O to complete.
314     fn modify_blockers(&self, amt: uint) {
315         unsafe {
316             let cur = uvll::get_data_for_uv_loop(self.handle) as uint;
317             uvll::set_data_for_uv_loop(self.handle, (cur + amt) as *c_void)
318         }
319     }
320
321     fn get_blockers(&self) -> uint {
322         unsafe { uvll::get_data_for_uv_loop(self.handle) as uint }
323     }
324 }
325
326 // FIXME: Need to define the error constants like EOF so they can be
327 // compared to the UvError type
328
329 pub struct UvError(c_int);
330
331 impl UvError {
332     pub fn name(&self) -> ~str {
333         unsafe {
334             let inner = match self { &UvError(a) => a };
335             let name_str = uvll::uv_err_name(inner);
336             assert!(name_str.is_not_null());
337             from_c_str(name_str)
338         }
339     }
340
341     pub fn desc(&self) -> ~str {
342         unsafe {
343             let inner = match self { &UvError(a) => a };
344             let desc_str = uvll::uv_strerror(inner);
345             assert!(desc_str.is_not_null());
346             from_c_str(desc_str)
347         }
348     }
349
350     pub fn is_eof(&self) -> bool {
351         let UvError(handle) = *self;
352         handle == uvll::EOF
353     }
354 }
355
356 impl fmt::Show for UvError {
357     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
358         write!(f.buf, "{}: {}", self.name(), self.desc())
359     }
360 }
361
362 #[test]
363 fn error_smoke_test() {
364     let err: UvError = UvError(uvll::EOF);
365     assert_eq!(err.to_str(), ~"EOF: end of file");
366 }
367
368 pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
369     unsafe {
370         // Importing error constants
371
372         // uv error descriptions are static
373         let UvError(errcode) = uverr;
374         let c_desc = uvll::uv_strerror(errcode);
375         let desc = str::raw::c_str_to_static_slice(c_desc);
376
377         let kind = match errcode {
378             uvll::UNKNOWN => io::OtherIoError,
379             uvll::OK => io::OtherIoError,
380             uvll::EOF => io::EndOfFile,
381             uvll::EACCES => io::PermissionDenied,
382             uvll::ECONNREFUSED => io::ConnectionRefused,
383             uvll::ECONNRESET => io::ConnectionReset,
384             uvll::ENOTCONN => io::NotConnected,
385             uvll::ENOENT => io::FileNotFound,
386             uvll::EPIPE => io::BrokenPipe,
387             uvll::ECONNABORTED => io::ConnectionAborted,
388             uvll::EADDRNOTAVAIL => io::ConnectionRefused,
389             err => {
390                 uvdebug!("uverr.code {}", err as int);
391                 // FIXME: Need to map remaining uv error types
392                 io::OtherIoError
393             }
394         };
395
396         IoError {
397             kind: kind,
398             desc: desc,
399             detail: None
400         }
401     }
402 }
403
404 /// Given a uv error code, convert a callback status to a UvError
405 pub fn status_to_maybe_uv_error(status: c_int) -> Option<UvError> {
406     if status >= 0 {
407         None
408     } else {
409         Some(UvError(status))
410     }
411 }
412
413 pub fn status_to_io_result(status: c_int) -> Result<(), IoError> {
414     if status >= 0 {Ok(())} else {Err(uv_error_to_io_error(UvError(status)))}
415 }
416
417 /// The uv buffer type
418 pub type Buf = uvll::uv_buf_t;
419
420 pub fn empty_buf() -> Buf {
421     uvll::uv_buf_t {
422         base: null(),
423         len: 0,
424     }
425 }
426
427 /// Borrow a slice to a Buf
428 pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
429     let data = v.as_ptr();
430     uvll::uv_buf_t { base: data, len: v.len() as uvll::uv_buf_len_t }
431 }
432
433 // This function is full of lies!
434 #[cfg(test)]
435 fn local_loop() -> &'static mut uvio::UvIoFactory {
436     unsafe {
437         cast::transmute({
438             let mut task = Local::borrow(None::<Task>);
439             let mut io = task.get().local_io().unwrap();
440             let (_vtable, uvio): (uint, &'static mut uvio::UvIoFactory) =
441                 cast::transmute(io.get());
442             uvio
443         })
444     }
445 }
446
447 #[cfg(test)]
448 mod test {
449     use std::cast::transmute;
450     use std::unstable::run_in_bare_thread;
451
452     use super::{slice_to_uv_buf, Loop};
453
454     #[test]
455     fn test_slice_to_uv_buf() {
456         let slice = [0, .. 20];
457         let buf = slice_to_uv_buf(slice);
458
459         assert_eq!(buf.len, 20);
460
461         unsafe {
462             let base = transmute::<*u8, *mut u8>(buf.base);
463             (*base) = 1;
464             (*base.offset(1)) = 2;
465         }
466
467         assert!(slice[0] == 1);
468         assert!(slice[1] == 2);
469     }
470
471
472     #[test]
473     fn loop_smoke_test() {
474         run_in_bare_thread(proc() {
475             let mut loop_ = Loop::new();
476             loop_.run();
477             loop_.close();
478         });
479     }
480 }