9
9
// except according to those terms.
10
10
11
11
use std:: cast;
12
+ use std:: libc;
12
13
use std:: libc:: { size_t, ssize_t, c_int, c_void, c_uint, c_char} ;
13
14
use std:: ptr;
14
15
use std:: rt:: BlockedTask ;
@@ -28,103 +29,81 @@ use super::{Loop, Request, UvError, Buf, status_to_io_result,
28
29
wait_until_woken_after} ;
29
30
use uvio:: HomingIO ;
30
31
use uvll;
32
+ use uvll:: sockaddr;
31
33
32
34
////////////////////////////////////////////////////////////////////////////////
33
35
/// Generic functions related to dealing with sockaddr things
34
36
////////////////////////////////////////////////////////////////////////////////
35
37
36
- pub enum UvSocketAddr {
37
- UvIpv4SocketAddr ( * uvll:: sockaddr_in ) ,
38
- UvIpv6SocketAddr ( * uvll:: sockaddr_in6 ) ,
39
- }
40
-
41
- pub fn sockaddr_to_UvSocketAddr ( addr : * uvll:: sockaddr ) -> UvSocketAddr {
42
- unsafe {
43
- assert ! ( ( uvll:: is_ip4_addr( addr) || uvll:: is_ip6_addr( addr) ) ) ;
44
- assert ! ( !( uvll:: is_ip4_addr( addr) && uvll:: is_ip6_addr( addr) ) ) ;
45
- match addr {
46
- _ if uvll:: is_ip4_addr ( addr) =>
47
- UvIpv4SocketAddr ( addr as * uvll:: sockaddr_in ) ,
48
- _ if uvll:: is_ip6_addr ( addr) =>
49
- UvIpv6SocketAddr ( addr as * uvll:: sockaddr_in6 ) ,
50
- _ => fail ! ( ) ,
51
- }
52
- }
53
- }
54
-
55
- fn socket_addr_as_uv_socket_addr < T > ( addr : SocketAddr , f : & fn ( UvSocketAddr ) -> T ) -> T {
38
+ #[ fixed_stack_segment]
39
+ fn socket_addr_as_sockaddr < T > ( addr : SocketAddr , f : & fn ( * sockaddr ) -> T ) -> T {
56
40
let malloc = match addr. ip {
57
- Ipv4Addr ( * ) => uvll:: malloc_ip4_addr,
58
- Ipv6Addr ( * ) => uvll:: malloc_ip6_addr,
59
- } ;
60
- let wrap = match addr. ip {
61
- Ipv4Addr ( * ) => UvIpv4SocketAddr ,
62
- Ipv6Addr ( * ) => UvIpv6SocketAddr ,
63
- } ;
64
- let free = match addr. ip {
65
- Ipv4Addr ( * ) => uvll:: free_ip4_addr,
66
- Ipv6Addr ( * ) => uvll:: free_ip6_addr,
41
+ Ipv4Addr ( * ) => uvll:: rust_malloc_ip4_addr,
42
+ Ipv6Addr ( * ) => uvll:: rust_malloc_ip6_addr,
67
43
} ;
68
44
69
- let addr = unsafe { malloc ( addr. ip . to_str ( ) , addr. port as int ) } ;
45
+ let ip = addr. ip . to_str ( ) ;
46
+ let addr = ip. with_c_str ( |p| unsafe { malloc ( p, addr. port as c_int ) } ) ;
70
47
do ( || {
71
- f ( wrap ( addr) )
48
+ f ( addr)
72
49
} ) . finally {
73
- unsafe { free ( addr) } ;
50
+ unsafe { libc :: free ( addr) } ;
74
51
}
75
52
}
76
53
77
- fn uv_socket_addr_as_socket_addr < T > ( addr : UvSocketAddr , f : & fn ( SocketAddr ) -> T ) -> T {
78
- let ip_size = match addr {
79
- UvIpv4SocketAddr ( * ) => 4 /*groups of*/ * 3 /*digits separated by*/ + 3 /*periods*/ ,
80
- UvIpv6SocketAddr ( * ) => 8 /*groups of*/ * 4 /*hex digits separated by*/ + 7 /*colons*/ ,
81
- } ;
82
- let ip_name = {
83
- let buf = vec:: from_elem ( ip_size + 1 /*null terminated*/ , 0u8 ) ;
84
- unsafe {
54
+ #[ fixed_stack_segment]
55
+ pub fn sockaddr_to_socket_addr ( addr : * sockaddr ) -> SocketAddr {
56
+ unsafe {
57
+ let ip_size = if uvll:: rust_is_ipv4_sockaddr ( addr) == 1 {
58
+ 4 /*groups of*/ * 3 /*digits separated by*/ + 3 /*periods*/
59
+ } else if uvll:: rust_is_ipv6_sockaddr ( addr) == 1 {
60
+ 8 /*groups of*/ * 4 /*hex digits separated by*/ + 7 /*colons*/
61
+ } else {
62
+ fail ! ( "unknown address?" ) ;
63
+ } ;
64
+ let ip_name = {
65
+ let buf = vec:: from_elem ( ip_size + 1 /*null terminated*/ , 0u8 ) ;
85
66
let buf_ptr = vec:: raw:: to_ptr ( buf) ;
86
- match addr {
87
- UvIpv4SocketAddr ( addr) =>
88
- uvll:: uv_ip4_name ( addr, buf_ptr as * c_char , ip_size as size_t ) ,
89
- UvIpv6SocketAddr ( addr) =>
90
- uvll:: uv_ip6_name ( addr, buf_ptr as * c_char , ip_size as size_t ) ,
67
+ if uvll:: rust_is_ipv4_sockaddr ( addr) == 1 {
68
+ uvll:: uv_ip4_name ( addr, buf_ptr as * c_char , ip_size as size_t ) ;
69
+ } else {
70
+ uvll:: uv_ip6_name ( addr, buf_ptr as * c_char , ip_size as size_t ) ;
91
71
}
72
+ buf
92
73
} ;
93
- buf
94
- } ;
95
- let ip_port = unsafe {
96
- let port = match addr {
97
- UvIpv4SocketAddr ( addr) => uvll:: ip4_port ( addr) ,
98
- UvIpv6SocketAddr ( addr) => uvll:: ip6_port ( addr) ,
74
+ let ip_port = {
75
+ let port = if uvll:: rust_is_ipv4_sockaddr ( addr) == 1 {
76
+ uvll:: rust_ip4_port ( addr)
77
+ } else {
78
+ uvll:: rust_ip6_port ( addr)
79
+ } ;
80
+ port as u16
99
81
} ;
100
- port as u16
101
- } ;
102
- let ip_str = str:: from_utf8_slice ( ip_name) . trim_right_chars ( & '\x00' ) ;
103
- let ip_addr = FromStr :: from_str ( ip_str) . unwrap ( ) ;
82
+ let ip_str = str:: from_utf8_slice ( ip_name) . trim_right_chars ( & '\x00' ) ;
83
+ let ip_addr = FromStr :: from_str ( ip_str) . unwrap ( ) ;
104
84
105
- // finally run the closure
106
- f ( SocketAddr { ip : ip_addr, port : ip_port } )
107
- }
108
-
109
- pub fn uv_socket_addr_to_socket_addr ( addr : UvSocketAddr ) -> SocketAddr {
110
- use std:: util;
111
- uv_socket_addr_as_socket_addr ( addr, util:: id)
85
+ SocketAddr { ip : ip_addr, port : ip_port }
86
+ }
112
87
}
113
88
114
89
#[ cfg( test) ]
115
90
#[ test]
116
91
fn test_ip4_conversion ( ) {
117
92
use std:: rt;
118
93
let ip4 = rt:: test:: next_test_ip4 ( ) ;
119
- assert_eq ! ( ip4, socket_addr_as_uv_socket_addr( ip4, uv_socket_addr_to_socket_addr) ) ;
94
+ do socket_addr_as_sockaddr ( ip4) |addr| {
95
+ assert_eq ! ( ip4, sockaddr_to_socket_addr( addr) ) ;
96
+ }
120
97
}
121
98
122
99
#[ cfg( test) ]
123
100
#[ test]
124
101
fn test_ip6_conversion ( ) {
125
102
use std:: rt;
126
103
let ip6 = rt:: test:: next_test_ip6 ( ) ;
127
- assert_eq ! ( ip6, socket_addr_as_uv_socket_addr( ip6, uv_socket_addr_to_socket_addr) ) ;
104
+ do socket_addr_as_sockaddr ( ip6) |addr| {
105
+ assert_eq ! ( ip6, sockaddr_to_socket_addr( addr) ) ;
106
+ }
128
107
}
129
108
130
109
enum SocketNameKind {
@@ -133,37 +112,29 @@ enum SocketNameKind {
133
112
Udp
134
113
}
135
114
115
+ #[ fixed_stack_segment]
136
116
fn socket_name ( sk : SocketNameKind , handle : * c_void ) -> Result < SocketAddr , IoError > {
137
- let getsockname = match sk {
138
- TcpPeer => uvll:: tcp_getpeername,
139
- Tcp => uvll:: tcp_getsockname,
140
- Udp => uvll:: udp_getsockname,
141
- } ;
142
-
143
- // Allocate a sockaddr_storage
144
- // since we don't know if it's ipv4 or ipv6
145
- let r_addr = unsafe { uvll:: malloc_sockaddr_storage ( ) } ;
117
+ unsafe {
118
+ let getsockname = match sk {
119
+ TcpPeer => uvll:: uv_tcp_getpeername,
120
+ Tcp => uvll:: uv_tcp_getsockname,
121
+ Udp => uvll:: uv_udp_getsockname,
122
+ } ;
146
123
147
- let r = unsafe {
148
- getsockname ( handle, r_addr as * uvll:: sockaddr_storage )
149
- } ;
124
+ // Allocate a sockaddr_storage
125
+ // since we don't know if it's ipv4 or ipv6
126
+ let size = uvll:: rust_sockaddr_size ( ) ;
127
+ let name = libc:: malloc ( size as size_t ) ;
128
+ assert ! ( !name. is_null( ) ) ;
129
+ let mut namelen = size;
150
130
151
- if r != 0 {
152
- return Err ( uv_error_to_io_error ( UvError ( r) ) ) ;
131
+ let ret = match getsockname ( handle, name, & mut namelen) {
132
+ 0 => Ok ( sockaddr_to_socket_addr ( name) ) ,
133
+ n => Err ( uv_error_to_io_error ( UvError ( n) ) )
134
+ } ;
135
+ libc:: free ( name) ;
136
+ ret
153
137
}
154
-
155
- let addr = unsafe {
156
- if uvll:: is_ip6_addr ( r_addr as * uvll:: sockaddr ) {
157
- uv_socket_addr_to_socket_addr ( UvIpv6SocketAddr ( r_addr as * uvll:: sockaddr_in6 ) )
158
- } else {
159
- uv_socket_addr_to_socket_addr ( UvIpv4SocketAddr ( r_addr as * uvll:: sockaddr_in ) )
160
- }
161
- } ;
162
-
163
- unsafe { uvll:: free_sockaddr_storage ( r_addr) ; }
164
-
165
- Ok ( addr)
166
-
167
138
}
168
139
169
140
////////////////////////////////////////////////////////////////////////////////
@@ -210,17 +181,11 @@ impl TcpWatcher {
210
181
211
182
return do task:: unkillable {
212
183
let tcp = TcpWatcher :: new ( loop_) ;
213
- let ret = do socket_addr_as_uv_socket_addr ( address) |addr| {
184
+ let ret = do socket_addr_as_sockaddr ( address) |addr| {
214
185
let mut req = Request :: new ( uvll:: UV_CONNECT ) ;
215
- let result = match addr {
216
- UvIpv4SocketAddr ( addr) => unsafe {
217
- uvll:: tcp_connect ( req. handle , tcp. handle , addr,
218
- connect_cb)
219
- } ,
220
- UvIpv6SocketAddr ( addr) => unsafe {
221
- uvll:: tcp_connect6 ( req. handle , tcp. handle , addr,
222
- connect_cb)
223
- } ,
186
+ let result = unsafe {
187
+ uvll:: uv_tcp_connect ( req. handle , tcp. handle , addr,
188
+ connect_cb)
224
189
} ;
225
190
match result {
226
191
0 => {
@@ -340,11 +305,8 @@ impl TcpListener {
340
305
closing_task : None ,
341
306
outgoing : Tube :: new ( ) ,
342
307
} ;
343
- let res = socket_addr_as_uv_socket_addr ( address, |addr| unsafe {
344
- match addr {
345
- UvIpv4SocketAddr ( addr) => uvll:: tcp_bind ( l. handle , addr) ,
346
- UvIpv6SocketAddr ( addr) => uvll:: tcp_bind6 ( l. handle , addr) ,
347
- }
308
+ let res = socket_addr_as_sockaddr ( address, |addr| unsafe {
309
+ uvll:: uv_tcp_bind ( l. handle , addr)
348
310
} ) ;
349
311
match res {
350
312
0 => Ok ( l. install ( ) ) ,
@@ -475,13 +437,8 @@ impl UdpWatcher {
475
437
assert_eq ! ( unsafe {
476
438
uvll:: uv_udp_init( loop_. handle, udp. handle)
477
439
} , 0 ) ;
478
- let result = socket_addr_as_uv_socket_addr ( address, |addr| unsafe {
479
- match addr {
480
- UvIpv4SocketAddr ( addr) =>
481
- uvll:: udp_bind ( udp. handle , addr, 0u32 ) ,
482
- UvIpv6SocketAddr ( addr) =>
483
- uvll:: udp_bind6 ( udp. handle , addr, 0u32 ) ,
484
- }
440
+ let result = socket_addr_as_sockaddr ( address, |addr| unsafe {
441
+ uvll:: uv_udp_bind ( udp. handle , addr, 0u32 )
485
442
} ) ;
486
443
match result {
487
444
0 => Ok ( udp) ,
@@ -513,7 +470,7 @@ impl rtio::RtioUdpSocket for UdpWatcher {
513
470
struct Ctx {
514
471
task : Option < BlockedTask > ,
515
472
buf : Option < Buf > ,
516
- result : Option < ( ssize_t , SocketAddr ) > ,
473
+ result : Option < ( ssize_t , Option < SocketAddr > ) > ,
517
474
}
518
475
let _m = self . fire_homing_missile ( ) ;
519
476
@@ -532,22 +489,24 @@ impl rtio::RtioUdpSocket for UdpWatcher {
532
489
match cx. result . take_unwrap ( ) {
533
490
( n, _) if n < 0 =>
534
491
Err ( uv_error_to_io_error ( UvError ( n as c_int ) ) ) ,
535
- ( n, addr) => Ok ( ( n as uint , addr) )
492
+ ( n, addr) => Ok ( ( n as uint , addr. unwrap ( ) ) )
536
493
}
537
494
}
538
495
n => Err ( uv_error_to_io_error ( UvError ( n) ) )
539
496
} ;
540
497
return a;
541
498
542
499
extern fn alloc_cb ( handle : * uvll:: uv_udp_t ,
543
- _suggested_size : size_t ) -> Buf {
544
- let cx: & mut Ctx = unsafe {
545
- cast:: transmute ( uvll:: get_data_for_uv_handle ( handle) )
546
- } ;
547
- cx. buf . take ( ) . expect ( "recv alloc_cb called more than once" )
500
+ _suggested_size : size_t ,
501
+ buf : * mut Buf ) {
502
+ unsafe {
503
+ let cx: & mut Ctx =
504
+ cast:: transmute ( uvll:: get_data_for_uv_handle ( handle) ) ;
505
+ * buf = cx. buf . take ( ) . expect ( "recv alloc_cb called more than once" )
506
+ }
548
507
}
549
508
550
- extern fn recv_cb ( handle : * uvll:: uv_udp_t , nread : ssize_t , buf : Buf ,
509
+ extern fn recv_cb ( handle : * uvll:: uv_udp_t , nread : ssize_t , buf : * Buf ,
551
510
addr : * uvll:: sockaddr , _flags : c_uint ) {
552
511
assert ! ( nread != uvll:: ECANCELED as ssize_t) ;
553
512
let cx: & mut Ctx = unsafe {
@@ -558,7 +517,7 @@ impl rtio::RtioUdpSocket for UdpWatcher {
558
517
// This can happen if read returns EAGAIN/EWOULDBLOCK. By ignoring
559
518
// this we just drop back to kqueue and wait for the next callback.
560
519
if nread == 0 {
561
- cx. buf = Some ( buf) ;
520
+ cx. buf = Some ( unsafe { * buf } ) ;
562
521
return
563
522
}
564
523
@@ -569,8 +528,11 @@ impl rtio::RtioUdpSocket for UdpWatcher {
569
528
let cx: & mut Ctx = unsafe {
570
529
cast:: transmute ( uvll:: get_data_for_uv_handle ( handle) )
571
530
} ;
572
- let addr = sockaddr_to_UvSocketAddr ( addr) ;
573
- let addr = uv_socket_addr_to_socket_addr ( addr) ;
531
+ let addr = if addr == ptr:: null ( ) {
532
+ None
533
+ } else {
534
+ Some ( sockaddr_to_socket_addr ( addr) )
535
+ } ;
574
536
cx. result = Some ( ( nread, addr) ) ;
575
537
576
538
let sched: ~Scheduler = Local :: take ( ) ;
@@ -585,13 +547,8 @@ impl rtio::RtioUdpSocket for UdpWatcher {
585
547
586
548
let mut req = Request :: new ( uvll:: UV_UDP_SEND ) ;
587
549
let buf = slice_to_uv_buf ( buf) ;
588
- let result = socket_addr_as_uv_socket_addr ( dst, |dst| unsafe {
589
- match dst {
590
- UvIpv4SocketAddr ( dst) =>
591
- uvll:: udp_send ( req. handle , self . handle , [ buf] , dst, send_cb) ,
592
- UvIpv6SocketAddr ( dst) =>
593
- uvll:: udp_send6 ( req. handle , self . handle , [ buf] , dst, send_cb) ,
594
- }
550
+ let result = socket_addr_as_sockaddr ( dst, |dst| unsafe {
551
+ uvll:: uv_udp_send ( req. handle , self . handle , [ buf] , dst, send_cb)
595
552
} ) ;
596
553
597
554
return match result {
0 commit comments