1 use test_programs::wasi::sockets::network::{ 2 ErrorCode, IpAddress, IpAddressFamily, IpSocketAddress, Network, 3 }; 4 use test_programs::wasi::sockets::udp::UdpSocket; 5 6 const SOME_PORT: u16 = 47; // If the tests pass, this will never actually be connected to. 7 8 fn test_udp_connect_disconnect_reconnect(net: &Network, family: IpAddressFamily) { 9 let unspecified_addr = IpSocketAddress::new(IpAddress::new_unspecified(family), 0); 10 let remote1 = IpSocketAddress::new(IpAddress::new_loopback(family), 4321); 11 let remote2 = IpSocketAddress::new(IpAddress::new_loopback(family), 4320); 12 13 let client = UdpSocket::new(family).unwrap(); 14 client.blocking_bind(&net, unspecified_addr).unwrap(); 15 16 _ = client.stream(None).unwrap(); 17 assert_eq!(client.remote_address(), Err(ErrorCode::InvalidState)); 18 19 _ = client.stream(None).unwrap(); 20 assert_eq!(client.remote_address(), Err(ErrorCode::InvalidState)); 21 22 _ = client.stream(Some(remote1)).unwrap(); 23 assert_eq!(client.remote_address(), Ok(remote1)); 24 25 _ = client.stream(Some(remote1)).unwrap(); 26 assert_eq!(client.remote_address(), Ok(remote1)); 27 28 _ = client.stream(Some(remote2)).unwrap(); 29 assert_eq!(client.remote_address(), Ok(remote2)); 30 31 _ = client.stream(None).unwrap(); 32 assert_eq!(client.remote_address(), Err(ErrorCode::InvalidState)); 33 34 _ = client.stream(Some(remote1)).unwrap(); 35 assert_eq!(client.remote_address(), Ok(remote1)); 36 } 37 38 /// `0.0.0.0` / `::` is not a valid remote address in WASI. 39 fn test_udp_connect_unspec(net: &Network, family: IpAddressFamily) { 40 let addr = IpSocketAddress::new(IpAddress::new_unspecified(family), SOME_PORT); 41 let sock = UdpSocket::new(family).unwrap(); 42 sock.blocking_bind_unspecified(&net).unwrap(); 43 44 assert!(matches!( 45 sock.stream(Some(addr)), 46 Err(ErrorCode::InvalidArgument) 47 )); 48 } 49 50 /// 0 is not a valid remote port. 51 fn test_udp_connect_port_0(net: &Network, family: IpAddressFamily) { 52 let addr = IpSocketAddress::new(IpAddress::new_loopback(family), 0); 53 let sock = UdpSocket::new(family).unwrap(); 54 sock.blocking_bind_unspecified(&net).unwrap(); 55 56 assert!(matches!( 57 sock.stream(Some(addr)), 58 Err(ErrorCode::InvalidArgument) 59 )); 60 } 61 62 /// Connect should validate the address family. 63 fn test_udp_connect_wrong_family(net: &Network, family: IpAddressFamily) { 64 let wrong_ip = match family { 65 IpAddressFamily::Ipv4 => IpAddress::IPV6_LOOPBACK, 66 IpAddressFamily::Ipv6 => IpAddress::IPV4_LOOPBACK, 67 }; 68 let remote_addr = IpSocketAddress::new(wrong_ip, SOME_PORT); 69 70 let sock = UdpSocket::new(family).unwrap(); 71 sock.blocking_bind_unspecified(&net).unwrap(); 72 73 assert!(matches!( 74 sock.stream(Some(remote_addr)), 75 Err(ErrorCode::InvalidArgument) 76 )); 77 } 78 79 fn test_udp_connect_dual_stack(net: &Network) { 80 // Set-up: 81 let v4_server = UdpSocket::new(IpAddressFamily::Ipv4).unwrap(); 82 v4_server 83 .blocking_bind(&net, IpSocketAddress::new(IpAddress::IPV4_LOOPBACK, 0)) 84 .unwrap(); 85 86 let v4_server_addr = v4_server.local_address().unwrap(); 87 let v6_server_addr = 88 IpSocketAddress::new(IpAddress::IPV4_MAPPED_LOOPBACK, v4_server_addr.port()); 89 90 // Tests: 91 let v6_client = UdpSocket::new(IpAddressFamily::Ipv6).unwrap(); 92 93 v6_client.blocking_bind_unspecified(&net).unwrap(); 94 95 // Connecting to an IPv4 address on an IPv6 socket should fail: 96 assert!(matches!( 97 v6_client.stream(Some(v4_server_addr)), 98 Err(ErrorCode::InvalidArgument) 99 )); 100 101 // Connecting to an IPv4-mapped-IPv6 address on an IPv6 socket should fail: 102 assert!(matches!( 103 v6_client.stream(Some(v6_server_addr)), 104 Err(ErrorCode::InvalidArgument) 105 )); 106 } 107 108 fn main() { 109 let net = Network::default(); 110 111 test_udp_connect_disconnect_reconnect(&net, IpAddressFamily::Ipv4); 112 test_udp_connect_disconnect_reconnect(&net, IpAddressFamily::Ipv6); 113 114 test_udp_connect_unspec(&net, IpAddressFamily::Ipv4); 115 test_udp_connect_unspec(&net, IpAddressFamily::Ipv6); 116 117 test_udp_connect_port_0(&net, IpAddressFamily::Ipv4); 118 test_udp_connect_port_0(&net, IpAddressFamily::Ipv6); 119 120 test_udp_connect_wrong_family(&net, IpAddressFamily::Ipv4); 121 test_udp_connect_wrong_family(&net, IpAddressFamily::Ipv6); 122 123 test_udp_connect_dual_stack(&net); 124 } 125