File: uds_socket.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (121 lines) | stat: -rw-r--r-- 3,309 bytes parent folder | download | duplicates (4)
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
111
112
113
114
115
116
117
118
119
120
121
#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]
#![cfg(unix)]

use futures::future::try_join;
use std::io;
use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    net::UnixSocket,
};

#[tokio::test]
#[cfg_attr(miri, ignore)] // No `socket` in miri.
async fn datagram_echo_server() -> io::Result<()> {
    let dir = tempfile::tempdir().unwrap();
    let server_path = dir.path().join("server.sock");
    let client_path = dir.path().join("client.sock");

    let server_socket = {
        let socket = UnixSocket::new_datagram()?;
        socket.bind(&server_path)?;
        socket.datagram()?
    };

    tokio::spawn(async move {
        let mut recv_buf = vec![0u8; 1024];
        loop {
            let (len, peer_addr) = server_socket.recv_from(&mut recv_buf[..]).await?;
            if let Some(path) = peer_addr.as_pathname() {
                server_socket.send_to(&recv_buf[..len], path).await?;
            }
        }

        #[allow(unreachable_code)]
        Ok::<(), io::Error>(())
    });

    {
        let socket = UnixSocket::new_datagram()?;
        socket.bind(&client_path).unwrap();
        let socket = socket.datagram()?;

        socket.connect(server_path)?;
        socket.send(b"ECHO").await?;

        let mut recv_buf = [0u8; 16];
        let len = socket.recv(&mut recv_buf[..]).await?;
        assert_eq!(&recv_buf[..len], b"ECHO");
    }

    Ok(())
}

#[tokio::test]
#[cfg_attr(miri, ignore)] // No `socket` in miri.
async fn listen_and_stream() -> std::io::Result<()> {
    let dir = tempfile::Builder::new().tempdir().unwrap();
    let sock_path = dir.path().join("connect.sock");
    let peer_path = dir.path().join("peer.sock");

    let listener = {
        let sock = UnixSocket::new_stream()?;
        sock.bind(&sock_path)?;
        sock.listen(1024)?
    };

    let accept = listener.accept();
    let connect = {
        let sock = UnixSocket::new_stream()?;
        sock.bind(&peer_path)?;
        sock.connect(&sock_path)
    };

    let ((mut server, _), mut client) = try_join(accept, connect).await?;

    assert_eq!(
        server.peer_addr().unwrap().as_pathname().unwrap(),
        &peer_path
    );

    // Write to the client.
    client.write_all(b"hello").await?;
    drop(client);

    // Read from the server.
    let mut buf = vec![];
    server.read_to_end(&mut buf).await?;
    assert_eq!(&buf, b"hello");
    let len = server.read(&mut buf).await?;
    assert_eq!(len, 0);
    Ok(())
}

#[tokio::test]
#[cfg_attr(miri, ignore)] // No `socket` in miri.
async fn assert_usage() -> std::io::Result<()> {
    let datagram_socket = UnixSocket::new_datagram()?;
    let result = datagram_socket
        .connect(std::path::PathBuf::new().join("invalid.sock"))
        .await;
    assert_eq!(
        result.unwrap_err().to_string(),
        "connect cannot be called on a datagram socket"
    );

    let datagram_socket = UnixSocket::new_datagram()?;
    let result = datagram_socket.listen(1024);
    assert_eq!(
        result.unwrap_err().to_string(),
        "listen cannot be called on a datagram socket"
    );

    let stream_socket = UnixSocket::new_stream()?;
    let result = stream_socket.datagram();
    assert_eq!(
        result.unwrap_err().to_string(),
        "datagram cannot be called on a stream socket"
    );

    Ok(())
}