shadowsocks_service/local/loadbalancing/
server_data.rs1use std::{
4 fmt::{self, Debug},
5 net::SocketAddr,
6 sync::{
7 Arc,
8 atomic::{AtomicU32, Ordering},
9 },
10 time::Duration,
11};
12
13use shadowsocks::{ServerConfig, net::ConnectOpts};
14use tokio::sync::Mutex;
15
16use crate::{config::ServerInstanceConfig, local::context::ServiceContext};
17
18use super::server_stat::{Score, ServerStat, ServerStatData};
19
20pub struct ServerScore {
22 stat_data: Mutex<ServerStat>,
23 score: AtomicU32,
24}
25
26impl ServerScore {
27 pub fn new(user_weight: f32, max_server_rtt: Duration, check_window: Duration) -> Self {
29 let max_server_rtt = max_server_rtt.as_millis() as u32;
30 assert!(max_server_rtt > 0);
31
32 Self {
33 stat_data: Mutex::new(ServerStat::new(user_weight, max_server_rtt, check_window)),
34 score: AtomicU32::new(u32::MAX),
35 }
36 }
37
38 pub fn score(&self) -> u32 {
40 self.score.load(Ordering::Acquire)
41 }
42
43 pub async fn push_score(&self, score: Score) -> u32 {
45 let updated_score = {
46 let mut stat = self.stat_data.lock().await;
47 stat.push_score(score)
48 };
49 self.score.store(updated_score, Ordering::Release);
50 updated_score
51 }
52
53 pub async fn push_score_fetch_statistic(&self, score: Score) -> (u32, ServerStatData) {
55 let (updated_score, data) = {
56 let mut stat = self.stat_data.lock().await;
57 (stat.push_score(score), *stat.data())
58 };
59 self.score.store(updated_score, Ordering::Release);
60 (updated_score, data)
61 }
62
63 pub async fn report_failure(&self) -> u32 {
65 self.push_score(Score::Errored).await
66 }
67
68 pub async fn stat_data(&self) -> ServerStatData {
70 *self.stat_data.lock().await.data()
71 }
72}
73
74impl Debug for ServerScore {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 f.debug_struct("ServerScore").field("score", &self.score()).finish()
77 }
78}
79
80#[derive(Debug)]
82pub struct ServerIdent {
83 tcp_score: ServerScore,
84 udp_score: ServerScore,
85 svr_cfg: ServerInstanceConfig,
86 connect_opts: ConnectOpts,
87}
88
89impl ServerIdent {
90 pub fn new(
92 context: Arc<ServiceContext>,
93 svr_cfg: ServerInstanceConfig,
94 max_server_rtt: Duration,
95 check_window: Duration,
96 ) -> Self {
97 let mut connect_opts = context.connect_opts_ref().clone();
98
99 #[cfg(any(target_os = "linux", target_os = "android"))]
100 if let Some(fwmark) = svr_cfg.outbound_fwmark {
101 connect_opts.fwmark = Some(fwmark);
102 }
103
104 #[cfg(target_os = "freebsd")]
105 if let Some(user_cookie) = svr_cfg.outbound_user_cookie {
106 connect_opts.user_cookie = Some(user_cookie);
107 }
108
109 if let Some(bind_local_addr) = svr_cfg.outbound_bind_addr {
110 connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0));
111 }
112
113 if let Some(ref bind_interface) = svr_cfg.outbound_bind_interface {
114 connect_opts.bind_interface = Some(bind_interface.clone());
115 }
116
117 Self {
118 tcp_score: ServerScore::new(svr_cfg.config.weight().tcp_weight(), max_server_rtt, check_window),
119 udp_score: ServerScore::new(svr_cfg.config.weight().udp_weight(), max_server_rtt, check_window),
120 svr_cfg,
121 connect_opts,
122 }
123 }
124
125 pub fn connect_opts_ref(&self) -> &ConnectOpts {
126 &self.connect_opts
127 }
128
129 pub fn server_config(&self) -> &ServerConfig {
130 &self.svr_cfg.config
131 }
132
133 pub fn server_config_mut(&mut self) -> &mut ServerConfig {
134 &mut self.svr_cfg.config
135 }
136
137 pub fn server_instance_config(&self) -> &ServerInstanceConfig {
138 &self.svr_cfg
139 }
140
141 pub fn tcp_score(&self) -> &ServerScore {
142 &self.tcp_score
143 }
144
145 pub fn udp_score(&self) -> &ServerScore {
146 &self.udp_score
147 }
148}