]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/common/net2.rs
core: Fix size_hint for signed integer Range<T> iterators
[rust.git] / src / libstd / sys / common / net2.rs
1 // Copyright 2013-2014 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 use prelude::v1::*;
12
13 use ffi::{CStr, CString};
14 use io::{self, Error, ErrorKind};
15 use libc::{self, c_int, c_char, c_void, socklen_t};
16 use mem;
17 use net::{SocketAddr, Shutdown, IpAddr};
18 use str::from_utf8;
19 use sys::c;
20 use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
21 use sys_common::{AsInner, FromInner, IntoInner};
22
23 ////////////////////////////////////////////////////////////////////////////////
24 // sockaddr and misc bindings
25 ////////////////////////////////////////////////////////////////////////////////
26
27 fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
28                      payload: T) -> io::Result<()> {
29     unsafe {
30         let payload = &payload as *const T as *const c_void;
31         try!(cvt(libc::setsockopt(*sock.as_inner(), opt, val, payload,
32                                   mem::size_of::<T>() as socklen_t)));
33         Ok(())
34     }
35 }
36
37 #[allow(dead_code)]
38 fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
39                        val: c_int) -> io::Result<T> {
40     unsafe {
41         let mut slot: T = mem::zeroed();
42         let mut len = mem::size_of::<T>() as socklen_t;
43         let ret = try!(cvt(c::getsockopt(*sock.as_inner(), opt, val,
44                                          &mut slot as *mut _ as *mut _,
45                                          &mut len)));
46         assert_eq!(ret as usize, mem::size_of::<T>());
47         Ok(slot)
48     }
49 }
50
51 fn sockname<F>(f: F) -> io::Result<SocketAddr>
52     where F: FnOnce(*mut libc::sockaddr, *mut socklen_t) -> c_int
53 {
54     unsafe {
55         let mut storage: libc::sockaddr_storage = mem::zeroed();
56         let mut len = mem::size_of_val(&storage) as socklen_t;
57         try!(cvt(f(&mut storage as *mut _ as *mut _, &mut len)));
58         sockaddr_to_addr(&storage, len as usize)
59     }
60 }
61
62 fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
63                     len: usize) -> io::Result<SocketAddr> {
64     match storage.ss_family as libc::c_int {
65         libc::AF_INET => {
66             assert!(len as usize >= mem::size_of::<libc::sockaddr_in>());
67             Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
68                 *(storage as *const _ as *const libc::sockaddr_in)
69             })))
70         }
71         libc::AF_INET6 => {
72             assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
73             Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
74                 *(storage as *const _ as *const libc::sockaddr_in6)
75             })))
76         }
77         _ => {
78             Err(Error::new(ErrorKind::InvalidInput, "invalid argument"))
79         }
80     }
81 }
82
83 ////////////////////////////////////////////////////////////////////////////////
84 // get_host_addresses
85 ////////////////////////////////////////////////////////////////////////////////
86
87 extern "system" {
88     fn getaddrinfo(node: *const c_char, service: *const c_char,
89                    hints: *const libc::addrinfo,
90                    res: *mut *mut libc::addrinfo) -> c_int;
91     fn freeaddrinfo(res: *mut libc::addrinfo);
92 }
93
94 pub struct LookupHost {
95     original: *mut libc::addrinfo,
96     cur: *mut libc::addrinfo,
97 }
98
99 impl Iterator for LookupHost {
100     type Item = io::Result<SocketAddr>;
101     fn next(&mut self) -> Option<io::Result<SocketAddr>> {
102         unsafe {
103             if self.cur.is_null() { return None }
104             let ret = sockaddr_to_addr(mem::transmute((*self.cur).ai_addr),
105                                        (*self.cur).ai_addrlen as usize);
106             self.cur = (*self.cur).ai_next as *mut libc::addrinfo;
107             Some(ret)
108         }
109     }
110 }
111
112 impl Drop for LookupHost {
113     fn drop(&mut self) {
114         unsafe { freeaddrinfo(self.original) }
115     }
116 }
117
118 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
119     init();
120
121     let c_host = try!(CString::new(host));
122     let mut res = 0 as *mut _;
123     unsafe {
124         try!(cvt_gai(getaddrinfo(c_host.as_ptr(), 0 as *const _, 0 as *const _,
125                                  &mut res)));
126         Ok(LookupHost { original: res, cur: res })
127     }
128 }
129
130 ////////////////////////////////////////////////////////////////////////////////
131 // lookup_addr
132 ////////////////////////////////////////////////////////////////////////////////
133
134 extern "system" {
135     fn getnameinfo(sa: *const libc::sockaddr, salen: socklen_t,
136                    host: *mut c_char, hostlen: libc::size_t,
137                    serv: *mut c_char, servlen: libc::size_t,
138                    flags: c_int) -> c_int;
139 }
140
141 const NI_MAXHOST: usize = 1025;
142
143 pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
144     init();
145
146     let saddr = SocketAddr::new(*addr, 0);
147     let (inner, len) = saddr.into_inner();
148     let mut hostbuf = [0 as c_char; NI_MAXHOST];
149
150     let data = unsafe {
151         try!(cvt_gai(getnameinfo(inner, len,
152                                  hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t,
153                                  0 as *mut _, 0, 0)));
154
155         CStr::from_ptr(hostbuf.as_ptr())
156     };
157
158     match from_utf8(data.to_bytes()) {
159         Ok(name) => Ok(name.to_string()),
160         Err(_) => Err(io::Error::new(io::ErrorKind::Other,
161                                      "failed to lookup address information"))
162     }
163 }
164
165 ////////////////////////////////////////////////////////////////////////////////
166 // TCP streams
167 ////////////////////////////////////////////////////////////////////////////////
168
169 pub struct TcpStream {
170     inner: Socket,
171 }
172
173 impl TcpStream {
174     pub fn connect(addr: &SocketAddr) -> io::Result<TcpStream> {
175         init();
176
177         let sock = try!(Socket::new(addr, libc::SOCK_STREAM));
178
179         let (addrp, len) = addr.into_inner();
180         try!(cvt_r(|| unsafe { libc::connect(*sock.as_inner(), addrp, len) }));
181         Ok(TcpStream { inner: sock })
182     }
183
184     pub fn socket(&self) -> &Socket { &self.inner }
185
186     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
187         setsockopt(&self.inner, libc::IPPROTO_TCP, libc::TCP_NODELAY,
188                    nodelay as c_int)
189     }
190
191     pub fn set_keepalive(&self, seconds: Option<u32>) -> io::Result<()> {
192         let ret = setsockopt(&self.inner, libc::SOL_SOCKET, libc::SO_KEEPALIVE,
193                              seconds.is_some() as c_int);
194         match seconds {
195             Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)),
196             None => ret,
197         }
198     }
199
200     #[cfg(any(target_os = "macos", target_os = "ios"))]
201     fn set_tcp_keepalive(&self, seconds: u32) -> io::Result<()> {
202         setsockopt(&self.inner, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
203                    seconds as c_int)
204     }
205     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
206     fn set_tcp_keepalive(&self, seconds: u32) -> io::Result<()> {
207         setsockopt(&self.inner, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
208                    seconds as c_int)
209     }
210     #[cfg(not(any(target_os = "macos",
211                   target_os = "ios",
212                   target_os = "freebsd",
213                   target_os = "dragonfly")))]
214     fn set_tcp_keepalive(&self, _seconds: u32) -> io::Result<()> {
215         Ok(())
216     }
217
218     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
219         self.inner.read(buf)
220     }
221
222     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
223         let ret = try!(cvt(unsafe {
224             libc::send(*self.inner.as_inner(),
225                        buf.as_ptr() as *const c_void,
226                        buf.len() as wrlen_t,
227                        0)
228         }));
229         Ok(ret as usize)
230     }
231
232     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
233         sockname(|buf, len| unsafe {
234             libc::getpeername(*self.inner.as_inner(), buf, len)
235         })
236     }
237
238     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
239         sockname(|buf, len| unsafe {
240             libc::getsockname(*self.inner.as_inner(), buf, len)
241         })
242     }
243
244     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
245         use libc::consts::os::bsd44::SHUT_RDWR;
246
247         let how = match how {
248             Shutdown::Write => libc::SHUT_WR,
249             Shutdown::Read => libc::SHUT_RD,
250             Shutdown::Both => SHUT_RDWR,
251         };
252         try!(cvt(unsafe { libc::shutdown(*self.inner.as_inner(), how) }));
253         Ok(())
254     }
255
256     pub fn duplicate(&self) -> io::Result<TcpStream> {
257         self.inner.duplicate().map(|s| TcpStream { inner: s })
258     }
259 }
260
261 impl FromInner<Socket> for TcpStream {
262     fn from_inner(socket: Socket) -> TcpStream {
263         TcpStream { inner: socket }
264     }
265 }
266
267 ////////////////////////////////////////////////////////////////////////////////
268 // TCP listeners
269 ////////////////////////////////////////////////////////////////////////////////
270
271 pub struct TcpListener {
272     inner: Socket,
273 }
274
275 impl TcpListener {
276     pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
277         init();
278
279         let sock = try!(Socket::new(addr, libc::SOCK_STREAM));
280
281         // On platforms with Berkeley-derived sockets, this allows
282         // to quickly rebind a socket, without needing to wait for
283         // the OS to clean up the previous one.
284         if !cfg!(windows) {
285             try!(setsockopt(&sock, libc::SOL_SOCKET, libc::SO_REUSEADDR,
286                             1 as c_int));
287         }
288
289         // Bind our new socket
290         let (addrp, len) = addr.into_inner();
291         try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) }));
292
293         // Start listening
294         try!(cvt(unsafe { libc::listen(*sock.as_inner(), 128) }));
295         Ok(TcpListener { inner: sock })
296     }
297
298     pub fn socket(&self) -> &Socket { &self.inner }
299
300     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
301         sockname(|buf, len| unsafe {
302             libc::getsockname(*self.inner.as_inner(), buf, len)
303         })
304     }
305
306     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
307         let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
308         let mut len = mem::size_of_val(&storage) as socklen_t;
309         let sock = try!(self.inner.accept(&mut storage as *mut _ as *mut _,
310                                           &mut len));
311         let addr = try!(sockaddr_to_addr(&storage, len as usize));
312         Ok((TcpStream { inner: sock, }, addr))
313     }
314
315     pub fn duplicate(&self) -> io::Result<TcpListener> {
316         self.inner.duplicate().map(|s| TcpListener { inner: s })
317     }
318 }
319
320 impl FromInner<Socket> for TcpListener {
321     fn from_inner(socket: Socket) -> TcpListener {
322         TcpListener { inner: socket }
323     }
324 }
325
326 ////////////////////////////////////////////////////////////////////////////////
327 // UDP
328 ////////////////////////////////////////////////////////////////////////////////
329
330 pub struct UdpSocket {
331     inner: Socket,
332 }
333
334 impl UdpSocket {
335     pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
336         init();
337
338         let sock = try!(Socket::new(addr, libc::SOCK_DGRAM));
339         let (addrp, len) = addr.into_inner();
340         try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) }));
341         Ok(UdpSocket { inner: sock })
342     }
343
344     pub fn socket(&self) -> &Socket { &self.inner }
345
346     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
347         sockname(|buf, len| unsafe {
348             libc::getsockname(*self.inner.as_inner(), buf, len)
349         })
350     }
351
352     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
353         let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
354         let mut addrlen = mem::size_of_val(&storage) as socklen_t;
355
356         let n = try!(cvt(unsafe {
357             libc::recvfrom(*self.inner.as_inner(),
358                            buf.as_mut_ptr() as *mut c_void,
359                            buf.len() as wrlen_t, 0,
360                            &mut storage as *mut _ as *mut _, &mut addrlen)
361         }));
362         Ok((n as usize, try!(sockaddr_to_addr(&storage, addrlen as usize))))
363     }
364
365     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
366         let (dstp, dstlen) = dst.into_inner();
367         let ret = try!(cvt(unsafe {
368             libc::sendto(*self.inner.as_inner(),
369                          buf.as_ptr() as *const c_void, buf.len() as wrlen_t,
370                          0, dstp, dstlen)
371         }));
372         Ok(ret as usize)
373     }
374
375     pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
376         setsockopt(&self.inner, libc::SOL_SOCKET, libc::SO_BROADCAST,
377                    on as c_int)
378     }
379
380     pub fn set_multicast_loop(&self, on: bool) -> io::Result<()> {
381         setsockopt(&self.inner, libc::IPPROTO_IP,
382                    libc::IP_MULTICAST_LOOP, on as c_int)
383     }
384
385     pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
386         match *multi {
387             IpAddr::V4(..) => {
388                 self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
389             }
390             IpAddr::V6(..) => {
391                 self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
392             }
393         }
394     }
395     pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
396         match *multi {
397             IpAddr::V4(..) => {
398                 self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
399             }
400             IpAddr::V6(..) => {
401                 self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
402             }
403         }
404     }
405     fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> {
406         match *addr {
407             IpAddr::V4(ref addr) => {
408                 let mreq = libc::ip_mreq {
409                     imr_multiaddr: *addr.as_inner(),
410                     // interface == INADDR_ANY
411                     imr_interface: libc::in_addr { s_addr: 0x0 },
412                 };
413                 setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq)
414             }
415             IpAddr::V6(ref addr) => {
416                 let mreq = libc::ip6_mreq {
417                     ipv6mr_multiaddr: *addr.as_inner(),
418                     ipv6mr_interface: 0,
419                 };
420                 setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq)
421             }
422         }
423     }
424
425     pub fn multicast_time_to_live(&self, ttl: i32) -> io::Result<()> {
426         setsockopt(&self.inner, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL,
427                    ttl as c_int)
428     }
429
430     pub fn time_to_live(&self, ttl: i32) -> io::Result<()> {
431         setsockopt(&self.inner, libc::IPPROTO_IP, libc::IP_TTL, ttl as c_int)
432     }
433
434     pub fn duplicate(&self) -> io::Result<UdpSocket> {
435         self.inner.duplicate().map(|s| UdpSocket { inner: s })
436     }
437 }
438
439 impl FromInner<Socket> for UdpSocket {
440     fn from_inner(socket: Socket) -> UdpSocket {
441         UdpSocket { inner: socket }
442     }
443 }