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
use lazy_static::lazy_static;
use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags};
use std::{
    collections::HashSet,
    sync::atomic::{AtomicU16, Ordering},
};

mod block0;
mod jormungandr_config;
mod node;
mod secret;

pub use block0::Block0ConfigurationBuilder;
pub use jormungandr_config::EitherHashOrBlock0;
pub use node::{NodeConfigBuilder, NodeConfigManager};
pub use secret::{NodeSecretExtension, SecretModelFactory};

lazy_static! {
    static ref NEXT_AVAILABLE_PORT_NUMBER: AtomicU16 = AtomicU16::new(10000);
    static ref OCCUPIED_PORTS: HashSet<u16> = {
        let af_flags = AddressFamilyFlags::IPV4;
        let proto_flags = ProtocolFlags::TCP | ProtocolFlags::UDP;
        get_sockets_info(af_flags, proto_flags)
            .unwrap()
            .into_iter()
            .map(|s| s.local_port())
            .collect::<HashSet<_>>()
    };
}

pub fn get_available_port() -> u16 {
    loop {
        let candidate_port = NEXT_AVAILABLE_PORT_NUMBER.fetch_add(1, Ordering::SeqCst);
        if !(*OCCUPIED_PORTS).contains(&candidate_port) {
            return candidate_port;
        }
    }
}