1b8a62b91Sopenharmony_ci//! Test a simple IPv4 socket server and client.
2b8a62b91Sopenharmony_ci//!
3b8a62b91Sopenharmony_ci//! The client send a message and the server sends one back.
4b8a62b91Sopenharmony_ci
5b8a62b91Sopenharmony_ci#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
6b8a62b91Sopenharmony_ci
7b8a62b91Sopenharmony_ciuse rustix::net::{
8b8a62b91Sopenharmony_ci    accept, bind_v4, connect_v4, getsockname, listen, recv, send, socket, AddressFamily, Ipv4Addr,
9b8a62b91Sopenharmony_ci    Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketType,
10b8a62b91Sopenharmony_ci};
11b8a62b91Sopenharmony_ciuse std::sync::{Arc, Condvar, Mutex};
12b8a62b91Sopenharmony_ciuse std::thread;
13b8a62b91Sopenharmony_ci
14b8a62b91Sopenharmony_ciconst BUFFER_SIZE: usize = 20;
15b8a62b91Sopenharmony_ci
16b8a62b91Sopenharmony_cifn server(ready: Arc<(Mutex<u16>, Condvar)>) {
17b8a62b91Sopenharmony_ci    let connection_socket =
18b8a62b91Sopenharmony_ci        socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
19b8a62b91Sopenharmony_ci
20b8a62b91Sopenharmony_ci    let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0);
21b8a62b91Sopenharmony_ci    bind_v4(&connection_socket, &name).unwrap();
22b8a62b91Sopenharmony_ci
23b8a62b91Sopenharmony_ci    let who = match getsockname(&connection_socket).unwrap() {
24b8a62b91Sopenharmony_ci        SocketAddrAny::V4(addr) => addr,
25b8a62b91Sopenharmony_ci        _ => panic!(),
26b8a62b91Sopenharmony_ci    };
27b8a62b91Sopenharmony_ci
28b8a62b91Sopenharmony_ci    listen(&connection_socket, 1).unwrap();
29b8a62b91Sopenharmony_ci
30b8a62b91Sopenharmony_ci    {
31b8a62b91Sopenharmony_ci        let (lock, cvar) = &*ready;
32b8a62b91Sopenharmony_ci        let mut port = lock.lock().unwrap();
33b8a62b91Sopenharmony_ci        *port = who.port();
34b8a62b91Sopenharmony_ci        cvar.notify_all();
35b8a62b91Sopenharmony_ci    }
36b8a62b91Sopenharmony_ci
37b8a62b91Sopenharmony_ci    let mut buffer = vec![0; BUFFER_SIZE];
38b8a62b91Sopenharmony_ci    let data_socket = accept(&connection_socket).unwrap();
39b8a62b91Sopenharmony_ci    let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
40b8a62b91Sopenharmony_ci    assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello, world");
41b8a62b91Sopenharmony_ci
42b8a62b91Sopenharmony_ci    send(&data_socket, b"goodnight, moon", SendFlags::empty()).unwrap();
43b8a62b91Sopenharmony_ci}
44b8a62b91Sopenharmony_ci
45b8a62b91Sopenharmony_cifn client(ready: Arc<(Mutex<u16>, Condvar)>) {
46b8a62b91Sopenharmony_ci    let port = {
47b8a62b91Sopenharmony_ci        let (lock, cvar) = &*ready;
48b8a62b91Sopenharmony_ci        let mut port = lock.lock().unwrap();
49b8a62b91Sopenharmony_ci        while *port == 0 {
50b8a62b91Sopenharmony_ci            port = cvar.wait(port).unwrap();
51b8a62b91Sopenharmony_ci        }
52b8a62b91Sopenharmony_ci        *port
53b8a62b91Sopenharmony_ci    };
54b8a62b91Sopenharmony_ci
55b8a62b91Sopenharmony_ci    let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port);
56b8a62b91Sopenharmony_ci    let mut buffer = vec![0; BUFFER_SIZE];
57b8a62b91Sopenharmony_ci
58b8a62b91Sopenharmony_ci    let data_socket = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
59b8a62b91Sopenharmony_ci    connect_v4(&data_socket, &addr).unwrap();
60b8a62b91Sopenharmony_ci
61b8a62b91Sopenharmony_ci    send(&data_socket, b"hello, world", SendFlags::empty()).unwrap();
62b8a62b91Sopenharmony_ci
63b8a62b91Sopenharmony_ci    let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
64b8a62b91Sopenharmony_ci    assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "goodnight, moon");
65b8a62b91Sopenharmony_ci}
66b8a62b91Sopenharmony_ci
67b8a62b91Sopenharmony_ci#[test]
68b8a62b91Sopenharmony_cifn test_v4() {
69b8a62b91Sopenharmony_ci    let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
70b8a62b91Sopenharmony_ci    let ready_clone = Arc::clone(&ready);
71b8a62b91Sopenharmony_ci
72b8a62b91Sopenharmony_ci    let server = thread::Builder::new()
73b8a62b91Sopenharmony_ci        .name("server".to_string())
74b8a62b91Sopenharmony_ci        .spawn(move || {
75b8a62b91Sopenharmony_ci            server(ready);
76b8a62b91Sopenharmony_ci        })
77b8a62b91Sopenharmony_ci        .unwrap();
78b8a62b91Sopenharmony_ci    let client = thread::Builder::new()
79b8a62b91Sopenharmony_ci        .name("client".to_string())
80b8a62b91Sopenharmony_ci        .spawn(move || {
81b8a62b91Sopenharmony_ci            client(ready_clone);
82b8a62b91Sopenharmony_ci        })
83b8a62b91Sopenharmony_ci        .unwrap();
84b8a62b91Sopenharmony_ci    client.join().unwrap();
85b8a62b91Sopenharmony_ci    server.join().unwrap();
86b8a62b91Sopenharmony_ci}
87