1b8a62b91Sopenharmony_ci//! Test a simple Unix-domain socket server and client. 2b8a62b91Sopenharmony_ci//! 3b8a62b91Sopenharmony_ci//! The client sends lists of integers and the server sends back sums. 4b8a62b91Sopenharmony_ci 5b8a62b91Sopenharmony_ci// This test uses `AF_UNIX` with `SOCK_SEQPACKET` which is unsupported on macOS. 6b8a62b91Sopenharmony_ci#![cfg(not(any( 7b8a62b91Sopenharmony_ci target_os = "ios", 8b8a62b91Sopenharmony_ci target_os = "macos", 9b8a62b91Sopenharmony_ci target_os = "redox", 10b8a62b91Sopenharmony_ci target_os = "wasi", 11b8a62b91Sopenharmony_ci)))] 12b8a62b91Sopenharmony_ci// This test uses `DecInt`. 13b8a62b91Sopenharmony_ci#![cfg(feature = "itoa")] 14b8a62b91Sopenharmony_ci#![cfg(feature = "fs")] 15b8a62b91Sopenharmony_ci 16b8a62b91Sopenharmony_ciuse rustix::fs::{cwd, unlinkat, AtFlags}; 17b8a62b91Sopenharmony_ciuse rustix::io::{read, write}; 18b8a62b91Sopenharmony_ciuse rustix::net::{ 19b8a62b91Sopenharmony_ci accept, bind_unix, connect_unix, listen, socket, AddressFamily, Protocol, SocketAddrUnix, 20b8a62b91Sopenharmony_ci SocketType, 21b8a62b91Sopenharmony_ci}; 22b8a62b91Sopenharmony_ciuse rustix::path::DecInt; 23b8a62b91Sopenharmony_ciuse std::path::Path; 24b8a62b91Sopenharmony_ciuse std::str::FromStr; 25b8a62b91Sopenharmony_ciuse std::sync::{Arc, Condvar, Mutex}; 26b8a62b91Sopenharmony_ciuse std::thread; 27b8a62b91Sopenharmony_ci 28b8a62b91Sopenharmony_ciconst BUFFER_SIZE: usize = 20; 29b8a62b91Sopenharmony_ci 30b8a62b91Sopenharmony_cifn server(ready: Arc<(Mutex<bool>, Condvar)>, path: &Path) { 31b8a62b91Sopenharmony_ci let connection_socket = socket( 32b8a62b91Sopenharmony_ci AddressFamily::UNIX, 33b8a62b91Sopenharmony_ci SocketType::SEQPACKET, 34b8a62b91Sopenharmony_ci Protocol::default(), 35b8a62b91Sopenharmony_ci ) 36b8a62b91Sopenharmony_ci .unwrap(); 37b8a62b91Sopenharmony_ci 38b8a62b91Sopenharmony_ci let name = SocketAddrUnix::new(path).unwrap(); 39b8a62b91Sopenharmony_ci bind_unix(&connection_socket, &name).unwrap(); 40b8a62b91Sopenharmony_ci listen(&connection_socket, 1).unwrap(); 41b8a62b91Sopenharmony_ci 42b8a62b91Sopenharmony_ci { 43b8a62b91Sopenharmony_ci let (lock, cvar) = &*ready; 44b8a62b91Sopenharmony_ci let mut started = lock.lock().unwrap(); 45b8a62b91Sopenharmony_ci *started = true; 46b8a62b91Sopenharmony_ci cvar.notify_all(); 47b8a62b91Sopenharmony_ci } 48b8a62b91Sopenharmony_ci 49b8a62b91Sopenharmony_ci let mut buffer = vec![0; BUFFER_SIZE]; 50b8a62b91Sopenharmony_ci 'exit: loop { 51b8a62b91Sopenharmony_ci let data_socket = accept(&connection_socket).unwrap(); 52b8a62b91Sopenharmony_ci let mut sum = 0; 53b8a62b91Sopenharmony_ci loop { 54b8a62b91Sopenharmony_ci let nread = read(&data_socket, &mut buffer).unwrap(); 55b8a62b91Sopenharmony_ci 56b8a62b91Sopenharmony_ci if &buffer[..nread] == b"exit" { 57b8a62b91Sopenharmony_ci break 'exit; 58b8a62b91Sopenharmony_ci } 59b8a62b91Sopenharmony_ci if &buffer[..nread] == b"sum" { 60b8a62b91Sopenharmony_ci break; 61b8a62b91Sopenharmony_ci } 62b8a62b91Sopenharmony_ci 63b8a62b91Sopenharmony_ci sum += i32::from_str(&String::from_utf8_lossy(&buffer[..nread])).unwrap(); 64b8a62b91Sopenharmony_ci } 65b8a62b91Sopenharmony_ci 66b8a62b91Sopenharmony_ci write(&data_socket, DecInt::new(sum).as_bytes()).unwrap(); 67b8a62b91Sopenharmony_ci } 68b8a62b91Sopenharmony_ci 69b8a62b91Sopenharmony_ci unlinkat(cwd(), path, AtFlags::empty()).unwrap(); 70b8a62b91Sopenharmony_ci} 71b8a62b91Sopenharmony_ci 72b8a62b91Sopenharmony_cifn client(ready: Arc<(Mutex<bool>, Condvar)>, path: &Path, runs: &[(&[&str], i32)]) { 73b8a62b91Sopenharmony_ci { 74b8a62b91Sopenharmony_ci let (lock, cvar) = &*ready; 75b8a62b91Sopenharmony_ci let mut started = lock.lock().unwrap(); 76b8a62b91Sopenharmony_ci while !*started { 77b8a62b91Sopenharmony_ci started = cvar.wait(started).unwrap(); 78b8a62b91Sopenharmony_ci } 79b8a62b91Sopenharmony_ci } 80b8a62b91Sopenharmony_ci 81b8a62b91Sopenharmony_ci let addr = SocketAddrUnix::new(path).unwrap(); 82b8a62b91Sopenharmony_ci let mut buffer = vec![0; BUFFER_SIZE]; 83b8a62b91Sopenharmony_ci 84b8a62b91Sopenharmony_ci for (args, sum) in runs { 85b8a62b91Sopenharmony_ci let data_socket = socket( 86b8a62b91Sopenharmony_ci AddressFamily::UNIX, 87b8a62b91Sopenharmony_ci SocketType::SEQPACKET, 88b8a62b91Sopenharmony_ci Protocol::default(), 89b8a62b91Sopenharmony_ci ) 90b8a62b91Sopenharmony_ci .unwrap(); 91b8a62b91Sopenharmony_ci connect_unix(&data_socket, &addr).unwrap(); 92b8a62b91Sopenharmony_ci 93b8a62b91Sopenharmony_ci for arg in *args { 94b8a62b91Sopenharmony_ci write(&data_socket, arg.as_bytes()).unwrap(); 95b8a62b91Sopenharmony_ci } 96b8a62b91Sopenharmony_ci write(&data_socket, b"sum").unwrap(); 97b8a62b91Sopenharmony_ci 98b8a62b91Sopenharmony_ci let nread = read(&data_socket, &mut buffer).unwrap(); 99b8a62b91Sopenharmony_ci assert_eq!( 100b8a62b91Sopenharmony_ci i32::from_str(&String::from_utf8_lossy(&buffer[..nread])).unwrap(), 101b8a62b91Sopenharmony_ci *sum 102b8a62b91Sopenharmony_ci ); 103b8a62b91Sopenharmony_ci } 104b8a62b91Sopenharmony_ci 105b8a62b91Sopenharmony_ci let data_socket = socket( 106b8a62b91Sopenharmony_ci AddressFamily::UNIX, 107b8a62b91Sopenharmony_ci SocketType::SEQPACKET, 108b8a62b91Sopenharmony_ci Protocol::default(), 109b8a62b91Sopenharmony_ci ) 110b8a62b91Sopenharmony_ci .unwrap(); 111b8a62b91Sopenharmony_ci connect_unix(&data_socket, &addr).unwrap(); 112b8a62b91Sopenharmony_ci write(&data_socket, b"exit").unwrap(); 113b8a62b91Sopenharmony_ci} 114b8a62b91Sopenharmony_ci 115b8a62b91Sopenharmony_ci#[test] 116b8a62b91Sopenharmony_cifn test_unix() { 117b8a62b91Sopenharmony_ci let ready = Arc::new((Mutex::new(false), Condvar::new())); 118b8a62b91Sopenharmony_ci let ready_clone = Arc::clone(&ready); 119b8a62b91Sopenharmony_ci 120b8a62b91Sopenharmony_ci let tmp = tempfile::tempdir().unwrap(); 121b8a62b91Sopenharmony_ci let path = tmp.path().join("soccer"); 122b8a62b91Sopenharmony_ci let send_path = path.to_owned(); 123b8a62b91Sopenharmony_ci let server = thread::Builder::new() 124b8a62b91Sopenharmony_ci .name("server".to_string()) 125b8a62b91Sopenharmony_ci .spawn(move || { 126b8a62b91Sopenharmony_ci server(ready, &send_path); 127b8a62b91Sopenharmony_ci }) 128b8a62b91Sopenharmony_ci .unwrap(); 129b8a62b91Sopenharmony_ci let send_path = path.to_owned(); 130b8a62b91Sopenharmony_ci let client = thread::Builder::new() 131b8a62b91Sopenharmony_ci .name("client".to_string()) 132b8a62b91Sopenharmony_ci .spawn(move || { 133b8a62b91Sopenharmony_ci client( 134b8a62b91Sopenharmony_ci ready_clone, 135b8a62b91Sopenharmony_ci &send_path, 136b8a62b91Sopenharmony_ci &[ 137b8a62b91Sopenharmony_ci (&["1", "2"], 3), 138b8a62b91Sopenharmony_ci (&["4", "77", "103"], 184), 139b8a62b91Sopenharmony_ci (&["5", "78", "104"], 187), 140b8a62b91Sopenharmony_ci (&[], 0), 141b8a62b91Sopenharmony_ci ], 142b8a62b91Sopenharmony_ci ); 143b8a62b91Sopenharmony_ci }) 144b8a62b91Sopenharmony_ci .unwrap(); 145b8a62b91Sopenharmony_ci client.join().unwrap(); 146b8a62b91Sopenharmony_ci server.join().unwrap(); 147b8a62b91Sopenharmony_ci} 148