1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#[cfg(target_os = "fuchsia")]
mod fuchsia;

#[cfg(target_os = "fuchsia")]
pub use fuchsia::*;

#[cfg(all(not(target_os = "fuchsia"), not(target_arch = "wasm32")))]
mod portable;

#[cfg(all(not(target_os = "fuchsia"), not(target_arch = "wasm32")))]
pub use portable::*;

#[cfg(not(target_arch = "wasm32"))]
#[cfg(test)]
mod udp_tests {
    use super::UdpSocket;
    use crate::TestExecutor;

    const MESSAGE: &[u8; 11] = b"hello world";

    fn send_recv_same_socket(addr: std::net::IpAddr) {
        let mut exec = TestExecutor::new();

        let addr = std::net::SocketAddr::new(addr, 0);
        let socket = UdpSocket::bind(&addr).expect("could not create socket");
        let addr = socket.local_addr().expect("could not get local address");
        let fut = async move {
            assert_eq!(socket.send_to(MESSAGE, addr).await.expect("send_to failed"), MESSAGE.len());
            let mut recvbuf = [0; MESSAGE.len()];
            assert_eq!(
                socket.recv_from(&mut recvbuf).await.expect("recv_from failed"),
                (MESSAGE.len(), addr)
            );
            assert_eq!(recvbuf, *MESSAGE);
        };

        exec.run_singlethreaded(fut);
    }

    #[test]
    fn send_recv_same_socket_ipv4() {
        send_recv_same_socket(std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST))
    }

    #[test]
    fn send_recv_same_socket_ipv6() {
        send_recv_same_socket(std::net::IpAddr::V6(std::net::Ipv6Addr::LOCALHOST))
    }

    fn send_recv(addr: std::net::IpAddr) {
        let mut exec = TestExecutor::new();

        let socket_addr = std::net::SocketAddr::new(addr.into(), 0);
        let client_socket = UdpSocket::bind(&socket_addr).expect("could not create client socket");
        let server_socket = UdpSocket::bind(&socket_addr).expect("could not create server socket");
        let client_addr =
            client_socket.local_addr().expect("could not get client socket's local address");
        let server_addr =
            server_socket.local_addr().expect("could not get server socket's local address");
        let fut = async move {
            assert_eq!(
                client_socket.send_to(MESSAGE, server_addr).await.expect("send_to failed"),
                MESSAGE.len()
            );
            let mut recvbuf = [0; MESSAGE.len()];
            assert_eq!(
                server_socket.recv_from(&mut recvbuf).await.expect("recv_from failed"),
                (MESSAGE.len(), client_addr)
            );
            assert_eq!(*MESSAGE, recvbuf);
        };

        exec.run_singlethreaded(fut);
    }

    #[test]
    fn send_recv_ipv4() {
        send_recv(std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST))
    }

    #[test]
    fn send_recv_ipv6() {
        send_recv(std::net::IpAddr::V6(std::net::Ipv6Addr::LOCALHOST))
    }

    #[test]
    fn broadcast() {
        let mut _exec = TestExecutor::new();

        let addr = "127.0.0.1:0".parse().expect("could not parse test address");
        let socket = UdpSocket::bind(&addr).expect("could not create socket");
        let initial = socket.broadcast().expect("could not get broadcast");
        assert!(!initial);
        socket.set_broadcast(true).expect("could not set broadcast");
        let set = socket.broadcast().expect("could not get broadcast");
        assert!(set);
    }

    #[test]
    fn test_local_addr() {
        let mut _exec = TestExecutor::new();
        let addr = "127.0.0.1:5432".parse().expect("could not parse test address");
        let socket = UdpSocket::bind(&addr).expect("could not create socket");
        assert_eq!(socket.local_addr().expect("could not get local address"), addr);
    }
}