@@ -5,7 +5,7 @@ use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK};
5
5
use fcntl:: FcntlArg :: { F_SETFD , F_SETFL } ;
6
6
use libc:: { c_void, c_int, socklen_t, size_t, ssize_t} ;
7
7
use std:: { fmt, mem, net, ptr, path} ;
8
- use std:: ffi:: AsOsStr ;
8
+ use std:: ffi:: { AsOsStr , CStr , OsStr } ;
9
9
use std:: os:: unix:: prelude:: * ;
10
10
11
11
/*
@@ -63,14 +63,30 @@ pub enum SockAddr {
63
63
SockUnix ( sockaddr_un )
64
64
}
65
65
66
- /// Convert a value into a socket address
67
- pub trait AsSockAddr {
68
- fn as_sock_addr ( & self ) -> NixResult < SockAddr > ;
66
+ /// A trait for values which can be converted or resolved to a SockAddr.
67
+ pub trait ToSockAddr {
68
+ /// Converts the value to a SockAddr
69
+ fn to_sock_addr ( & self ) -> NixResult < SockAddr > ;
70
+
71
+ /// Converts and yields the value as a SockAddr
72
+ fn with_sock_addr < T , F : FnOnce ( & SockAddr ) -> T > ( & self , action : F ) -> NixResult < T > {
73
+ Ok ( action ( & try!( self . to_sock_addr ( ) ) ) )
74
+ }
75
+ }
76
+
77
+ impl ToSockAddr for SockAddr {
78
+ fn to_sock_addr ( & self ) -> NixResult < SockAddr > {
79
+ Ok ( * self )
80
+ }
81
+
82
+ fn with_sock_addr < T , F : FnOnce ( & SockAddr ) -> T > ( & self , action : F ) -> NixResult < T > {
83
+ Ok ( action ( self ) )
84
+ }
69
85
}
70
86
71
87
/// Convert a path into a unix domain socket address
72
- impl AsSockAddr for path:: Path {
73
- fn as_sock_addr ( & self ) -> NixResult < SockAddr > {
88
+ impl ToSockAddr for path:: Path {
89
+ fn to_sock_addr ( & self ) -> NixResult < SockAddr > {
74
90
let bytes = self . as_os_str ( ) . as_bytes ( ) ;
75
91
76
92
Ok ( SockAddr :: SockUnix ( unsafe {
@@ -96,8 +112,8 @@ impl AsSockAddr for path::Path {
96
112
}
97
113
98
114
/// Convert an inet address into a socket address
99
- impl AsSockAddr for net:: SocketAddr {
100
- fn as_sock_addr ( & self ) -> NixResult < SockAddr > {
115
+ impl ToSockAddr for net:: SocketAddr {
116
+ fn to_sock_addr ( & self ) -> NixResult < SockAddr > {
101
117
use std:: net:: IpAddr ;
102
118
use std:: num:: Int ;
103
119
@@ -122,6 +138,47 @@ impl AsSockAddr for net::SocketAddr {
122
138
}
123
139
}
124
140
141
+ /// Convert from a socket address
142
+ pub trait FromSockAddr {
143
+ fn from_sock_addr ( addr : & SockAddr ) -> Option < Self > ;
144
+ }
145
+
146
+ impl FromSockAddr for net:: SocketAddr {
147
+ fn from_sock_addr ( addr : & SockAddr ) -> Option < net:: SocketAddr > {
148
+ use std:: net:: { IpAddr , Ipv4Addr } ;
149
+ use std:: num:: Int ;
150
+
151
+ match * addr {
152
+ SockAddr :: SockIpV4 ( ref addr) => {
153
+ let ip = Int :: from_be ( addr. sin_addr . s_addr ) ;
154
+ let ip = Ipv4Addr :: new (
155
+ ( ( ip >> 24 ) as u8 ) & 0xff ,
156
+ ( ( ip >> 16 ) as u8 ) & 0xff ,
157
+ ( ( ip >> 8 ) as u8 ) & 0xff ,
158
+ ( ( ip >> 0 ) as u8 ) & 0xff ) ;
159
+
160
+ Some ( net:: SocketAddr :: new ( IpAddr :: V4 ( ip) , addr. sin_port ) )
161
+ }
162
+ SockAddr :: SockIpV6 ( _) => unimplemented ! ( ) ,
163
+ _ => None ,
164
+ }
165
+ }
166
+ }
167
+
168
+ impl FromSockAddr for path:: PathBuf {
169
+ fn from_sock_addr ( addr : & SockAddr ) -> Option < path:: PathBuf > {
170
+ if let SockAddr :: SockUnix ( ref addr) = * addr {
171
+ unsafe {
172
+ let bytes = CStr :: from_ptr ( addr. sun_path . as_ptr ( ) ) . to_bytes ( ) ;
173
+ let osstr = <OsStr as OsStrExt >:: from_bytes ( bytes) ;
174
+ return Some ( path:: PathBuf :: new ( osstr) ) ;
175
+ }
176
+ }
177
+
178
+ None
179
+ }
180
+ }
181
+
125
182
/*
126
183
*
127
184
* ===== Consts =====
@@ -347,15 +404,17 @@ pub fn listen(sockfd: Fd, backlog: usize) -> NixResult<()> {
347
404
from_ffi ( res)
348
405
}
349
406
350
- pub fn bind ( sockfd : Fd , addr : & SockAddr ) -> NixResult < ( ) > {
407
+ pub fn bind < A : ToSockAddr > ( sockfd : Fd , addr : & A ) -> NixResult < ( ) > {
351
408
use self :: SockAddr :: * ;
352
409
353
410
let res = unsafe {
354
- match * addr {
355
- SockIpV4 ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in > ( ) as socklen_t ) ,
356
- SockIpV6 ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ) ,
357
- SockUnix ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_un > ( ) as socklen_t )
358
- }
411
+ try!( addr. with_sock_addr ( |addr| {
412
+ match * addr {
413
+ SockIpV4 ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in > ( ) as socklen_t ) ,
414
+ SockIpV6 ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ) ,
415
+ SockUnix ( ref addr) => ffi:: bind ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_un > ( ) as socklen_t )
416
+ }
417
+ } ) )
359
418
} ;
360
419
361
420
from_ffi ( res)
@@ -422,15 +481,17 @@ fn accept4_polyfill(sockfd: Fd, flags: SockFlag) -> NixResult<Fd> {
422
481
Ok ( res)
423
482
}
424
483
425
- pub fn connect ( sockfd : Fd , addr : & SockAddr ) -> NixResult < ( ) > {
484
+ pub fn connect < A : ToSockAddr > ( sockfd : Fd , addr : & A ) -> NixResult < ( ) > {
426
485
use self :: SockAddr :: * ;
427
486
428
487
let res = unsafe {
429
- match * addr {
430
- SockIpV4 ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in > ( ) as socklen_t ) ,
431
- SockIpV6 ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ) ,
432
- SockUnix ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_un > ( ) as socklen_t )
433
- }
488
+ try!( addr. with_sock_addr ( |addr| {
489
+ match * addr {
490
+ SockIpV4 ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in > ( ) as socklen_t ) ,
491
+ SockIpV6 ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ) ,
492
+ SockUnix ( ref addr) => ffi:: connect ( sockfd, mem:: transmute ( addr) , mem:: size_of :: < sockaddr_un > ( ) as socklen_t )
493
+ }
494
+ } ) )
434
495
} ;
435
496
436
497
from_ffi ( res)
0 commit comments