]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/common/net.rs
Auto merge of #34686 - alexcrichton:new-stage, r=luqmana
[rust.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 cmp;
14 use ffi::CString;
15 use fmt;
16 use io::{self, Error, ErrorKind};
17 use libc::{c_int, c_void};
18 use mem;
19 use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
20 use ptr;
21 use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
22 use sys::net::netc as c;
23 use sys_common::{AsInner, FromInner, IntoInner};
24 use time::Duration;
25
26 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
27           target_os = "ios", target_os = "macos",
28           target_os = "openbsd", target_os = "netbsd"))]
29 use sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
30 #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
31               target_os = "ios", target_os = "macos",
32           target_os = "openbsd", target_os = "netbsd")))]
33 use sys::net::netc::IPV6_ADD_MEMBERSHIP;
34 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
35           target_os = "ios", target_os = "macos",
36           target_os = "openbsd", target_os = "netbsd"))]
37 use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
38 #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd",
39               target_os = "ios", target_os = "macos",
40           target_os = "openbsd", target_os = "netbsd")))]
41 use sys::net::netc::IPV6_DROP_MEMBERSHIP;
42
43 ////////////////////////////////////////////////////////////////////////////////
44 // sockaddr and misc bindings
45 ////////////////////////////////////////////////////////////////////////////////
46
47 pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int,
48                      payload: T) -> io::Result<()> {
49     unsafe {
50         let payload = &payload as *const T as *const c_void;
51         cvt(c::setsockopt(*sock.as_inner(), opt, val, payload,
52                           mem::size_of::<T>() as c::socklen_t))?;
53         Ok(())
54     }
55 }
56
57 pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
58                        val: c_int) -> io::Result<T> {
59     unsafe {
60         let mut slot: T = mem::zeroed();
61         let mut len = mem::size_of::<T>() as c::socklen_t;
62         cvt(c::getsockopt(*sock.as_inner(), opt, val,
63                           &mut slot as *mut _ as *mut _,
64                           &mut len))?;
65         assert_eq!(len as usize, mem::size_of::<T>());
66         Ok(slot)
67     }
68 }
69
70 fn sockname<F>(f: F) -> io::Result<SocketAddr>
71     where F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int
72 {
73     unsafe {
74         let mut storage: c::sockaddr_storage = mem::zeroed();
75         let mut len = mem::size_of_val(&storage) as c::socklen_t;
76         cvt(f(&mut storage as *mut _ as *mut _, &mut len))?;
77         sockaddr_to_addr(&storage, len as usize)
78     }
79 }
80
81 fn sockaddr_to_addr(storage: &c::sockaddr_storage,
82                     len: usize) -> io::Result<SocketAddr> {
83     match storage.ss_family as c_int {
84         c::AF_INET => {
85             assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
86             Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
87                 *(storage as *const _ as *const c::sockaddr_in)
88             })))
89         }
90         c::AF_INET6 => {
91             assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
92             Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
93                 *(storage as *const _ as *const c::sockaddr_in6)
94             })))
95         }
96         _ => {
97             Err(Error::new(ErrorKind::InvalidInput, "invalid argument"))
98         }
99     }
100 }
101
102 #[cfg(target_os = "android")]
103 fn to_ipv6mr_interface(value: u32) -> c_int {
104     value as c_int
105 }
106
107 #[cfg(not(target_os = "android"))]
108 fn to_ipv6mr_interface(value: u32) -> ::libc::c_uint {
109     value as ::libc::c_uint
110 }
111
112 ////////////////////////////////////////////////////////////////////////////////
113 // get_host_addresses
114 ////////////////////////////////////////////////////////////////////////////////
115
116 pub struct LookupHost {
117     original: *mut c::addrinfo,
118     cur: *mut c::addrinfo,
119 }
120
121 impl Iterator for LookupHost {
122     type Item = SocketAddr;
123     fn next(&mut self) -> Option<SocketAddr> {
124         loop {
125             unsafe {
126                 let cur = match self.cur.as_ref() {
127                     None => return None,
128                     Some(c) => c,
129                 };
130                 self.cur = cur.ai_next;
131                 match sockaddr_to_addr(mem::transmute(cur.ai_addr),
132                                        cur.ai_addrlen as usize)
133                 {
134                     Ok(addr) => return Some(addr),
135                     Err(_) => continue,
136                 }
137             }
138         }
139     }
140 }
141
142 unsafe impl Sync for LookupHost {}
143 unsafe impl Send for LookupHost {}
144
145 impl Drop for LookupHost {
146     fn drop(&mut self) {
147         unsafe { c::freeaddrinfo(self.original) }
148     }
149 }
150
151 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
152     init();
153
154     let c_host = CString::new(host)?;
155     let hints = c::addrinfo {
156         ai_flags: 0,
157         ai_family: 0,
158         ai_socktype: c::SOCK_STREAM,
159         ai_protocol: 0,
160         ai_addrlen: 0,
161         ai_addr: ptr::null_mut(),
162         ai_canonname: ptr::null_mut(),
163         ai_next: ptr::null_mut()
164     };
165     let mut res = ptr::null_mut();
166     unsafe {
167         cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints,
168                                &mut res))?;
169         Ok(LookupHost { original: res, cur: res })
170     }
171 }
172
173 ////////////////////////////////////////////////////////////////////////////////
174 // TCP streams
175 ////////////////////////////////////////////////////////////////////////////////
176
177 pub struct TcpStream {
178     inner: Socket,
179 }
180
181 impl TcpStream {
182     pub fn connect(addr: &SocketAddr) -> io::Result<TcpStream> {
183         init();
184
185         let sock = Socket::new(addr, c::SOCK_STREAM)?;
186
187         let (addrp, len) = addr.into_inner();
188         cvt_r(|| unsafe { c::connect(*sock.as_inner(), addrp, len) })?;
189         Ok(TcpStream { inner: sock })
190     }
191
192     pub fn socket(&self) -> &Socket { &self.inner }
193
194     pub fn into_socket(self) -> Socket { self.inner }
195
196     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
197         self.inner.set_timeout(dur, c::SO_RCVTIMEO)
198     }
199
200     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
201         self.inner.set_timeout(dur, c::SO_SNDTIMEO)
202     }
203
204     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
205         self.inner.timeout(c::SO_RCVTIMEO)
206     }
207
208     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
209         self.inner.timeout(c::SO_SNDTIMEO)
210     }
211
212     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
213         self.inner.read(buf)
214     }
215
216     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
217         self.inner.read_to_end(buf)
218     }
219
220     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
221         let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
222         let ret = cvt(unsafe {
223             c::send(*self.inner.as_inner(),
224                     buf.as_ptr() as *const c_void,
225                     len,
226                     0)
227         })?;
228         Ok(ret as usize)
229     }
230
231     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
232         sockname(|buf, len| unsafe {
233             c::getpeername(*self.inner.as_inner(), buf, len)
234         })
235     }
236
237     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
238         sockname(|buf, len| unsafe {
239             c::getsockname(*self.inner.as_inner(), buf, len)
240         })
241     }
242
243     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
244         self.inner.shutdown(how)
245     }
246
247     pub fn duplicate(&self) -> io::Result<TcpStream> {
248         self.inner.duplicate().map(|s| TcpStream { inner: s })
249     }
250
251     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
252         self.inner.set_nodelay(nodelay)
253     }
254
255     pub fn nodelay(&self) -> io::Result<bool> {
256         self.inner.nodelay()
257     }
258
259     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
260         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
261     }
262
263     pub fn ttl(&self) -> io::Result<u32> {
264         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
265         Ok(raw as u32)
266     }
267
268     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
269         self.inner.take_error()
270     }
271
272     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
273         self.inner.set_nonblocking(nonblocking)
274     }
275 }
276
277 impl FromInner<Socket> for TcpStream {
278     fn from_inner(socket: Socket) -> TcpStream {
279         TcpStream { inner: socket }
280     }
281 }
282
283 impl fmt::Debug for TcpStream {
284     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285         let mut res = f.debug_struct("TcpStream");
286
287         if let Ok(addr) = self.socket_addr() {
288             res.field("addr", &addr);
289         }
290
291         if let Ok(peer) = self.peer_addr() {
292             res.field("peer", &peer);
293         }
294
295         let name = if cfg!(windows) {"socket"} else {"fd"};
296         res.field(name, &self.inner.as_inner())
297             .finish()
298     }
299 }
300
301 ////////////////////////////////////////////////////////////////////////////////
302 // TCP listeners
303 ////////////////////////////////////////////////////////////////////////////////
304
305 pub struct TcpListener {
306     inner: Socket,
307 }
308
309 impl TcpListener {
310     pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
311         init();
312
313         let sock = Socket::new(addr, c::SOCK_STREAM)?;
314
315         // On platforms with Berkeley-derived sockets, this allows
316         // to quickly rebind a socket, without needing to wait for
317         // the OS to clean up the previous one.
318         if !cfg!(windows) {
319             setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR,
320                        1 as c_int)?;
321         }
322
323         // Bind our new socket
324         let (addrp, len) = addr.into_inner();
325         cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
326
327         // Start listening
328         cvt(unsafe { c::listen(*sock.as_inner(), 128) })?;
329         Ok(TcpListener { inner: sock })
330     }
331
332     pub fn socket(&self) -> &Socket { &self.inner }
333
334     pub fn into_socket(self) -> Socket { self.inner }
335
336     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
337         sockname(|buf, len| unsafe {
338             c::getsockname(*self.inner.as_inner(), buf, len)
339         })
340     }
341
342     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
343         let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
344         let mut len = mem::size_of_val(&storage) as c::socklen_t;
345         let sock = self.inner.accept(&mut storage as *mut _ as *mut _,
346                                      &mut len)?;
347         let addr = sockaddr_to_addr(&storage, len as usize)?;
348         Ok((TcpStream { inner: sock, }, addr))
349     }
350
351     pub fn duplicate(&self) -> io::Result<TcpListener> {
352         self.inner.duplicate().map(|s| TcpListener { inner: s })
353     }
354
355     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
356         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
357     }
358
359     pub fn ttl(&self) -> io::Result<u32> {
360         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
361         Ok(raw as u32)
362     }
363
364     pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
365         setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
366     }
367
368     pub fn only_v6(&self) -> io::Result<bool> {
369         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
370         Ok(raw != 0)
371     }
372
373     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
374         self.inner.take_error()
375     }
376
377     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
378         self.inner.set_nonblocking(nonblocking)
379     }
380 }
381
382 impl FromInner<Socket> for TcpListener {
383     fn from_inner(socket: Socket) -> TcpListener {
384         TcpListener { inner: socket }
385     }
386 }
387
388 impl fmt::Debug for TcpListener {
389     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
390         let mut res = f.debug_struct("TcpListener");
391
392         if let Ok(addr) = self.socket_addr() {
393             res.field("addr", &addr);
394         }
395
396         let name = if cfg!(windows) {"socket"} else {"fd"};
397         res.field(name, &self.inner.as_inner())
398             .finish()
399     }
400 }
401
402 ////////////////////////////////////////////////////////////////////////////////
403 // UDP
404 ////////////////////////////////////////////////////////////////////////////////
405
406 pub struct UdpSocket {
407     inner: Socket,
408 }
409
410 impl UdpSocket {
411     pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
412         init();
413
414         let sock = Socket::new(addr, c::SOCK_DGRAM)?;
415         let (addrp, len) = addr.into_inner();
416         cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
417         Ok(UdpSocket { inner: sock })
418     }
419
420     pub fn socket(&self) -> &Socket { &self.inner }
421
422     pub fn into_socket(self) -> Socket { self.inner }
423
424     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
425         sockname(|buf, len| unsafe {
426             c::getsockname(*self.inner.as_inner(), buf, len)
427         })
428     }
429
430     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
431         let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
432         let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
433         let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
434
435         let n = cvt(unsafe {
436             c::recvfrom(*self.inner.as_inner(),
437                         buf.as_mut_ptr() as *mut c_void,
438                         len, 0,
439                         &mut storage as *mut _ as *mut _, &mut addrlen)
440         })?;
441         Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
442     }
443
444     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
445         let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
446         let (dstp, dstlen) = dst.into_inner();
447         let ret = cvt(unsafe {
448             c::sendto(*self.inner.as_inner(),
449                       buf.as_ptr() as *const c_void, len,
450                       0, dstp, dstlen)
451         })?;
452         Ok(ret as usize)
453     }
454
455     pub fn duplicate(&self) -> io::Result<UdpSocket> {
456         self.inner.duplicate().map(|s| UdpSocket { inner: s })
457     }
458
459     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
460         self.inner.set_timeout(dur, c::SO_RCVTIMEO)
461     }
462
463     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
464         self.inner.set_timeout(dur, c::SO_SNDTIMEO)
465     }
466
467     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
468         self.inner.timeout(c::SO_RCVTIMEO)
469     }
470
471     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
472         self.inner.timeout(c::SO_SNDTIMEO)
473     }
474
475     pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
476         setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
477     }
478
479     pub fn broadcast(&self) -> io::Result<bool> {
480         let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
481         Ok(raw != 0)
482     }
483
484     pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
485         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP, multicast_loop_v4 as c_int)
486     }
487
488     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
489         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
490         Ok(raw != 0)
491     }
492
493     pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
494         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, multicast_ttl_v4 as c_int)
495     }
496
497     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
498         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
499         Ok(raw as u32)
500     }
501
502     pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
503         setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
504     }
505
506     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
507         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
508         Ok(raw != 0)
509     }
510
511     pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
512                          -> io::Result<()> {
513         let mreq = c::ip_mreq {
514             imr_multiaddr: *multiaddr.as_inner(),
515             imr_interface: *interface.as_inner(),
516         };
517         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
518     }
519
520     pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
521                          -> io::Result<()> {
522         let mreq = c::ipv6_mreq {
523             ipv6mr_multiaddr: *multiaddr.as_inner(),
524             ipv6mr_interface: to_ipv6mr_interface(interface),
525         };
526         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
527     }
528
529     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
530                           -> io::Result<()> {
531         let mreq = c::ip_mreq {
532             imr_multiaddr: *multiaddr.as_inner(),
533             imr_interface: *interface.as_inner(),
534         };
535         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
536     }
537
538     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
539                           -> io::Result<()> {
540         let mreq = c::ipv6_mreq {
541             ipv6mr_multiaddr: *multiaddr.as_inner(),
542             ipv6mr_interface: to_ipv6mr_interface(interface),
543         };
544         setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
545     }
546
547     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
548         setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
549     }
550
551     pub fn ttl(&self) -> io::Result<u32> {
552         let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
553         Ok(raw as u32)
554     }
555
556     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
557         self.inner.take_error()
558     }
559
560     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
561         self.inner.set_nonblocking(nonblocking)
562     }
563
564     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
565         self.inner.read(buf)
566     }
567
568     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
569         let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
570         let ret = cvt(unsafe {
571             c::send(*self.inner.as_inner(),
572                     buf.as_ptr() as *const c_void,
573                     len,
574                     0)
575         })?;
576         Ok(ret as usize)
577     }
578
579     pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
580         let (addrp, len) = addr.into_inner();
581         cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(|_| ())
582     }
583 }
584
585 impl FromInner<Socket> for UdpSocket {
586     fn from_inner(socket: Socket) -> UdpSocket {
587         UdpSocket { inner: socket }
588     }
589 }
590
591 impl fmt::Debug for UdpSocket {
592     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593         let mut res = f.debug_struct("UdpSocket");
594
595         if let Ok(addr) = self.socket_addr() {
596             res.field("addr", &addr);
597         }
598
599         let name = if cfg!(windows) {"socket"} else {"fd"};
600         res.field(name, &self.inner.as_inner())
601             .finish()
602     }
603 }
604
605 #[cfg(test)]
606 mod tests {
607     use prelude::v1::*;
608
609     use super::*;
610     use collections::HashMap;
611
612     #[test]
613     fn no_lookup_host_duplicates() {
614         let mut addrs = HashMap::new();
615         let lh = match lookup_host("localhost") {
616             Ok(lh) => lh,
617             Err(e) => panic!("couldn't resolve `localhost': {}", e)
618         };
619         let _na = lh.map(|sa| *addrs.entry(sa).or_insert(0) += 1).count();
620         assert!(addrs.values().filter(|&&v| v > 1).count() == 0);
621     }
622 }