Skip to content

Commit cc886d4

Browse files
author
Eric Reed
committed
---
yaml --- r: 63313 b: refs/heads/snap-stage3 c: a7f92c9 h: refs/heads/master i: 63311: e372c2b v: v3
1 parent 8162b8e commit cc886d4

File tree

3 files changed

+185
-6
lines changed

3 files changed

+185
-6
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 2d28d645422c1617be58c8ca7ad9a457264ca850
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 03fe59aefa6ec84531335fd93e8dbf44dee65570
4+
refs/heads/snap-stage3: a7f92c92ed07588c3bde3cc38e64b9289ea682f5
55
refs/heads/try: 7b78b52e602bb3ea8174f9b2006bff3315f03ef9
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libstd/rt/uv/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use rt::io::IoError;
5454
#[cfg(test)] use unstable::run_in_bare_thread;
5555

5656
pub use self::file::FsRequest;
57-
pub use self::net::{StreamWatcher, TcpWatcher};
57+
pub use self::net::{StreamWatcher, TcpWatcher, UdpWatcher};
5858
pub use self::idle::IdleWatcher;
5959
pub use self::timer::TimerWatcher;
6060
pub use self::async::AsyncWatcher;
@@ -128,6 +128,8 @@ pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
128128
pub type FsCallback = ~fn(FsRequest, Option<UvError>);
129129
pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
130130
pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
131+
pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, Ipv4, uint, Option<UvError>);
132+
pub type UdpSendCallback = ~fn(UdpWatcher, Option<UvError>);
131133

132134

133135
/// Callbacks used by StreamWatchers, set as custom data on the foreign handle
@@ -139,7 +141,9 @@ struct WatcherData {
139141
alloc_cb: Option<AllocCallback>,
140142
idle_cb: Option<IdleCallback>,
141143
timer_cb: Option<TimerCallback>,
142-
async_cb: Option<AsyncCallback>
144+
async_cb: Option<AsyncCallback>,
145+
udp_recv_cb: Option<UdpReceiveCallback>,
146+
udp_send_cb: Option<UdpSendCallback>
143147
}
144148

145149
pub trait WatcherInterop {
@@ -169,7 +173,9 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
169173
alloc_cb: None,
170174
idle_cb: None,
171175
timer_cb: None,
172-
async_cb: None
176+
async_cb: None,
177+
udp_recv_cb: None,
178+
udp_send_cb: None
173179
};
174180
let data = transmute::<~WatcherData, *c_void>(data);
175181
uvll::set_data_for_uv_handle(self.native_handle(), data);
@@ -309,6 +315,9 @@ pub fn status_to_maybe_uv_error<T>(handle: *T, status: c_int) -> Option<UvError>
309315
/// The uv buffer type
310316
pub type Buf = uvll::uv_buf_t;
311317
318+
/// The uv IPv4 type
319+
pub type Ipv4 = uvll::sockaddr_in;
320+
312321
/// Borrow a slice to a Buf
313322
pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
314323
let data = vec::raw::to_ptr(v);

branches/snap-stage3/src/libstd/rt/uv/net.rs

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
// except according to those terms.
1010

1111
use prelude::*;
12-
use libc::{size_t, ssize_t, c_int, c_void};
12+
use libc::{size_t, ssize_t, c_int, c_void, c_uint};
1313
use rt::uv::uvll;
1414
use rt::uv::uvll::*;
15-
use rt::uv::{AllocCallback, ConnectionCallback, ReadCallback};
15+
use rt::uv::{AllocCallback, ConnectionCallback, ReadCallback, UdpReceiveCallback, UdpSendCallback};
1616
use rt::uv::{Loop, Watcher, Request, UvError, Buf, NativeHandle, NullCallback,
1717
status_to_maybe_uv_error};
1818
use rt::io::net::ip::{IpAddr, Ipv4, Ipv6};
@@ -254,6 +254,142 @@ impl NativeHandle<*uvll::uv_tcp_t> for TcpWatcher {
254254
}
255255
}
256256

257+
pub struct UdpWatcher(*uvll::uv_udp_t);
258+
impl Watcher for UdpWatcher { }
259+
260+
pub impl UdpWatcher {
261+
fn new(loop_: &mut Loop) -> UdpWatcher {
262+
unsafe {
263+
let handle = malloc_handle(UV_UDP);
264+
assert!(handle.is_not_null());
265+
assert_eq!(0, uvll::udp_init(loop_.native_handle(), handle));
266+
let mut watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
267+
watcher.install_watcher_data();
268+
return watcher;
269+
}
270+
}
271+
272+
fn bind(&mut self, address: IpAddr) -> Result<(), UvError> {
273+
match address {
274+
Ipv4(*) => {
275+
do ip4_as_uv_ip4(address) |addr| {
276+
let result = unsafe {
277+
uvll::udp_bind(self.native_handle(), addr, 0u32)
278+
};
279+
if result == 0 {
280+
Ok(())
281+
} else {
282+
Err(last_uv_error(self))
283+
}
284+
}
285+
}
286+
_ => fail!() // TODO ipv6
287+
}
288+
}
289+
290+
fn recv_start(&mut self, alloc: AllocCallback, cb: UdpReceiveCallback) {
291+
{
292+
let data = self.get_watcher_data();
293+
data.alloc_cb = Some(alloc);
294+
data.udp_recv_cb = Some(cb);
295+
}
296+
297+
let handle = self.native_handle();
298+
unsafe { uvll::read_start(handle, alloc_cb, recv_cb); }
299+
300+
extern fn alloc_cb(handle: *uvll::uv_udp_t, suggested_size: size_t) -> Buf {
301+
let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
302+
let data = udp_watcher.get_watcher_data();
303+
let alloc_cb = data.alloc_cb.get_ref();
304+
return (*alloc_cb)(suggested_size as uint);
305+
}
306+
307+
/* TODO the socket address should actually be a pointer to either a sockaddr_in or sockaddr_in6.
308+
In libuv, the udp_recv callback takes a struct *sockaddr */
309+
extern fn recv_cb(handle: *uvll::uv_udp_t, nread: ssize_t, buf: Buf,
310+
address: *uvll::sockaddr_in, flags: c_uint) {
311+
rtdebug!("buf addr: %x", buf.base as uint);
312+
rtdebug!("buf len: %d", buf.len as int);
313+
let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
314+
let data = udp_watcher.get_watcher_data();
315+
let cb = data.udp_recv_cb.get_ref();
316+
let status = status_to_maybe_uv_error(handle, nread as c_int);
317+
unsafe { (*cb)(udp_watcher, nread as int, buf, *address, flags as uint, status) };
318+
}
319+
}
320+
321+
fn recv_stop(&mut self) {
322+
let handle = self.native_handle();
323+
unsafe { uvll::udp_recv_stop(handle); }
324+
}
325+
326+
fn send(&mut self, buf: Buf, address: IpAddr, cb: UdpSendCallback) {
327+
{
328+
let data = self.get_watcher_data();
329+
assert!(data.udp_send_cb.is_none());
330+
data.udp_send_cb = Some(cb);
331+
}
332+
333+
let req = UdpSendRequest::new();
334+
let bufs = [buf];
335+
match address {
336+
Ipv4(*) => {
337+
do ip4_as_uv_ip4(address) |addr| {
338+
unsafe {
339+
assert!(0 == uvll::udp_send(req.native_handle(),
340+
self.native_handle(),
341+
bufs, addr, send_cb));
342+
}
343+
}
344+
}
345+
_ => fail!() // TODO ipv6
346+
}
347+
348+
extern fn send_cb(req: *uvll::uv_udp_send_t, status: c_int) {
349+
let send_request: UdpSendRequest = NativeHandle::from_native_handle(req);
350+
let mut udp_watcher = send_request.handle();
351+
send_request.delete();
352+
let cb = {
353+
let data = udp_watcher.get_watcher_data();
354+
let cb = data.udp_send_cb.swap_unwrap();
355+
cb
356+
};
357+
let status = status_to_maybe_uv_error(udp_watcher.native_handle(), status);
358+
cb(udp_watcher, status);
359+
}
360+
}
361+
362+
fn close(self, cb: NullCallback) {
363+
{
364+
let mut this = self;
365+
let data = this.get_watcher_data();
366+
assert!(data.close_cb.is_none());
367+
data.close_cb = Some(cb);
368+
}
369+
370+
unsafe { uvll::close(self.native_handle(), close_cb); }
371+
372+
extern fn close_cb(handle: *uvll::uv_udp_t) {
373+
let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
374+
{
375+
let data = udp_watcher.get_watcher_data();
376+
data.close_cb.swap_unwrap()();
377+
}
378+
udp_watcher.drop_watcher_data();
379+
unsafe { free_handle(handle as *c_void) }
380+
}
381+
}
382+
}
383+
384+
impl NativeHandle<*uvll::uv_udp_t> for UdpWatcher {
385+
fn from_native_handle(handle: *uvll::uv_udp_t) -> UdpWatcher {
386+
UdpWatcher(handle)
387+
}
388+
fn native_handle(&self) -> *uvll::uv_udp_t {
389+
match self { &UdpWatcher(ptr) => ptr }
390+
}
391+
}
392+
257393
// uv_connect_t is a subclass of uv_req_t
258394
struct ConnectRequest(*uvll::uv_connect_t);
259395
impl Request for ConnectRequest { }
@@ -327,6 +463,40 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest {
327463
}
328464
}
329465

466+
pub struct UdpSendRequest(*uvll::uv_udp_send_t);
467+
468+
impl Request for UdpSendRequest { }
469+
470+
pub impl UdpSendRequest {
471+
fn new() -> UdpSendRequest {
472+
let send_handle = unsafe {
473+
malloc_req(UV_UDP_SEND)
474+
};
475+
assert!(send_handle.is_not_null());
476+
let send_handle = send_handle as *uvll::uv_udp_send_t;
477+
UdpSendRequest(send_handle)
478+
}
479+
480+
fn handle(&self) -> UdpWatcher {
481+
unsafe {
482+
let udp_handle = uvll::get_udp_handle_from_send_req(self.native_handle());
483+
NativeHandle::from_native_handle(udp_handle)
484+
}
485+
}
486+
487+
fn delete(self) {
488+
unsafe { free_req(self.native_handle() as *c_void) }
489+
}
490+
}
491+
492+
impl NativeHandle<*uvll::uv_udp_send_t> for UdpSendRequest {
493+
fn from_native_handle(handle: *uvll::uv_udp_send_t) -> UdpSendRequest {
494+
UdpSendRequest(handle)
495+
}
496+
fn native_handle(&self) -> *uvll::uv_udp_send_t {
497+
match self { &UdpSendRequest(ptr) => ptr }
498+
}
499+
}
330500

331501
#[cfg(test)]
332502
mod test {

0 commit comments

Comments
 (0)