1use std::thread::JoinHandle;
2use std::sync::Arc;
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::io::Result;
5use std::net::UdpSocket;
6use std::net::SocketAddr;
7use std::sync::Mutex;
8use std::time::Duration;
9use rand::Rng;
10use crossbeam_queue::ArrayQueue;
11use crate::protocol::*;
12
13#[derive(Copy, Clone, Debug, Default)]
14struct Slot {
15 controller_info: ControllerInfo,
16 controller_data: ControllerData,
17 latest_packet_number: u32
18}
19
20#[derive(Copy, Clone, Debug)]
21pub enum ClientEvent {
22 ControllerInfoChanged(ControllerInfo),
23 ControllerDataChanged {
24 controller_info: ControllerInfo,
25 controller_data: ControllerData
26 }
27}
28
29const DEFAULT_PORT: u16 = 3333;
30const DEFAULT_SERVER_PORT: u16 = 26760;
31
32pub trait DsClient {
33 fn start(self, countinue_running: Arc<AtomicBool>) -> JoinHandle<()>;
35
36 fn controller_info(&self, slot_number: u8) -> ControllerInfo;
38
39 fn controller_data(&self, slot_number: u8) -> ControllerData;
41
42 fn next_event(&self) -> Option<ClientEvent>;
44}
45
46pub struct Client {
47 server_address: SocketAddr,
48 message_header: MessageHeader,
49 slots: Mutex<[Slot; 4]>,
50 socket: UdpSocket,
51 events: ArrayQueue<ClientEvent>
52}
53
54impl Client {
55 pub fn new(id: Option<u32>, address: Option<SocketAddr>, server_address: Option<SocketAddr>) -> Result<Client> {
63 let mut rng = rand::thread_rng();
64
65 let client_id = match id {
66 Some(id) => id,
67 None => rng.gen()
68 };
69
70 let message_header = {
71 MessageHeader {
72 source: MessageSource::Client,
73 protocol_version: PROTOCOL_VERSION,
74 message_length: 0,
75 checksum: 0,
76 source_id: client_id
77 }
78 };
79
80 let slots = {
81 let mut slots: [Slot; 4] = [Default::default(); 4];
82 let mut i = 0;
83 for slot in slots.iter_mut() {
84 slot.controller_info.slot = i;
85 i += 1;
86 }
87
88 Mutex::new(slots)
89 };
90
91 let client_address = match address {
92 Some(address) => address,
93 None => SocketAddr::from(([127, 0, 0, 1], DEFAULT_PORT))
94 };
95
96 let server_address = match server_address {
97 Some(address) => address,
98 None => SocketAddr::from(([127, 0, 0, 1], DEFAULT_SERVER_PORT))
99 };
100 let socket = UdpSocket::bind(client_address)?;
101 socket.set_read_timeout(Some(Duration::from_secs_f64(0.2)))?;
102 socket.set_write_timeout(Some(Duration::from_secs_f64(0.2)))?;
103
104 let events = ArrayQueue::new(50);
105
106 Ok(Client {
107 server_address,
108 message_header,
109 slots,
110 socket,
111 events
112 })
113 }
114
115 fn encode_and_send(&self, message: Message) -> Result<()> {
116 let mut encoded_message = vec![];
117 encode_message(&mut encoded_message, message).unwrap();
118
119 self.socket.send_to(&encoded_message, self.server_address).map(|_amount| ())
120 }
121
122 pub fn request_connected_controllers_info(&self, slot_numbers: &[u8]) -> Result<()> {
128 let slot_numbers = {
129 let mut slots = [0; 4];
130
131 let mut i = 0;
132 for &slot in slot_numbers {
133 slots[i] = slot;
134 i += 1;
135 }
136
137 slots
138 };
139
140 let payload = MessagePayload::ConnectedControllersRequest {
141 amount: slot_numbers.len() as i32,
142 slot_numbers
143 };
144
145 let message = Message {
146 header: self.message_header,
147 message_type: MessageType::ConnectedControllers,
148 payload
149 };
150
151 self.encode_and_send(message)
152 }
153
154 pub fn request_controller_data(&self, request: ControllerDataRequest) -> Result<()> {
157 let payload = MessagePayload::ControllerDataRequest(request);
158
159 let message = Message {
160 header: self.message_header,
161 message_type: MessageType::ControllerData,
162 payload
163 };
164
165 self.encode_and_send(message)
166 }
167
168 fn handle_response(&self, response: Message) -> Option<ClientEvent> {
169 match response.message_type {
170 MessageType::ProtocolVersion => None,
171 _ => {
172 match response.payload {
173 MessagePayload::ConnectedControllerResponse { controller_info } => {
174 let slot_number = controller_info.slot;
175
176 let mut slots = self.slots.lock().unwrap();
177 if slots[slot_number as usize].controller_info != controller_info {
178 slots[slot_number as usize].controller_info = controller_info;
179
180 let event = ClientEvent::ControllerInfoChanged(controller_info);
181
182 Some(event)
183 } else {
184 None
185 }
186 },
187 MessagePayload::ControllerData { packet_number,
188 controller_info,
189 controller_data } => {
190 let slot_number = controller_info.slot;
191
192 let mut slots = self.slots.lock().unwrap();
193
194 let slot = slots[slot_number as usize];
195 if packet_number > slot.latest_packet_number {
196 slots[slot_number as usize].latest_packet_number = packet_number;
197
198 if slot.controller_info != controller_info || slot.controller_data != controller_data {
199 slots[slot_number as usize].controller_info = controller_info;
200 slots[slot_number as usize].controller_data = controller_data;
201
202 let event = ClientEvent::ControllerDataChanged {
203 controller_info,
204 controller_data
205 };
206
207 Some(event)
208 } else {
209 None
210 }
211 } else {
212 None
213 }
214 }
215 _ => None }
217 }
218 }
219 }
220}
221
222impl DsClient for Arc<Client> {
223 fn start(self, countinue_running: Arc<AtomicBool>) -> JoinHandle<()> {
224 let countinue_running = countinue_running.clone();
225
226 std::thread::spawn(move || {
227 let mut buf = [0 as u8; 100];
228 while countinue_running.load(Ordering::SeqCst) {
229 match self.socket.recv_from(&mut buf) {
230 Ok((amount, source)) => {
231 if source == self.server_address {
232 let message = parse_message(MessageSource::Server, &buf[..amount], true);
233 if let Ok(message) = message {
234 let event = self.handle_response(message);
235 if let Some(event) = event {
236 let _ = self.events.push(event);
237 }
238 }
239 }
240 },
241 _ => ()
242 }
243 }
244 })
245 }
246
247 fn controller_info(&self, slot_number: u8) -> ControllerInfo {
248 assert!(slot_number < 4);
249
250 let slot = self.slots.lock().unwrap()[slot_number as usize];
251
252 slot.controller_info
253 }
254
255 fn controller_data(&self, slot_number: u8) -> ControllerData {
256 assert!(slot_number < 4);
257
258 let slot = self.slots.lock().unwrap()[slot_number as usize];
259
260 slot.controller_data
261 }
262
263 fn next_event(&self) -> Option<ClientEvent> {
264 self.events.pop()
265 }
266}