1 //! The same as v6.rs, but with `poll` calls.
2
3 #![cfg(not(any(target_os = "redox", target_os = "wasi")))]
4
5 use rustix::io::{poll, PollFd, PollFlags};
6 use rustix::net::{
7 accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr,
8 Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV6, SocketType,
9 };
10 use std::sync::{Arc, Condvar, Mutex};
11 use std::thread;
12
13 const BUFFER_SIZE: usize = 20;
14
server(ready: Arc<(Mutex<u16>, Condvar)>)15 fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
16 let connection_socket = socket(
17 AddressFamily::INET6,
18 SocketType::STREAM,
19 Protocol::default(),
20 )
21 .unwrap();
22
23 let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0);
24 bind_v6(&connection_socket, &name).unwrap();
25
26 let who = match getsockname(&connection_socket).unwrap() {
27 SocketAddrAny::V6(addr) => addr,
28 _ => panic!(),
29 };
30
31 listen(&connection_socket, 1).unwrap();
32
33 {
34 let (lock, cvar) = &*ready;
35 let mut port = lock.lock().unwrap();
36 *port = who.port();
37 cvar.notify_all();
38 }
39
40 let mut buffer = vec![0; BUFFER_SIZE];
41 let data_socket = accept(&connection_socket).unwrap();
42
43 let mut fds = [PollFd::new(&data_socket, PollFlags::IN)];
44 assert_eq!(poll(&mut fds, -1).unwrap(), 1);
45 assert!(fds[0].revents().intersects(PollFlags::IN));
46 assert!(!fds[0].revents().intersects(PollFlags::OUT));
47
48 let expected_nread = rustix::io::ioctl_fionread(&data_socket).unwrap();
49 let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
50 assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello, world");
51 assert_eq!(expected_nread, nread as u64);
52
53 let mut fds = [PollFd::new(&data_socket, PollFlags::OUT)];
54 assert_eq!(poll(&mut fds, -1).unwrap(), 1);
55 assert!(!fds[0].revents().intersects(PollFlags::IN));
56 assert!(fds[0].revents().intersects(PollFlags::OUT));
57
58 send(&data_socket, b"goodnight, moon", SendFlags::empty()).unwrap();
59 }
60
client(ready: Arc<(Mutex<u16>, Condvar)>)61 fn client(ready: Arc<(Mutex<u16>, Condvar)>) {
62 let port = {
63 let (lock, cvar) = &*ready;
64 let mut port = lock.lock().unwrap();
65 while *port == 0 {
66 port = cvar.wait(port).unwrap();
67 }
68 *port
69 };
70
71 let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0);
72 let mut buffer = vec![0; BUFFER_SIZE];
73
74 let data_socket = socket(
75 AddressFamily::INET6,
76 SocketType::STREAM,
77 Protocol::default(),
78 )
79 .unwrap();
80 connect_v6(&data_socket, &addr).unwrap();
81
82 let mut fds = [PollFd::new(&data_socket, PollFlags::OUT)];
83 assert_eq!(poll(&mut fds, -1).unwrap(), 1);
84 assert!(!fds[0].revents().intersects(PollFlags::IN));
85 assert!(fds[0].revents().intersects(PollFlags::OUT));
86
87 send(&data_socket, b"hello, world", SendFlags::empty()).unwrap();
88
89 let mut fds = [PollFd::new(&data_socket, PollFlags::IN)];
90 assert_eq!(poll(&mut fds, -1).unwrap(), 1);
91 assert!(fds[0].revents().intersects(PollFlags::IN));
92 assert!(!fds[0].revents().intersects(PollFlags::OUT));
93
94 let expected_nread = rustix::io::ioctl_fionread(&data_socket).unwrap();
95 let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
96 assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "goodnight, moon");
97 assert_eq!(expected_nread, nread as u64);
98 }
99
100 #[test]
test_poll()101 fn test_poll() {
102 let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
103 let ready_clone = Arc::clone(&ready);
104
105 let server = thread::Builder::new()
106 .name("server".to_string())
107 .spawn(move || {
108 server(ready);
109 })
110 .unwrap();
111 let client = thread::Builder::new()
112 .name("client".to_string())
113 .spawn(move || {
114 client(ready_clone);
115 })
116 .unwrap();
117 client.join().unwrap();
118 server.join().unwrap();
119 }
120