1 use core::ops::Range;
2 
3 use crate::p3::wasi::random;
4 use crate::p3::wasi::sockets::types::{
5     ErrorCode, IpAddress, IpAddressFamily, IpSocketAddress, Ipv4SocketAddress, Ipv6SocketAddress,
6     UdpSocket,
7 };
8 
9 impl IpAddress {
10     pub const IPV4_BROADCAST: IpAddress = IpAddress::Ipv4((255, 255, 255, 255));
11 
12     pub const IPV4_LOOPBACK: IpAddress = IpAddress::Ipv4((127, 0, 0, 1));
13     pub const IPV6_LOOPBACK: IpAddress = IpAddress::Ipv6((0, 0, 0, 0, 0, 0, 0, 1));
14 
15     pub const IPV4_UNSPECIFIED: IpAddress = IpAddress::Ipv4((0, 0, 0, 0));
16     pub const IPV6_UNSPECIFIED: IpAddress = IpAddress::Ipv6((0, 0, 0, 0, 0, 0, 0, 0));
17 
18     pub const IPV4_MAPPED_LOOPBACK: IpAddress =
19         IpAddress::Ipv6((0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 0x0001));
20 
new_loopback(family: IpAddressFamily) -> IpAddress21     pub const fn new_loopback(family: IpAddressFamily) -> IpAddress {
22         match family {
23             IpAddressFamily::Ipv4 => Self::IPV4_LOOPBACK,
24             IpAddressFamily::Ipv6 => Self::IPV6_LOOPBACK,
25         }
26     }
27 
new_unspecified(family: IpAddressFamily) -> IpAddress28     pub const fn new_unspecified(family: IpAddressFamily) -> IpAddress {
29         match family {
30             IpAddressFamily::Ipv4 => Self::IPV4_UNSPECIFIED,
31             IpAddressFamily::Ipv6 => Self::IPV6_UNSPECIFIED,
32         }
33     }
34 
family(&self) -> IpAddressFamily35     pub const fn family(&self) -> IpAddressFamily {
36         match self {
37             IpAddress::Ipv4(_) => IpAddressFamily::Ipv4,
38             IpAddress::Ipv6(_) => IpAddressFamily::Ipv6,
39         }
40     }
41 }
42 
43 impl PartialEq for IpAddress {
eq(&self, other: &Self) -> bool44     fn eq(&self, other: &Self) -> bool {
45         match (self, other) {
46             (Self::Ipv4(left), Self::Ipv4(right)) => left == right,
47             (Self::Ipv6(left), Self::Ipv6(right)) => left == right,
48             _ => false,
49         }
50     }
51 }
52 
53 impl IpSocketAddress {
new(ip: IpAddress, port: u16) -> IpSocketAddress54     pub const fn new(ip: IpAddress, port: u16) -> IpSocketAddress {
55         match ip {
56             IpAddress::Ipv4(addr) => IpSocketAddress::Ipv4(Ipv4SocketAddress {
57                 port,
58                 address: addr,
59             }),
60             IpAddress::Ipv6(addr) => IpSocketAddress::Ipv6(Ipv6SocketAddress {
61                 port,
62                 address: addr,
63                 flow_info: 0,
64                 scope_id: 0,
65             }),
66         }
67     }
68 
ip(&self) -> IpAddress69     pub const fn ip(&self) -> IpAddress {
70         match self {
71             IpSocketAddress::Ipv4(addr) => IpAddress::Ipv4(addr.address),
72             IpSocketAddress::Ipv6(addr) => IpAddress::Ipv6(addr.address),
73         }
74     }
75 
port(&self) -> u1676     pub const fn port(&self) -> u16 {
77         match self {
78             IpSocketAddress::Ipv4(addr) => addr.port,
79             IpSocketAddress::Ipv6(addr) => addr.port,
80         }
81     }
82 
family(&self) -> IpAddressFamily83     pub const fn family(&self) -> IpAddressFamily {
84         match self {
85             IpSocketAddress::Ipv4(_) => IpAddressFamily::Ipv4,
86             IpSocketAddress::Ipv6(_) => IpAddressFamily::Ipv6,
87         }
88     }
89 }
90 
91 impl PartialEq for Ipv4SocketAddress {
eq(&self, other: &Self) -> bool92     fn eq(&self, other: &Self) -> bool {
93         self.port == other.port && self.address == other.address
94     }
95 }
96 
97 impl PartialEq for Ipv6SocketAddress {
eq(&self, other: &Self) -> bool98     fn eq(&self, other: &Self) -> bool {
99         self.port == other.port
100             && self.flow_info == other.flow_info
101             && self.address == other.address
102             && self.scope_id == other.scope_id
103     }
104 }
105 
106 impl PartialEq for IpSocketAddress {
eq(&self, other: &Self) -> bool107     fn eq(&self, other: &Self) -> bool {
108         match (self, other) {
109             (Self::Ipv4(l0), Self::Ipv4(r0)) => l0 == r0,
110             (Self::Ipv6(l0), Self::Ipv6(r0)) => l0 == r0,
111             _ => false,
112         }
113     }
114 }
115 
generate_random_u16(range: Range<u16>) -> u16116 fn generate_random_u16(range: Range<u16>) -> u16 {
117     let start = range.start as u64;
118     let end = range.end as u64;
119     let port = start + (random::random::get_random_u64() % (end - start));
120     port as u16
121 }
122 
123 /// Execute the inner function with a randomly generated port.
124 /// To prevent random failures, we make a few attempts before giving up.
attempt_random_port<F>( local_address: IpAddress, mut f: F, ) -> Result<IpSocketAddress, ErrorCode> where F: FnMut(IpSocketAddress) -> Result<(), ErrorCode>,125 pub fn attempt_random_port<F>(
126     local_address: IpAddress,
127     mut f: F,
128 ) -> Result<IpSocketAddress, ErrorCode>
129 where
130     F: FnMut(IpSocketAddress) -> Result<(), ErrorCode>,
131 {
132     const MAX_ATTEMPTS: u32 = 10;
133     let mut i = 0;
134     loop {
135         i += 1;
136 
137         let port: u16 = generate_random_u16(1024..u16::MAX);
138         let sock_addr = IpSocketAddress::new(local_address, port);
139 
140         match f(sock_addr) {
141             Ok(_) => return Ok(sock_addr),
142             Err(e) if i >= MAX_ATTEMPTS => return Err(e),
143             // Try again if the port is already taken. This can sometimes show up as `AccessDenied` on Windows.
144             Err(ErrorCode::AddressInUse | ErrorCode::AccessDenied) => {}
145             Err(e) => return Err(e),
146         }
147     }
148 }
149 
150 impl UdpSocket {
bind_unspecified(&self) -> Result<(), ErrorCode>151     pub fn bind_unspecified(&self) -> Result<(), ErrorCode> {
152         let ip = IpAddress::new_unspecified(self.get_address_family());
153         let port = 0;
154 
155         self.bind(IpSocketAddress::new(ip, port))
156     }
157 }
158