Skip to main content

zombienet_orchestrator/generators/
port.rs

1use std::net::{SocketAddr, TcpListener};
2
3use configuration::shared::types::Port;
4use socket2::{Domain, Protocol, Socket, Type};
5use support::constants::THIS_IS_A_BUG;
6
7use super::errors::GeneratorError;
8use crate::shared::types::ParkedPort;
9
10// TODO: (team), we want to continue support ws_port? No
11enum PortTypes {
12    Rpc,
13    P2P,
14    Prometheus,
15}
16
17pub fn generate(port: Option<Port>) -> Result<ParkedPort, GeneratorError> {
18    let port = port.unwrap_or(0);
19    let addr: SocketAddr = format!("[::]:{port}")
20        .parse()
21        .expect("addr should be valid");
22    let socket = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))
23        .map_err(|_e| GeneratorError::PortGeneration(port, "Can't create the socket".into()))?;
24
25    // Explicitly disable v6only for dual-stack support
26    socket.set_only_v6(false).map_err(|_e| {
27        GeneratorError::PortGeneration(port, "Can't set v6 only to false in socket".into())
28    })?;
29    socket
30        .bind(&addr.into())
31        .map_err(|_e| GeneratorError::PortGeneration(port, "Can't bind in socket".into()))?;
32    socket
33        .listen(128)
34        .map_err(|_e| GeneratorError::PortGeneration(port, "Can't listen in socket".into()))?;
35
36    let listener: TcpListener = socket.into();
37    let port = listener
38        .local_addr()
39        .expect(&format!(
40            "We should always get the local_addr from the listener {THIS_IS_A_BUG}"
41        ))
42        .port();
43    Ok(ParkedPort::new(port, listener))
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    #[test]
50    fn generate_random() {
51        let port = generate(None).unwrap();
52        let listener = port.1.write().unwrap();
53
54        assert!(listener.is_some());
55    }
56
57    #[test]
58    fn generate_fixed_port() {
59        let port = generate(Some(33056)).unwrap();
60        let listener = port.1.write().unwrap();
61
62        assert!(listener.is_some());
63        assert_eq!(port.0, 33056);
64    }
65}