Skip to main content

why2_chat/
options.rs

1/*
2This is part of WHY2
3Copyright (C) 2022-2026 Václav Šmejkal
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19use std::sync::
20{
21    OnceLock,
22    atomic::{ AtomicBool, Ordering },
23};
24
25#[cfg(feature = "client")]
26use std::
27{
28    collections::HashSet,
29    sync::
30    {
31        Arc,
32        Mutex,
33        RwLock,
34        LazyLock,
35        atomic::AtomicUsize,
36    },
37};
38
39#[cfg(feature = "client")]
40use crate::consts::SharedKeys;
41
42//SETTINGS
43static SERVER_USERNAME: OnceLock<String> = OnceLock::new();
44
45#[cfg(feature = "server")]
46static VOICE_CHAT: AtomicBool = AtomicBool::new(false);
47
48#[cfg(feature = "client")]
49static KEYS: LazyLock<RwLock<Option<SharedKeys>>> = LazyLock::new(|| //SHARED SYMMETRIC KEY
50{
51    RwLock::new(None)
52});
53
54#[cfg(feature = "client")]
55static ASKING_PASSWORD: AtomicBool = AtomicBool::new(false); //CLIENT IS SENDING PASSWORD (DISABLE ECHO)
56
57#[cfg(feature = "client")]
58static EXTRA_SPACE: AtomicBool = AtomicBool::new(false); //CLIENT DISPLAYED SOME MENU (/help ETC.), ADD EXTRA SPACE ON NEXT MESSAGE
59
60#[cfg(feature = "client")]
61static SENDING_MESSAGES: AtomicBool = AtomicBool::new(false); //SENDING MESSAGES BOOL (CONDITION FOR ADDING MESSAGES TO HISTORY)
62
63#[cfg(feature = "client")]
64pub static INPUT_READ: LazyLock<Arc<Mutex<Vec<char>>>> = LazyLock::new(|| //INPUT READ FROM CLIENT
65{
66    Arc::new(Mutex::new(Vec::new()))
67});
68
69#[cfg(feature = "client")]
70static SEQ: AtomicUsize = AtomicUsize::new(0); //PACKET SEQUENCE NUMBER (CLIENT -> SERVER)
71
72#[cfg(feature = "client")]
73static SERVER_SEQ: AtomicUsize = AtomicUsize::new(0); //PACKET SEQUENCE NUMBER (SERVER -> CLIENT)
74
75#[cfg(feature = "client")]
76static SERVER_ADDRESS: OnceLock<String> = OnceLock::new();
77
78#[cfg(feature = "client")]
79static OBFUSCATION_KEY: OnceLock<[u8; 32]> = OnceLock::new();
80
81#[cfg(feature = "client")]
82static CHANNEL: LazyLock<RwLock<String>> = LazyLock::new(|| RwLock::new(String::new())); //ACTIVE CHANNEL
83
84#[cfg(feature = "client")]
85static MUTE: AtomicBool = AtomicBool::new(false); //MUTE LOCAL CLIENT
86#[cfg(feature = "client")]
87static MUTED: LazyLock<Mutex<HashSet<usize>>> = LazyLock::new(|| Mutex::new(HashSet::new())); //MUTED CLIENTS
88
89#[cfg(feature = "client")]
90static SOCKS5: AtomicBool = AtomicBool::new(false); //USE SOCKS5 (TOR)
91
92//FUNCTIONS
93//SERVER USERNAME
94pub fn get_server_username() -> String //GET SERVER USERNAME
95{
96    SERVER_USERNAME.get().unwrap().to_owned()
97}
98
99pub fn set_server_username(username: &str) //SET SERVER USERNAME
100{
101    SERVER_USERNAME.set(username.to_owned()).unwrap();
102}
103
104//VOICE CHAT
105#[cfg(feature = "server")]
106pub fn enable_voice_chat() //SET VOICE CHAT TO TRUE
107{
108    VOICE_CHAT.store(true, Ordering::Relaxed);
109}
110
111#[cfg(feature = "server")]
112pub fn voice_chat_enabled() -> bool //GET VOICE CHAT
113{
114    VOICE_CHAT.load(Ordering::Relaxed)
115}
116
117//SHARED KEYS
118#[cfg(feature = "client")]
119pub fn set_keys(keys: SharedKeys) //SET KEY
120{
121    let mut shared_key = KEYS.write().unwrap();
122    *shared_key = Some(keys);
123}
124
125#[cfg(feature = "client")]
126pub fn get_keys() -> Option<SharedKeys> //RETURN KEY
127{
128    let shared_key = KEYS.read().unwrap();
129    shared_key.clone()
130}
131
132//ASKING PASSWORD
133#[cfg(feature = "client")]
134pub fn set_asking_password(value: bool) //SET ASKING_PASSWORD
135{
136    ASKING_PASSWORD.store(value, Ordering::Relaxed);
137}
138
139#[cfg(feature = "client")]
140pub fn get_asking_password() -> bool //GET ASKING_PASSWORD
141{
142    ASKING_PASSWORD.load(Ordering::Relaxed)
143}
144
145//ADD EXTRA SPACE
146#[cfg(feature = "client")]
147pub fn set_extra_space(value: bool) //SET EXTRA_SPACE
148{
149    EXTRA_SPACE.store(value, Ordering::Relaxed);
150}
151
152#[cfg(feature = "client")]
153pub fn get_extra_space() -> bool //GET EXTRA_SPACE
154{
155    EXTRA_SPACE.load(Ordering::Relaxed)
156}
157
158//SENDING MESSAGES
159#[cfg(feature = "client")]
160pub fn get_sending_messages() -> bool //GET SENDING_MESSAGES
161{
162    SENDING_MESSAGES.load(Ordering::Relaxed)
163}
164
165#[cfg(feature = "client")]
166pub fn set_sending_messages(value: bool) //SET SENDING_MESSAGES
167{
168    SENDING_MESSAGES.store(value, Ordering::Relaxed);
169}
170
171#[cfg(feature = "client")]
172pub fn get_seq() -> usize //GET SEQUENCE NUMBER
173{
174    SEQ.load(Ordering::Relaxed)
175}
176
177#[cfg(feature = "client")]
178pub fn set_seq(value: usize) //SET SEQUENCE NUMBER
179{
180    SEQ.store(value, Ordering::Relaxed)
181}
182
183#[cfg(feature = "client")]
184pub fn get_server_seq() -> usize //GET SERVER SEQUENCE NUMBER
185{
186    SERVER_SEQ.load(Ordering::Relaxed)
187}
188
189#[cfg(feature = "client")]
190pub fn set_server_seq(value: usize) //SET SERVER SEQUENCE NUMBER
191{
192    SERVER_SEQ.store(value, Ordering::Relaxed)
193}
194
195//SERVER ADDRESS
196#[cfg(feature = "client")]
197pub fn get_server_address() -> String //GET SERVER ADDRESS
198{
199    SERVER_ADDRESS.get().unwrap().to_owned()
200}
201
202#[cfg(feature = "client")]
203pub fn set_server_address(address: &str) //SET SERVER ADDRESS
204{
205    SERVER_ADDRESS.set(address.to_owned()).unwrap();
206}
207
208//OBFUSCATION KEY
209#[cfg(feature = "client")]
210pub fn get_obfuscation_key() -> [u8; 32] //GET OBFUSCATION KEY
211{
212    *OBFUSCATION_KEY.get().unwrap()
213}
214
215#[cfg(feature = "client")]
216pub fn set_obfuscation_key(key: &[u8; 32]) //SET OBFUSCATION KEY
217{
218    OBFUSCATION_KEY.set(*key).unwrap();
219}
220
221//CHANNEL
222#[cfg(feature = "client")]
223pub fn get_channel() -> String //GET CHANNEL
224{
225    CHANNEL.read().unwrap().clone()
226}
227
228#[cfg(feature = "client")]
229pub fn set_channel(channel: String) //SET CHANNEL
230{
231    *CHANNEL.write().unwrap() = channel;
232}
233
234//MUTING
235#[cfg(feature = "client")]
236pub fn toggle_mute(id: Option<usize>) -> bool //ENABLE/DISABLE MUTE
237{
238    if let Some(id) = id //MUTE CLIENT
239    {
240        let mut muted = MUTED.lock().unwrap();
241
242        if muted.remove(&id)
243        {
244            false
245        } else
246        {
247            muted.insert(id);
248            true
249        }
250
251    } else //MUTE LOCAL CLIENT
252    {
253        !MUTE.fetch_xor(true, Ordering::Relaxed)
254    }
255}
256
257#[cfg(feature = "client")]
258pub fn is_muted(id: Option<usize>) -> bool //CHECK IF CLIENT IS MUTED
259{
260    if let Some(id) = id
261    {
262        MUTED.lock().unwrap().contains(&id)
263    } else
264    {
265        MUTE.load(Ordering::Relaxed)
266    }
267}
268
269//SOCKS5
270#[cfg(feature = "client")]
271pub fn enable_socks5() //SET SOCKS5 TO TRUE
272{
273    SOCKS5.store(true, Ordering::Relaxed);
274}
275
276#[cfg(feature = "client")]
277pub fn socks5_enabled() -> bool //GET SOCKS5
278{
279    SOCKS5.load(Ordering::Relaxed)
280}