Skip to content

Commit e241e10

Browse files
committed
rewrite server querying logic for efficiency
1 parent 3429d5e commit e241e10

File tree

6 files changed

+273
-127
lines changed

6 files changed

+273
-127
lines changed

src-tauri/src/main.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use gumdrop::Options;
1818
use injector::run_samp;
1919
use log::{error, info, LevelFilter};
2020
// use std::io::Read;
21-
use tauri::Manager;
22-
use tauri::PhysicalSize;
2321
use std::fs;
2422
use tauri::api::path::app_data_dir;
23+
use tauri::Manager;
24+
use tauri::PhysicalSize;
2525

2626
#[path = "deeplink/lib.rs"]
2727
#[cfg(target_os = "windows")]
@@ -106,9 +106,9 @@ Options:
106106

107107
if args.host.is_some() && args.name.is_some() && args.port.is_some() {
108108
if args.gamepath.is_some() && args.gamepath.as_ref().unwrap().len() > 0 {
109-
let password : String = if args.password.is_some() {
109+
let password: String = if args.password.is_some() {
110110
args.password.unwrap()
111-
} else {
111+
} else {
112112
"".to_string()
113113
};
114114
let _ = run_samp(
@@ -209,7 +209,8 @@ Options:
209209
commands::get_gtasa_path_from_samp,
210210
commands::get_nickname_from_samp,
211211
commands::get_samp_favorite_list,
212-
commands::rerun_as_admin
212+
commands::rerun_as_admin,
213+
query::query_server
213214
])
214215
.run(tauri::generate_context!())
215216
{

src-tauri/src/query.rs

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
use actix_web::web::Buf;
22
use byteorder::{LittleEndian, ReadBytesExt};
3+
use once_cell::sync::Lazy;
34
use regex::Regex;
45
use serde::{Deserialize, Serialize};
5-
use std::io::{Cursor, Read};
6+
use std::collections::HashMap;
7+
use std::io::{Cursor, Error, ErrorKind, Read};
8+
use std::sync::Mutex;
9+
use std::time::{SystemTime, UNIX_EPOCH};
610
use std::{net::Ipv4Addr, time::Duration};
711
use tokio::net::{lookup_host, UdpSocket};
812
use tokio::time::timeout_at;
913
use tokio::time::Instant;
1014

1115
use crate::helpers;
1216

17+
static OMP_EXTRA_INFO_LAST_UPDATE_LIST: Lazy<Mutex<HashMap<String, u64>>> =
18+
Lazy::new(|| Mutex::new(HashMap::new()));
19+
const OMP_EXTRA_INFO_UPDATE_COOLDOWN_SECS: u64 = 3;
20+
1321
pub struct Query {
1422
address: Ipv4Addr,
1523
port: i32,
@@ -40,6 +48,21 @@ pub struct ExtraInfoPacket {
4048
pub logo_url: String,
4149
}
4250

51+
#[derive(Serialize, Deserialize, Clone, Default)]
52+
pub struct ServerQueryResponse {
53+
pub info: Option<String>,
54+
pub extra_info: Option<String>,
55+
pub players: Option<String>,
56+
pub rules: Option<String>,
57+
pub ping: Option<u32>,
58+
}
59+
60+
#[derive(Serialize, Deserialize, Clone, Default)]
61+
pub struct ErrorResponse {
62+
pub info: String,
63+
pub error: bool,
64+
}
65+
4366
impl Query {
4467
pub async fn new(addr: &str, port: i32) -> Result<Self, std::io::Error> {
4568
let regex = Regex::new(r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$").unwrap();
@@ -119,7 +142,7 @@ impl Query {
119142
};
120143

121144
if amt == 0 {
122-
return Ok(String::from("no_data"));
145+
return Err(Error::new(ErrorKind::Other, String::from("no_data")));
123146
}
124147

125148
let query_type = buf[10] as char;
@@ -135,7 +158,7 @@ impl Query {
135158
} else if query_type == 'p' {
136159
Ok(String::from("pong"))
137160
} else {
138-
Ok(String::from("no_data"))
161+
Err(Error::new(ErrorKind::Other, String::from("no_data")))
139162
}
140163
}
141164

@@ -238,3 +261,118 @@ impl Query {
238261
Ok(serde_json::to_string(&rules).unwrap())
239262
}
240263
}
264+
265+
#[tauri::command]
266+
pub async fn query_server(
267+
ip: &str,
268+
port: i32,
269+
info: bool,
270+
extra_info: bool,
271+
players: bool,
272+
rules: bool,
273+
ping: bool,
274+
) -> Result<String, String> {
275+
match Query::new(ip, port).await {
276+
Ok(q) => {
277+
let mut result = ServerQueryResponse {
278+
info: None,
279+
extra_info: None,
280+
players: None,
281+
rules: None,
282+
ping: None,
283+
};
284+
285+
if info {
286+
let _ = q.send('i').await;
287+
result.info = Some(match q.recv().await {
288+
Ok(p) => format!("{}", p),
289+
Err(e) => {
290+
let mut error_details = ErrorResponse::default();
291+
error_details.error = true;
292+
error_details.info = e.to_string();
293+
serde_json::to_string(&error_details).unwrap()
294+
}
295+
});
296+
}
297+
298+
if players {
299+
let _ = q.send('c').await;
300+
result.players = Some(match q.recv().await {
301+
Ok(p) => format!("{}", p),
302+
Err(e) => {
303+
let mut error_details = ErrorResponse::default();
304+
error_details.error = true;
305+
error_details.info = e.to_string();
306+
serde_json::to_string(&error_details).unwrap()
307+
}
308+
});
309+
}
310+
311+
if rules {
312+
let _ = q.send('r').await;
313+
result.rules = Some(match q.recv().await {
314+
Ok(p) => format!("{}", p),
315+
Err(e) => {
316+
let mut error_details = ErrorResponse::default();
317+
error_details.error = true;
318+
error_details.info = e.to_string();
319+
serde_json::to_string(&error_details).unwrap()
320+
}
321+
});
322+
}
323+
324+
if extra_info {
325+
let now = SystemTime::now()
326+
.duration_since(UNIX_EPOCH)
327+
.unwrap()
328+
.as_secs();
329+
330+
let key = format!("{}:{}", ip, port);
331+
332+
let should_request = {
333+
let mut map = OMP_EXTRA_INFO_LAST_UPDATE_LIST.lock().unwrap();
334+
match map.get(&key) {
335+
Some(&last_time)
336+
if now - last_time < OMP_EXTRA_INFO_UPDATE_COOLDOWN_SECS =>
337+
{
338+
false
339+
}
340+
_ => {
341+
map.insert(key.clone(), now);
342+
true
343+
}
344+
}
345+
};
346+
347+
if should_request {
348+
let _ = q.send('o').await;
349+
result.extra_info = Some(match q.recv().await {
350+
Ok(p) => format!("{}", p),
351+
Err(e) => {
352+
let mut error_details = ErrorResponse::default();
353+
error_details.error = true;
354+
error_details.info = e.to_string();
355+
serde_json::to_string(&error_details).unwrap()
356+
}
357+
});
358+
}
359+
}
360+
361+
if ping {
362+
let _ = q.send('p').await;
363+
let before = Instant::now();
364+
match q.recv().await {
365+
Ok(_p) => {
366+
result.ping = Some(before.elapsed().as_millis() as u32);
367+
}
368+
Err(_) => {
369+
result.ping = Some(9999);
370+
}
371+
}
372+
}
373+
374+
Ok(serde_json::to_string(&result).unwrap())
375+
}
376+
Err(e) => Err(e.to_string()),
377+
}
378+
}

src/containers/LoadingScreen/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ const LoadingScreen = (props: { onEnd: () => void }) => {
221221
console.log("start", "validateResources");
222222
const dir = await path.appLocalDataDir();
223223
const samp = await path.join(dir, "samp");
224-
console.log("whaaaaqt?")
224+
225225
if (await fs.exists(samp)) {
226226
const archive = await path.join(samp, "samp_clients.7z");
227227
if (await fs.exists(archive)) {

src/hooks/query.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { queryServer } from "../utils/query";
44
import { ListType, Server } from "../utils/types";
55

66
const QUERY_INTERVAL_DELAY_MS = 1000;
7+
const QUERY_TIMES_TO_GET_INFO_THRESHOLD = 5;
78

89
export const useQuery = () => {
910
const queryTimer = useRef<ReturnType<typeof setInterval> | undefined>(
@@ -12,6 +13,7 @@ export const useQuery = () => {
1213

1314
const { selected, setSelected } = useServers();
1415
const selectedServer = useRef<Server | undefined>(selected);
16+
const queryTimesToGetInfo = useRef<number>(0);
1517

1618
useEffect(() => {
1719
selectedServer.current = selected;
@@ -31,6 +33,7 @@ export const useQuery = () => {
3133
clearInterval(queryTimer.current);
3234
queryTimer.current = undefined;
3335
} else {
36+
queryTimesToGetInfo.current = QUERY_TIMES_TO_GET_INFO_THRESHOLD;
3437
getServerInfo(srv, listType);
3538
queryTimer.current = setInterval(() => {
3639
getServerInfo(srv, listType);
@@ -39,7 +42,18 @@ export const useQuery = () => {
3942
};
4043

4144
const getServerInfo = (srv: Server, listType: ListType) => {
42-
queryServer(srv, listType);
45+
queryServer(
46+
srv,
47+
listType,
48+
"all",
49+
queryTimesToGetInfo.current != QUERY_TIMES_TO_GET_INFO_THRESHOLD
50+
);
51+
52+
if (queryTimesToGetInfo.current != QUERY_TIMES_TO_GET_INFO_THRESHOLD) {
53+
queryTimesToGetInfo.current++;
54+
} else {
55+
queryTimesToGetInfo.current = 0;
56+
}
4357
};
4458

4559
return {

src/utils/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ export const fetchServers = async (cached: boolean = true) => {
9191
offset < PARALLEL_SERVERS_TO_UPDATE_COUNT;
9292
offset++
9393
) {
94-
if (response.servers[i + offset])
94+
if (response.servers[i + offset]) {
9595
queryServer(response.servers[i + offset], "internet", "basic");
96+
}
9697
}
9798
}, 500 + (i / PARALLEL_SERVERS_TO_UPDATE_COUNT) * PARALLEL_SERVERS_TO_UPDATE_TIMER_INTERVAL);
9899
}

0 commit comments

Comments
 (0)