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