1b8a62b91Sopenharmony_ci#![cfg(any(target_os = "android", target_os = "linux"))] 2b8a62b91Sopenharmony_ci 3b8a62b91Sopenharmony_ciuse rustix::fd::{AsFd, OwnedFd}; 4b8a62b91Sopenharmony_ciuse rustix::io::epoll::{self, Epoll}; 5b8a62b91Sopenharmony_ciuse rustix::io::{ioctl_fionbio, read, write}; 6b8a62b91Sopenharmony_ciuse rustix::net::{ 7b8a62b91Sopenharmony_ci accept, bind_v4, connect_v4, getsockname, listen, socket, AddressFamily, Ipv4Addr, Protocol, 8b8a62b91Sopenharmony_ci SocketAddrAny, SocketAddrV4, SocketType, 9b8a62b91Sopenharmony_ci}; 10b8a62b91Sopenharmony_ciuse std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 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 listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap(); 18b8a62b91Sopenharmony_ci bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap(); 19b8a62b91Sopenharmony_ci listen(&listen_sock, 1).unwrap(); 20b8a62b91Sopenharmony_ci 21b8a62b91Sopenharmony_ci let who = match getsockname(&listen_sock).unwrap() { 22b8a62b91Sopenharmony_ci SocketAddrAny::V4(addr) => addr, 23b8a62b91Sopenharmony_ci _ => panic!(), 24b8a62b91Sopenharmony_ci }; 25b8a62b91Sopenharmony_ci 26b8a62b91Sopenharmony_ci { 27b8a62b91Sopenharmony_ci let (lock, cvar) = &*ready; 28b8a62b91Sopenharmony_ci let mut port = lock.lock().unwrap(); 29b8a62b91Sopenharmony_ci *port = who.port(); 30b8a62b91Sopenharmony_ci cvar.notify_all(); 31b8a62b91Sopenharmony_ci } 32b8a62b91Sopenharmony_ci 33b8a62b91Sopenharmony_ci let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::<OwnedFd>::new()).unwrap(); 34b8a62b91Sopenharmony_ci 35b8a62b91Sopenharmony_ci // Test into conversions. 36b8a62b91Sopenharmony_ci let fd: OwnedFd = epoll.into(); 37b8a62b91Sopenharmony_ci let epoll: Epoll<epoll::Owning<OwnedFd>> = fd.into(); 38b8a62b91Sopenharmony_ci let fd: RawFd = epoll.into_raw_fd(); 39b8a62b91Sopenharmony_ci let epoll = unsafe { Epoll::<epoll::Owning<OwnedFd>>::from_raw_fd(fd) }; 40b8a62b91Sopenharmony_ci 41b8a62b91Sopenharmony_ci let raw_listen_sock = listen_sock.as_fd().as_raw_fd(); 42b8a62b91Sopenharmony_ci epoll.add(listen_sock, epoll::EventFlags::IN).unwrap(); 43b8a62b91Sopenharmony_ci 44b8a62b91Sopenharmony_ci let mut event_list = epoll::EventVec::with_capacity(4); 45b8a62b91Sopenharmony_ci loop { 46b8a62b91Sopenharmony_ci epoll.wait(&mut event_list, -1).unwrap(); 47b8a62b91Sopenharmony_ci for (_event_flags, target) in &event_list { 48b8a62b91Sopenharmony_ci if target.as_raw_fd() == raw_listen_sock { 49b8a62b91Sopenharmony_ci let conn_sock = accept(&*target).unwrap(); 50b8a62b91Sopenharmony_ci ioctl_fionbio(&conn_sock, true).unwrap(); 51b8a62b91Sopenharmony_ci epoll 52b8a62b91Sopenharmony_ci .add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET) 53b8a62b91Sopenharmony_ci .unwrap(); 54b8a62b91Sopenharmony_ci } else { 55b8a62b91Sopenharmony_ci write(&*target, b"hello\n").unwrap(); 56b8a62b91Sopenharmony_ci let _ = epoll.del(target).unwrap(); 57b8a62b91Sopenharmony_ci } 58b8a62b91Sopenharmony_ci } 59b8a62b91Sopenharmony_ci } 60b8a62b91Sopenharmony_ci} 61b8a62b91Sopenharmony_ci 62b8a62b91Sopenharmony_cifn client(ready: Arc<(Mutex<u16>, Condvar)>) { 63b8a62b91Sopenharmony_ci let port = { 64b8a62b91Sopenharmony_ci let (lock, cvar) = &*ready; 65b8a62b91Sopenharmony_ci let mut port = lock.lock().unwrap(); 66b8a62b91Sopenharmony_ci while *port == 0 { 67b8a62b91Sopenharmony_ci port = cvar.wait(port).unwrap(); 68b8a62b91Sopenharmony_ci } 69b8a62b91Sopenharmony_ci *port 70b8a62b91Sopenharmony_ci }; 71b8a62b91Sopenharmony_ci 72b8a62b91Sopenharmony_ci let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port); 73b8a62b91Sopenharmony_ci let mut buffer = vec![0; BUFFER_SIZE]; 74b8a62b91Sopenharmony_ci 75b8a62b91Sopenharmony_ci for _ in 0..16 { 76b8a62b91Sopenharmony_ci let data_socket = 77b8a62b91Sopenharmony_ci socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap(); 78b8a62b91Sopenharmony_ci connect_v4(&data_socket, &addr).unwrap(); 79b8a62b91Sopenharmony_ci 80b8a62b91Sopenharmony_ci let nread = read(&data_socket, &mut buffer).unwrap(); 81b8a62b91Sopenharmony_ci assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello\n"); 82b8a62b91Sopenharmony_ci } 83b8a62b91Sopenharmony_ci} 84b8a62b91Sopenharmony_ci 85b8a62b91Sopenharmony_ci#[test] 86b8a62b91Sopenharmony_cifn test_epoll() { 87b8a62b91Sopenharmony_ci let ready = Arc::new((Mutex::new(0_u16), Condvar::new())); 88b8a62b91Sopenharmony_ci let ready_clone = Arc::clone(&ready); 89b8a62b91Sopenharmony_ci 90b8a62b91Sopenharmony_ci let _server = thread::Builder::new() 91b8a62b91Sopenharmony_ci .name("server".to_string()) 92b8a62b91Sopenharmony_ci .spawn(move || { 93b8a62b91Sopenharmony_ci server(ready); 94b8a62b91Sopenharmony_ci }) 95b8a62b91Sopenharmony_ci .unwrap(); 96b8a62b91Sopenharmony_ci let client = thread::Builder::new() 97b8a62b91Sopenharmony_ci .name("client".to_string()) 98b8a62b91Sopenharmony_ci .spawn(move || { 99b8a62b91Sopenharmony_ci client(ready_clone); 100b8a62b91Sopenharmony_ci }) 101b8a62b91Sopenharmony_ci .unwrap(); 102b8a62b91Sopenharmony_ci client.join().unwrap(); 103b8a62b91Sopenharmony_ci} 104