rush_sync_server/server/utils/
port.rs1use crate::core::config::Config;
2use crate::core::prelude::*;
3
4pub enum PortStatus {
5 Available,
6 OccupiedByUs,
7 OccupiedByOther,
8}
9
10pub fn check_port_status(port: u16) -> PortStatus {
11 use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
12
13 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
14
15 if let Ok(listener) = TcpListener::bind(addr) {
17 drop(listener);
18 return PortStatus::Available;
19 }
20
21 let ctx = crate::server::shared::get_shared_context();
23 if let Ok(servers) = ctx.servers.read() {
24 if servers.values().any(|s| s.port == port) {
25 return PortStatus::OccupiedByUs;
26 }
27 }
28
29 PortStatus::OccupiedByOther
30}
31
32pub fn is_port_available(port: u16) -> bool {
33 std::net::TcpListener::bind(("127.0.0.1", port))
34 .map(|l| {
35 drop(l);
36 true
37 })
38 .unwrap_or(false)
39}
40
41pub fn find_next_available_port(config: &Config) -> Result<u16> {
42 let ctx = crate::server::shared::get_shared_context();
43 let servers = ctx.servers.read().unwrap();
44 let mut used_ports: Vec<u16> = servers.values().map(|s| s.port).collect();
45 used_ports.sort();
46
47 let mut candidate_port = config.server.port_range_start;
48 let max_port = config.server.port_range_end;
49
50 loop {
51 if candidate_port > max_port {
52 return Err(AppError::Validation(format!(
53 "No available ports in range {}-{}",
54 config.server.port_range_start, config.server.port_range_end
55 )));
56 }
57
58 if !used_ports.contains(&candidate_port) && is_port_available(candidate_port) {
59 return Ok(candidate_port);
60 }
61
62 candidate_port += 1;
63 }
64}
65
66pub fn find_next_available_port_legacy() -> Result<u16> {
67 let ctx = crate::server::shared::get_shared_context();
68 let servers = ctx.servers.read().unwrap();
69 let mut used_ports: Vec<u16> = servers.values().map(|s| s.port).collect();
70 used_ports.sort();
71
72 let mut candidate_port = 8080;
73
74 loop {
75 if !used_ports.contains(&candidate_port) && is_port_available(candidate_port) {
76 return Ok(candidate_port);
77 }
78
79 candidate_port += 1;
80 if candidate_port > 8180 {
81 return Err(AppError::Validation(
82 "No available ports found in default range 8080-8180".to_string(),
83 ));
84 }
85 }
86}