8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use std:: cast:: transmute;
12
- use std:: cell:: Cell ;
13
- use std:: libc:: { c_int, c_void} ;
14
- use std:: ptr:: null;
15
11
use ai = std:: rt:: io:: net:: addrinfo;
12
+ use std:: cast;
13
+ use std:: libc:: c_int;
14
+ use std:: ptr:: null;
15
+ use std:: rt:: BlockedTask ;
16
+ use std:: rt:: local:: Local ;
17
+ use std:: rt:: sched:: Scheduler ;
16
18
17
- use uvll;
18
- use uvll:: UV_GETADDRINFO ;
19
- use super :: { Loop , UvError , NativeHandle , status_to_maybe_uv_error} ;
20
19
use net;
20
+ use super :: { Loop , UvError , NativeHandle } ;
21
+ use uvll:: UV_GETADDRINFO ;
22
+ use uvll;
21
23
22
- type GetAddrInfoCallback = ~fn ( GetAddrInfoRequest , & net:: UvAddrInfo , Option < UvError > ) ;
24
+ struct GetAddrInfoRequest {
25
+ handle : * uvll:: uv_getaddrinfo_t ,
26
+ }
23
27
24
- pub struct GetAddrInfoRequest ( * uvll:: uv_getaddrinfo_t ) ;
28
+ struct Addrinfo {
29
+ handle : * uvll:: addrinfo ,
30
+ }
25
31
26
- pub struct RequestData {
27
- priv getaddrinfo_cb : Option < GetAddrInfoCallback > ,
32
+ struct Ctx {
33
+ slot : Option < BlockedTask > ,
34
+ status : c_int ,
35
+ addrinfo : Option < Addrinfo > ,
28
36
}
29
37
30
38
impl GetAddrInfoRequest {
31
39
pub fn new ( ) -> GetAddrInfoRequest {
32
- let req = unsafe { uvll:: malloc_req ( UV_GETADDRINFO ) } ;
33
- assert ! ( req. is_not_null( ) ) ;
34
- let mut req: GetAddrInfoRequest = NativeHandle :: from_native_handle ( req) ;
35
- req. install_req_data ( ) ;
36
- return req;
40
+ GetAddrInfoRequest {
41
+ handle : unsafe { uvll:: malloc_req ( uvll:: UV_GETADDRINFO ) } ,
42
+ }
37
43
}
38
44
39
- pub fn getaddrinfo ( & mut self , loop_ : & Loop , node : Option < & str > ,
40
- service : Option < & str > , hints : Option < ai:: Hint > ,
41
- cb : GetAddrInfoCallback ) {
42
-
45
+ pub fn run ( loop_ : & Loop , node : Option < & str > , service : Option < & str > ,
46
+ hints : Option < ai:: Hint > ) -> Result < ~[ ai:: Info ] , UvError > {
43
47
assert ! ( node. is_some( ) || service. is_some( ) ) ;
44
-
45
- let ( c_node, c_node_ptr) = match node {
48
+ let ( _c_node, c_node_ptr) = match node {
46
49
Some ( n) => {
47
50
let c_node = n. to_c_str ( ) ;
48
51
let c_node_ptr = c_node. with_ref ( |r| r) ;
@@ -51,7 +54,7 @@ impl GetAddrInfoRequest {
51
54
None => ( None , null ( ) )
52
55
} ;
53
56
54
- let ( c_service , c_service_ptr) = match service {
57
+ let ( _c_service , c_service_ptr) = match service {
55
58
Some ( s) => {
56
59
let c_service = s. to_c_str ( ) ;
57
60
let c_service_ptr = c_service. with_ref ( |r| r) ;
@@ -60,37 +63,13 @@ impl GetAddrInfoRequest {
60
63
None => ( None , null ( ) )
61
64
} ;
62
65
63
- let cb = Cell :: new ( cb) ;
64
- let wrapper_cb: GetAddrInfoCallback = |req, addrinfo, err| {
65
- // Capture some heap values that need to stay alive for the
66
- // getaddrinfo call
67
- let _ = & c_node;
68
- let _ = & c_service;
69
-
70
- let cb = cb. take ( ) ;
71
- cb ( req, addrinfo, err)
72
- } ;
73
-
74
66
let hint = hints. map ( |hint| {
75
67
let mut flags = 0 ;
76
68
do each_ai_flag |cval, aival| {
77
69
if hint. flags & ( aival as uint ) != 0 {
78
70
flags |= cval as i32 ;
79
71
}
80
72
}
81
- /* XXX: do we really want to support these?
82
- let socktype = match hint.socktype {
83
- Some(ai::Stream) => uvll::rust_SOCK_STREAM(),
84
- Some(ai::Datagram) => uvll::rust_SOCK_DGRAM(),
85
- Some(ai::Raw) => uvll::rust_SOCK_RAW(),
86
- None => 0,
87
- };
88
- let protocol = match hint.protocol {
89
- Some(ai::UDP) => uvll::rust_IPPROTO_UDP(),
90
- Some(ai::TCP) => uvll::rust_IPPROTO_TCP(),
91
- _ => 0,
92
- };
93
- */
94
73
let socktype = 0 ;
95
74
let protocol = 0 ;
96
75
@@ -106,66 +85,54 @@ impl GetAddrInfoRequest {
106
85
}
107
86
} ) ;
108
87
let hint_ptr = hint. as_ref ( ) . map_default ( null ( ) , |x| x as * uvll:: addrinfo ) ;
88
+ let req = GetAddrInfoRequest :: new ( ) ;
89
+
90
+ return match unsafe {
91
+ uvll:: uv_getaddrinfo ( loop_. native_handle ( ) , req. handle ,
92
+ getaddrinfo_cb, c_node_ptr, c_service_ptr,
93
+ hint_ptr)
94
+ } {
95
+ 0 => {
96
+ let mut cx = Ctx { slot : None , status : 0 , addrinfo : None } ;
97
+ unsafe { uvll:: set_data_for_req ( req. handle , & cx) }
98
+ let scheduler: ~Scheduler = Local :: take ( ) ;
99
+ do scheduler. deschedule_running_task_and_then |_, task| {
100
+ cx. slot = Some ( task) ;
101
+ }
109
102
110
- self . get_req_data ( ) . getaddrinfo_cb = Some ( wrapper_cb) ;
111
-
112
- unsafe {
113
- assert ! ( 0 == uvll:: uv_getaddrinfo( loop_. native_handle( ) ,
114
- self . native_handle( ) ,
115
- getaddrinfo_cb,
116
- c_node_ptr,
117
- c_service_ptr,
118
- hint_ptr) ) ;
119
- }
120
-
121
- extern "C" fn getaddrinfo_cb ( req : * uvll:: uv_getaddrinfo_t ,
122
- status : c_int ,
123
- res : * uvll:: addrinfo ) {
124
- let mut req: GetAddrInfoRequest = NativeHandle :: from_native_handle ( req) ;
125
- let err = status_to_maybe_uv_error ( status) ;
126
- let addrinfo = net:: UvAddrInfo ( res) ;
127
- let data = req. get_req_data ( ) ;
128
- ( * data. getaddrinfo_cb . get_ref ( ) ) ( req, & addrinfo, err) ;
129
- unsafe {
130
- uvll:: uv_freeaddrinfo ( res) ;
103
+ match cx. status {
104
+ 0 => Ok ( accum_addrinfo ( cx. addrinfo . get_ref ( ) ) ) ,
105
+ n => Err ( UvError ( n) )
106
+ }
131
107
}
132
- }
133
- }
108
+ n => Err ( UvError ( n ) )
109
+ } ;
134
110
135
- fn get_loop ( & self ) -> Loop {
136
- unsafe {
137
- Loop {
138
- handle : uvll:: get_loop_from_fs_req ( self . native_handle ( ) )
139
- }
140
- }
141
- }
142
111
143
- fn install_req_data ( & mut self ) {
144
- let req = self . native_handle ( ) as * uvll:: uv_getaddrinfo_t ;
145
- let data = ~RequestData {
146
- getaddrinfo_cb : None
147
- } ;
148
- unsafe {
149
- let data = transmute :: < ~RequestData , * c_void > ( data) ;
150
- uvll:: set_data_for_req ( req, data) ;
112
+ extern fn getaddrinfo_cb ( req : * uvll:: uv_getaddrinfo_t ,
113
+ status : c_int ,
114
+ res : * uvll:: addrinfo ) {
115
+ let cx: & mut Ctx = unsafe {
116
+ cast:: transmute ( uvll:: get_data_for_req ( req) )
117
+ } ;
118
+ cx. status = status;
119
+ cx. addrinfo = Some ( Addrinfo { handle : res } ) ;
120
+
121
+ let sched: ~Scheduler = Local :: take ( ) ;
122
+ sched. resume_blocked_task_immediately ( cx. slot . take_unwrap ( ) ) ;
151
123
}
152
124
}
125
+ }
153
126
154
- fn get_req_data < ' r > ( & ' r mut self ) -> & ' r mut RequestData {
155
- unsafe {
156
- let data = uvll:: get_data_for_req ( self . native_handle ( ) ) ;
157
- let data = transmute :: < & * c_void , & mut ~RequestData > ( & data) ;
158
- return & mut * * data;
159
- }
127
+ impl Drop for GetAddrInfoRequest {
128
+ fn drop( & mut self ) {
129
+ unsafe { uvll:: free_req ( self . handle ) }
160
130
}
131
+ }
161
132
162
- fn delete ( self ) {
163
- unsafe {
164
- let data = uvll:: get_data_for_req ( self . native_handle ( ) ) ;
165
- let _data = transmute :: < * c_void , ~RequestData > ( data) ;
166
- uvll:: set_data_for_req ( self . native_handle ( ) , null :: < ( ) > ( ) ) ;
167
- uvll:: free_req ( self . native_handle ( ) ) ;
168
- }
133
+ impl Drop for Addrinfo {
134
+ fn drop ( & mut self ) {
135
+ unsafe { uvll:: uv_freeaddrinfo ( self . handle ) }
169
136
}
170
137
}
171
138
@@ -184,10 +151,9 @@ fn each_ai_flag(_f: &fn(c_int, ai::Flag)) {
184
151
}
185
152
186
153
// Traverse the addrinfo linked list, producing a vector of Rust socket addresses
187
- pub fn accum_addrinfo( addr : & net :: UvAddrInfo ) -> ~[ ai:: Info ] {
154
+ pub fn accum_addrinfo( addr : & Addrinfo ) -> ~[ ai:: Info ] {
188
155
unsafe {
189
- let & net:: UvAddrInfo ( addr) = addr;
190
- let mut addr = addr;
156
+ let mut addr = addr. handle ;
191
157
192
158
let mut addrs = ~[ ] ;
193
159
loop {
@@ -235,15 +201,6 @@ pub fn accum_addrinfo(addr: &net::UvAddrInfo) -> ~[ai::Info] {
235
201
}
236
202
}
237
203
238
- impl NativeHandle < * uvll:: uv_getaddrinfo_t > for GetAddrInfoRequest {
239
- fn from_native_handle ( handle : * uvll:: uv_getaddrinfo_t ) -> GetAddrInfoRequest {
240
- GetAddrInfoRequest ( handle)
241
- }
242
- fn native_handle ( & self ) -> * uvll:: uv_getaddrinfo_t {
243
- match self { & GetAddrInfoRequest ( ptr) => ptr }
244
- }
245
- }
246
-
247
204
#[ cfg( test) ]
248
205
mod test {
249
206
use Loop ;
0 commit comments