1#[cfg_attr(test, macro_use)]
2extern crate log;
3
4use core::fmt;
5
6use byteorder::{BigEndian, ByteOrder};
7#[cfg(feature = "proto-ipv4")]
8use smoltcp::wire::Ipv4Address;
9#[cfg(feature = "proto-ipv6")]
10use smoltcp::wire::Ipv6Address;
11#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
12use smoltcp::wire::{IpAddress, IpEndpoint};
13
14#[cfg(feature = "proto-ipv4")]
15pub use crate::ipv4::{ipv4_addr, ipv4_addr_from_bytes, SocketAddrV4};
16#[cfg(feature = "proto-ipv6")]
17pub use crate::ipv6::{ipv6_addr, ipv6_addr_from_bytes, SocketAddrV6};
18#[cfg(feature = "std")]
19pub use crate::std::*;
20
21type Result<T> = core::result::Result<T, Error>;
22
23pub const LEN_V4: usize = 6;
24pub const LEN_V6: usize = 18;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum Error {
28 AddrParseError,
29 UnspecifiedIp,
30}
31
32impl ::std::error::Error for Error {}
33
34impl fmt::Display for Error {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 match self {
37 Error::AddrParseError => write!(f, "invalid IP address bytes"),
38 Error::UnspecifiedIp => write!(f, "UnspecifiedIp"),
39 }
40 }
41}
42
43pub fn port_from_bytes(high: u8, low: u8) -> u16 {
45 u16::from(high) << 8 | u16::from(low)
46}
47
48pub fn port_to_bytes(port: u16) -> [u8; 2] {
49 let mut buf = [0; 2];
50 BigEndian::write_u16(&mut buf, port);
51 buf
52}
53
54#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
55#[derive(Copy, Clone, Eq, Hash, PartialEq)]
56pub enum SocketAddr {
57 #[cfg(feature = "proto-ipv4")]
59 V4(SocketAddrV4),
60 #[cfg(feature = "proto-ipv6")]
62 V6(SocketAddrV6),
63}
64
65#[allow(clippy::len_without_is_empty)]
66#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
67impl SocketAddr {
68 pub fn new(ip: IpAddress, port: u16) -> Result<Self> {
69 match ip {
70 #[cfg(feature = "proto-ipv4")]
71 IpAddress::Ipv4(ip) => Ok(SocketAddr::new_v4(ip, port)),
72 #[cfg(feature = "proto-ipv6")]
73 IpAddress::Ipv6(ip) => Ok(SocketAddr::V6(SocketAddrV6::new(ip, port))),
74 IpAddress::Unspecified => Err(Error::UnspecifiedIp),
75 _ => unreachable!(),
76 }
77 }
78
79 #[cfg(feature = "proto-ipv4")]
80 pub fn new_v4(ip: Ipv4Address, port: u16) -> Self {
81 SocketAddr::V4(SocketAddrV4::new(ip, port))
82 }
83
84 #[cfg(feature = "proto-ipv4")]
85 pub fn v4_from_bytes(bytes: &[u8]) -> Result<Self> {
86 if bytes.len() == LEN_V4 {
87 let ip_addr = ipv4_addr_from_bytes(&bytes[0..LEN_V4 - 2])?;
88 let port_bytes = &bytes[LEN_V4 - 2..LEN_V4];
89 let port = port_from_bytes(port_bytes[0], port_bytes[1]);
90 Ok(SocketAddr::new_v4(ip_addr, port))
91 } else {
92 Err(Error::AddrParseError)
93 }
94 }
95
96 #[cfg(feature = "proto-ipv4")]
97 pub fn new_ip4_port(a0: u8, a1: u8, a2: u8, a3: u8, port: u16) -> Self {
98 SocketAddr::V4(SocketAddrV4::new_ip4_port(a0, a1, a2, a3, port))
99 }
100
101 #[cfg(feature = "proto-ipv6")]
102 pub fn new_v6(ip: Ipv6Address, port: u16) -> Self {
103 SocketAddr::V6(SocketAddrV6::new(ip, port))
104 }
105
106 #[cfg(feature = "proto-ipv6")]
107 pub fn v6_from_bytes(bytes: &[u8]) -> Result<Self> {
108 if bytes.len() == LEN_V6 {
109 let ip_addr = ipv6_addr_from_bytes(&bytes[0..LEN_V6 - 2])?;
110 let port_bytes = &bytes[LEN_V6 - 2..LEN_V6];
111 let port = port_from_bytes(port_bytes[0], port_bytes[1]);
112 Ok(SocketAddr::new_v6(ip_addr, port))
113 } else {
114 Err(Error::AddrParseError)
115 }
116 }
117
118 #[cfg(feature = "proto-ipv6")]
119 #[allow(clippy::too_many_arguments)]
120 pub fn new_ip6_port(
121 a0: u16,
122 a1: u16,
123 a2: u16,
124 a3: u16,
125 a4: u16,
126 a5: u16,
127 a6: u16,
128 a7: u16,
129 port: u16,
130 ) -> Self {
131 SocketAddr::V6(SocketAddrV6::new_ip6_port(
132 a0, a1, a2, a3, a4, a5, a6, a7, port,
133 ))
134 }
135
136 pub fn len(&self) -> usize {
137 match self {
138 #[cfg(feature = "proto-ipv4")]
139 SocketAddr::V4(addr) => addr.len(),
140 #[cfg(feature = "proto-ipv6")]
141 SocketAddr::V6(addr) => addr.len(),
142 }
143 }
144
145 pub fn ip(&self) -> IpAddress {
146 match self {
147 #[cfg(feature = "proto-ipv4")]
148 SocketAddr::V4(addr) => IpAddress::Ipv4(addr.addr),
149 #[cfg(feature = "proto-ipv6")]
150 SocketAddr::V6(addr) => IpAddress::Ipv6(addr.addr),
151 }
152 }
153
154 pub fn ip_octets(&self) -> Vec<u8> {
155 match self {
156 #[cfg(feature = "proto-ipv4")]
157 SocketAddr::V4(addr) => addr.addr.0.to_vec(),
158 #[cfg(feature = "proto-ipv6")]
159 SocketAddr::V6(addr) => addr.addr.0.to_vec(),
160 }
161 }
162
163 pub fn port(&self) -> u16 {
164 match self {
165 #[cfg(feature = "proto-ipv4")]
166 SocketAddr::V4(addr) => addr.port,
167 #[cfg(feature = "proto-ipv6")]
168 SocketAddr::V6(addr) => addr.port,
169 }
170 }
171
172 pub fn to_vec(&self) -> Vec<u8> {
173 match self {
174 #[cfg(feature = "proto-ipv4")]
175 SocketAddr::V4(addr) => addr.to_vec(),
176 #[cfg(feature = "proto-ipv6")]
177 SocketAddr::V6(addr) => addr.to_vec(),
178 }
179 }
180}
181
182#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
183impl From<SocketAddr> for IpEndpoint {
184 fn from(val: SocketAddr) -> Self {
185 match val {
186 #[cfg(feature = "proto-ipv4")]
187 SocketAddr::V4(val) => IpEndpoint::new(IpAddress::Ipv4(val.addr), val.port),
188 #[cfg(feature = "proto-ipv6")]
189 SocketAddr::V6(val) => IpEndpoint::new(IpAddress::Ipv6(val.addr), val.port),
190 }
191 }
192}
193
194#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
195impl fmt::Display for SocketAddr {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 match *self {
198 #[cfg(feature = "proto-ipv4")]
199 SocketAddr::V4(ref a) => a.fmt(f),
200 #[cfg(feature = "proto-ipv6")]
201 SocketAddr::V6(ref a) => a.fmt(f),
202 }
203 }
204}
205
206#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
207impl fmt::Debug for SocketAddr {
208 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
209 fmt::Display::fmt(self, fmt)
210 }
211}
212
213#[cfg(feature = "proto-ipv4")]
214mod ipv4 {
215 use core::fmt;
216
217 use smoltcp::wire::Ipv4Address;
218
219 use super::{port_to_bytes, Error, Result, LEN_V4};
220
221 pub fn ipv4_addr_from_bytes(bytes: &[u8]) -> Result<Ipv4Address> {
222 if bytes.len() == 4 {
223 Ok(Ipv4Address::from_bytes(bytes))
224 } else {
225 Err(Error::AddrParseError)
226 }
227 }
228
229 pub fn ipv4_addr(a0: u8, a1: u8, a2: u8, a3: u8) -> Ipv4Address {
230 ipv4_addr_from_bytes(&[a0, a1, a2, a3]).expect("should be valid")
231 }
232
233 #[derive(Copy, Clone, Eq, Hash, PartialEq)]
234 pub struct SocketAddrV4 {
235 pub addr: Ipv4Address,
236 pub port: u16,
237 }
238
239 #[allow(clippy::len_without_is_empty)]
240 #[allow(clippy::trivially_copy_pass_by_ref)]
241 impl SocketAddrV4 {
242 pub fn new(addr: Ipv4Address, port: u16) -> Self {
243 SocketAddrV4 { addr, port }
244 }
245
246 pub fn new_ip4_port(a0: u8, a1: u8, a2: u8, a3: u8, port: u16) -> Self {
247 SocketAddrV4 {
248 addr: Ipv4Address::new(a0, a1, a2, a3),
249 port,
250 }
251 }
252
253 pub fn len(&self) -> usize {
254 LEN_V4
255 }
256
257 pub fn to_vec(&self) -> Vec<u8> {
258 let mut result = Vec::with_capacity(self.len());
259 result.extend_from_slice(&self.addr.0);
260 result.extend_from_slice(&port_to_bytes(self.port));
261 result
262 }
263 }
264
265 impl fmt::Display for SocketAddrV4 {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 write!(f, "{}:{}", self.addr, self.port)
268 }
269 }
270
271 impl fmt::Debug for SocketAddrV4 {
272 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
273 fmt::Display::fmt(self, fmt)
274 }
275 }
276}
277
278#[cfg(feature = "proto-ipv6")]
279mod ipv6 {
280 use core::fmt;
281
282 use byteorder::{BigEndian, ByteOrder};
283 use smoltcp::wire::Ipv6Address;
284
285 use super::{port_to_bytes, Error, Result, LEN_V6};
286
287 #[cfg(feature = "proto-ipv6")]
288 pub fn ipv6_addr_from_bytes(bytes: &[u8]) -> Result<Ipv6Address> {
289 if bytes.len() == 16 {
290 Ok(Ipv6Address::from_bytes(bytes))
291 } else {
292 Err(Error::AddrParseError)
293 }
294 }
295
296 #[allow(clippy::too_many_arguments)]
297 pub fn ipv6_addr(
298 a0: u16,
299 a1: u16,
300 a2: u16,
301 a3: u16,
302 a4: u16,
303 a5: u16,
304 a6: u16,
305 a7: u16,
306 ) -> Ipv6Address {
307 let ip_address: [u16; 8] = [a0, a1, a2, a3, a4, a5, a6, a7];
308 let mut ip_address_bytes = [0u8; 16];
309 {
310 let p = &mut ip_address_bytes[..];
311 for (idx, quartet) in ip_address.iter().enumerate() {
312 let idx = idx * 2;
313 BigEndian::write_u16(&mut p[idx..idx + 2], *quartet);
314 }
315 }
316 ipv6_addr_from_bytes(&ip_address_bytes).expect("should be valid")
317 }
318
319 #[derive(Copy, Clone, Eq, Hash, PartialEq)]
320 pub struct SocketAddrV6 {
321 pub addr: Ipv6Address,
322 pub port: u16,
323 }
324
325 #[allow(clippy::len_without_is_empty)]
326 #[allow(clippy::trivially_copy_pass_by_ref)]
327 impl SocketAddrV6 {
328 pub fn new(addr: Ipv6Address, port: u16) -> Self {
329 SocketAddrV6 { addr, port }
330 }
331
332 #[allow(clippy::too_many_arguments)]
333 pub fn new_ip6_port(
334 a0: u16,
335 a1: u16,
336 a2: u16,
337 a3: u16,
338 a4: u16,
339 a5: u16,
340 a6: u16,
341 a7: u16,
342 port: u16,
343 ) -> Self {
344 SocketAddrV6 {
345 addr: Ipv6Address::new(a0, a1, a2, a3, a4, a5, a6, a7),
346 port,
347 }
348 }
349
350 pub fn len(&self) -> usize {
351 LEN_V6
352 }
353
354 pub fn to_vec(&self) -> Vec<u8> {
355 let mut result = Vec::with_capacity(self.len());
356 result.extend_from_slice(&self.addr.0);
357 result.extend_from_slice(&port_to_bytes(self.port));
358 result
359 }
360 }
361
362 impl fmt::Display for SocketAddrV6 {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 write!(f, "[{}]:{}", self.addr, self.port)
365 }
366 }
367
368 impl fmt::Debug for SocketAddrV6 {
369 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
370 fmt::Display::fmt(self, fmt)
371 }
372 }
373}
374
375#[cfg(feature = "std")]
376mod std {
377 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
378 use ::std::net::{IpAddr, SocketAddr as StdSocketAddr};
379 #[cfg(feature = "proto-ipv4")]
380 use ::std::net::{Ipv4Addr, SocketAddrV4 as StdSocketAddrV4};
381 #[cfg(feature = "proto-ipv6")]
382 use ::std::net::{Ipv6Addr, SocketAddrV6 as StdSocketAddrV6};
383
384 #[cfg(feature = "proto-ipv4")]
385 use smoltcp::wire::Ipv4Address;
386 #[cfg(feature = "proto-ipv6")]
387 use smoltcp::wire::Ipv6Address;
388 #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
389 use smoltcp::wire::{IpAddress, IpEndpoint};
390
391 #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
392 use super::SocketAddr;
393 #[cfg(feature = "proto-ipv4")]
394 use super::SocketAddrV4;
395 #[cfg(feature = "proto-ipv6")]
396 use super::SocketAddrV6;
397 use super::{Error, Result};
398
399 #[cfg(feature = "proto-ipv4")]
400 pub trait IntoStdIpv4Addr: Sized {
401 fn into_std(self) -> Ipv4Addr;
402 }
403
404 #[cfg(feature = "proto-ipv4")]
405 impl IntoStdIpv4Addr for Ipv4Address {
406 fn into_std(self) -> Ipv4Addr {
407 self.0.into()
408 }
409 }
410
411 #[cfg(feature = "proto-ipv6")]
412 pub trait IntoStdIpv6Addr: Sized {
413 fn into_std(self) -> Ipv6Addr;
414 }
415
416 #[cfg(feature = "proto-ipv6")]
417 impl IntoStdIpv6Addr for Ipv6Address {
418 fn into_std(self) -> Ipv6Addr {
419 self.0.into()
420 }
421 }
422
423 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
424 pub trait IntoStdIpAddr: Sized {
425 fn into_std(self) -> Result<IpAddr>;
426 }
427
428 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
429 impl IntoStdIpAddr for IpAddress {
430 fn into_std(self) -> Result<IpAddr> {
431 match self {
432 IpAddress::Ipv4(ip) => Ok(ip.0.into()),
433 IpAddress::Ipv6(ip) => Ok(ip.0.into()),
434 IpAddress::Unspecified => Err(Error::UnspecifiedIp),
435 _ => unreachable!(),
436 }
437 }
438 }
439
440 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
441 pub trait IntoStdSocketAddr: Sized {
442 fn into_std(self) -> Result<StdSocketAddr>;
443 }
444
445 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
446 impl IntoStdSocketAddr for IpEndpoint {
447 fn into_std(self) -> Result<StdSocketAddr> {
448 let addr: IpAddr = self.addr.into_std()?;
449 Ok(StdSocketAddr::new(addr, self.port))
450 }
451 }
452
453 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
454 impl From<SocketAddr> for StdSocketAddr {
455 fn from(val: SocketAddr) -> Self {
456 match val {
457 SocketAddr::V4(val) => {
458 StdSocketAddr::V4(StdSocketAddrV4::new(val.addr.0.into(), val.port))
459 }
460 SocketAddr::V6(val) => {
461 StdSocketAddr::V6(StdSocketAddrV6::new(val.addr.0.into(), val.port, 0, 0))
462 }
463 }
464 }
465 }
466
467 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
468 impl From<&SocketAddr> for StdSocketAddr {
469 fn from(val: &SocketAddr) -> Self {
470 match val {
471 SocketAddr::V4(val) => {
472 StdSocketAddr::V4(StdSocketAddrV4::new(val.addr.0.into(), val.port))
473 }
474 SocketAddr::V6(val) => {
475 StdSocketAddr::V6(StdSocketAddrV6::new(val.addr.0.into(), val.port, 0, 0))
476 }
477 }
478 }
479 }
480
481 #[cfg(all(feature = "proto-ipv4", feature = "proto-ipv6"))]
482 impl From<StdSocketAddr> for SocketAddr {
483 fn from(val: StdSocketAddr) -> Self {
484 match val {
485 StdSocketAddr::V4(val) => SocketAddr::V4(SocketAddrV4 {
486 addr: Ipv4Address::from(*val.ip()),
487 port: val.port(),
488 }),
489 StdSocketAddr::V6(val) => SocketAddr::V6(SocketAddrV6 {
490 addr: Ipv6Address::from(*val.ip()),
491 port: val.port(),
492 }),
493 }
494 }
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use ::std::env;
501 #[cfg(all(feature = "std", feature = "proto-ipv4", feature = "proto-ipv6"))]
502 use ::std::net::IpAddr;
503 #[cfg(all(feature = "std", feature = "proto-ipv4"))]
504 use ::std::net::Ipv4Addr;
505 #[cfg(all(feature = "std", feature = "proto-ipv6"))]
506 use ::std::net::Ipv6Addr;
507 #[cfg(all(feature = "std", feature = "proto-ipv4", feature = "proto-ipv6"))]
508 use ::std::net::SocketAddr as StdSocketAddr;
509
510 use super::*;
511
512 #[cfg(feature = "proto-ipv4")]
513 #[test]
514 fn ipv4_socket_addr() {
515 if env::var("RUST_LOG").is_err() {
516 env::set_var("RUST_LOG", "debug");
517 }
518 let _ = pretty_env_logger::try_init_timed();
519
520 let ip_address_bytes = [127, 0, 0, 1];
521 let ip_address: Ipv4Address = ipv4_addr(127, 0, 0, 1);
522 info!("ip4 ip_address: {}", ip_address);
523 info!("ip4 ip_address debug: {:?}", ip_address);
524 assert_eq!(ip_address.as_bytes(), &ip_address_bytes);
525
526 let socket_addr = SocketAddrV4::new_ip4_port(127, 0, 0, 1, 8080);
527 info!("ip4 socket_addr: {}", socket_addr);
528 info!("ip4 socket_addr debug: {:?}", socket_addr);
529 assert_eq!(socket_addr.len(), LEN_V4);
530 assert_eq!(socket_addr.addr.as_bytes(), &ip_address_bytes);
531 assert_eq!(
532 socket_addr.addr.as_bytes(),
533 &socket_addr.to_vec().as_slice()[0..4]
534 );
535 assert_eq!(socket_addr.port, 8080);
536 }
537
538 #[cfg(feature = "proto-ipv6")]
539 #[test]
540 fn ipv6_socket_addr() {
541 if env::var("RUST_LOG").is_err() {
542 env::set_var("RUST_LOG", "debug");
543 }
544 let _ = pretty_env_logger::try_init_timed();
545
546 let ip_address_bytes: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
547 info!("ip6 ip_address_bytes: {:x?}", ip_address_bytes);
548
549 let ip_address: Ipv6Address = ipv6_addr(0, 0, 0, 0, 0, 0, 0, 1);
550 info!("ip6 ip_address: {}", ip_address);
551 info!("ip6 ip_address debug: {:?}", ip_address);
552 assert_eq!(ip_address.as_bytes(), &ip_address_bytes);
553
554 let socket_addr = SocketAddrV6::new_ip6_port(0, 0, 0, 0, 0, 0, 0, 1, 8080);
555 info!("ip6 socket_addr: {}", socket_addr);
556 info!("ip6 socket_addr debug: {:?}", socket_addr);
557 assert_eq!(socket_addr.len(), LEN_V6);
558 assert_eq!(socket_addr.addr.as_bytes(), &ip_address_bytes);
559 assert_eq!(
560 socket_addr.addr.as_bytes(),
561 &socket_addr.to_vec().as_slice()[0..16]
562 );
563 assert_eq!(socket_addr.port, 8080);
564 }
565
566 #[cfg(all(feature = "std", feature = "proto-ipv4", feature = "proto-ipv6"))]
567 #[test]
568 fn ipv4_to_std() {
569 if env::var("RUST_LOG").is_err() {
570 env::set_var("RUST_LOG", "debug");
571 }
572 let _ = pretty_env_logger::try_init_timed();
573
574 let ip_address_bytes = [127, 0, 0, 1];
575 let ip_address: Ipv4Address = ipv4_addr(127, 0, 0, 1);
576 let std_ip_address: Ipv4Addr = ip_address.into_std();
577 assert_eq!(std_ip_address.octets().as_ref(), ip_address_bytes);
578 let std_ip_address: Result<IpAddr> = IpAddress::Ipv4(ip_address).into_std();
579 assert_eq!(std_ip_address, Ok(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
580
581 let socket_addr_v4 = SocketAddrV4::new(ip_address, 80);
582 assert_eq!(socket_addr_v4.len(), LEN_V4);
583 let socket_addr = SocketAddr::V4(socket_addr_v4);
584 assert_eq!(
585 Ok(socket_addr),
586 SocketAddr::new(IpAddress::Ipv4(ip_address), 80)
587 );
588 assert_eq!(
589 Err(Error::UnspecifiedIp),
590 SocketAddr::new(IpAddress::Unspecified, 80)
591 );
592 assert_eq!(socket_addr, SocketAddr::new_v4(ip_address, 80));
593 assert_eq!(socket_addr, SocketAddr::new_ip4_port(127, 0, 0, 1, 80));
594 assert_eq!(socket_addr.len(), LEN_V4);
595 assert_eq!(socket_addr.ip().as_bytes(), ip_address_bytes);
596 assert_eq!(socket_addr.ip_octets(), ip_address_bytes);
597 let socket_addr_vec = socket_addr.to_vec();
598 assert_eq!(socket_addr_vec[0..4], ip_address_bytes);
599 assert_eq!(port_from_bytes(socket_addr_vec[4], socket_addr_vec[5]), 80);
600 info!("ip4 socket_addr: {}", socket_addr);
601 info!("ip4 socket_addr debug: {:?}", socket_addr);
602
603 let std_socket_addr: StdSocketAddr = socket_addr.into();
604 assert!(std_socket_addr.ip().is_loopback());
605 assert_eq!(std_socket_addr.ip().to_string(), "127.0.0.1".to_string());
606 assert_eq!(std_socket_addr.port(), socket_addr_v4.port);
607 assert_eq!(std_socket_addr.port(), socket_addr.port());
608 }
609
610 #[cfg(all(feature = "std", feature = "proto-ipv4", feature = "proto-ipv6"))]
611 #[test]
612 fn ipv6_to_std() {
613 if env::var("RUST_LOG").is_err() {
614 env::set_var("RUST_LOG", "debug");
615 }
616 let _ = pretty_env_logger::try_init_timed();
617
618 let ip_address_bytes: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
619 let ip_address: Ipv6Address = ipv6_addr(0, 0, 0, 0, 0, 0, 0, 1);
620 let std_ip_address: Ipv6Addr = ip_address.into_std();
621 assert_eq!(std_ip_address.octets().as_ref(), ip_address_bytes);
622 let std_ip_address: Result<IpAddr> = IpAddress::Ipv6(ip_address).into_std();
623 assert_eq!(
624 std_ip_address,
625 Ok(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))
626 );
627
628 let socket_addr_v6 = SocketAddrV6::new(ip_address, 80);
629 assert_eq!(socket_addr_v6.len(), LEN_V6);
630 let socket_addr = SocketAddr::V6(socket_addr_v6);
631 assert_eq!(
632 Ok(socket_addr),
633 SocketAddr::new(IpAddress::Ipv6(ip_address), 80)
634 );
635 assert_eq!(
636 Err(Error::UnspecifiedIp),
637 SocketAddr::new(IpAddress::Unspecified, 80)
638 );
639 assert_eq!(socket_addr, SocketAddr::new_v6(ip_address, 80));
640 assert_eq!(
641 socket_addr,
642 SocketAddr::new_ip6_port(0, 0, 0, 0, 0, 0, 0, 1, 80)
643 );
644 assert_eq!(socket_addr.len(), LEN_V6);
645 assert_eq!(socket_addr.ip().as_bytes(), ip_address_bytes);
646 assert_eq!(socket_addr.ip_octets(), ip_address_bytes);
647 let socket_addr_vec = socket_addr.to_vec();
648 assert_eq!(socket_addr_vec[0..16], ip_address_bytes);
649 assert_eq!(
650 port_from_bytes(socket_addr_vec[16], socket_addr_vec[17]),
651 80
652 );
653 info!("ip6 socket_addr: {}", socket_addr);
654 info!("ip6 socket_addr debug: {:?}", socket_addr);
655
656 let std_socket_addr: StdSocketAddr = socket_addr.into();
657 assert!(std_socket_addr.ip().is_loopback());
658 assert_eq!(std_socket_addr.ip().to_string(), "::1".to_string());
659 assert_eq!(std_socket_addr.port(), socket_addr_v6.port);
660 assert_eq!(std_socket_addr.port(), socket_addr.port());
661 }
662}