1#![allow(dead_code)] #[macro_use]
3extern crate bitflags;
4extern crate winapi;
5extern crate serde;
6extern crate serde_yaml;
7extern crate encoding;
8extern crate libc;
9
10pub mod session;
11pub mod telemetry;
12pub mod track_surface;
13pub mod states;
14
15use crate::session::*;
16use serde_yaml::from_str as yaml_from;
17use std::ptr::null;
18use std::io::Error;
19use std::slice::from_raw_parts;
20use std::io::Result as IOResult;
21use std::mem::transmute;
22use std::sync::Mutex;
23use libc::c_void;
24use encoding::{Encoding, DecoderTrap};
25use encoding::all::ISO_8859_1;
26
27#[cfg(target_os="windows")]
28use crate::telemetry::Header;
29
30#[cfg(target_os="windows")]
31use std::os::windows::raw::HANDLE;
32#[cfg(target_os="windows")]
33use winapi::shared::minwindef::LPVOID;
34#[cfg(target_os="windows")]
35use winapi::um::errhandlingapi::GetLastError;
36#[cfg(target_os="windows")]
37use winapi::um::handleapi::CloseHandle;
38#[cfg(target_os="windows")]
39use winapi::um::memoryapi::{OpenFileMappingW, FILE_MAP_READ, MapViewOfFile};
40
41
42pub const TELEMETRY_PATH: &'static str = "Local\\IRSDKMemMapFileName";
43pub const UNLIMITED_LAPS: i32 = 32767;
44pub const UNLIMITED_TIME: f32 = 604800.0;
45
46
47#[cfg(target_os="windows")]
48pub struct Connection {
63 mux: Mutex<()>,
64 location: *mut c_void,
65 header: Header
66}
67
68#[cfg(target_os = "windows")]
69impl Connection {
70 pub fn new() -> IOResult<Connection> {
71 let mut path: Vec<u16> = TELEMETRY_PATH.encode_utf16().collect();
72 path.push(0);
73
74 let mapping: HANDLE;
75 let errno: i32;
76
77 unsafe { mapping = OpenFileMappingW(FILE_MAP_READ, 0, path.as_ptr()); };
78
79 if null() == mapping {
80
81 unsafe { errno = GetLastError() as i32; }
82
83 return Err(Error::from_raw_os_error(errno));
84 }
85
86 let view: LPVOID;
87
88 unsafe {
89 view = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
90 }
91
92 if null() == view {
93 unsafe { errno = GetLastError() as i32; }
94
95 return Err(Error::from_raw_os_error(errno))
96 }
97
98 let header = unsafe { Self::read_header(view) };
99
100 return Ok(Connection {mux: Mutex::default(), location: view, header: header});
101 }
102
103 pub unsafe fn read_header(from: *const c_void) -> Header {
120 let raw_header: *const Header = transmute(from);
121 let h: Header = *raw_header;
122
123 h.clone()
124 }
125
126 pub fn session_info(&mut self) -> Result<SessionDetails, Box<dyn std::error::Error>> {
143 let header = unsafe { Self::read_header(self.location) };
144
145 let start = (self.location as usize + header.session_info_offset as usize) as *const u8;
146 let size = header.session_info_length as usize;
147
148 let data: &[u8] = unsafe { from_raw_parts(start, size) };
149
150 let content: String = match ISO_8859_1.decode(data, DecoderTrap::Strict) {
152 Ok(value) => value,
153 Err(e) => return Err(Box::from(e))
154 };
155
156 match yaml_from(content.as_str()) {
157 Ok(session) => Ok(session),
158 Err(e) => Err(Box::from(e))
159 }
160 }
161
162 pub fn telemetry(&self) -> Result<telemetry::Sample, Box<dyn std::error::Error>> {
175 let header = unsafe { Self::read_header(self.location) };
176 header.telemetry(self.location as *const std::ffi::c_void)
177 }
178
179 pub fn blocking(&self) -> IOResult<telemetry::Blocking> {
195 telemetry::Blocking::new(self.location, unsafe { Self::read_header(self.location) })
196 }
197
198 pub fn close(&self) -> IOResult<()> {
199 let succ = unsafe { CloseHandle(self.location) };
200
201 if succ != 0 {
202 Ok(())
203 } else {
204 let errno: i32 = unsafe { GetLastError() as i32 };
205
206 Err(Error::from_raw_os_error(errno))
207 }
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214
215 #[test]
216 fn test_session_info() {
217 match Connection::new().expect("Unable to open telemetry").session_info() {
218 Ok(session) => println!("Track: {}", session.weekend.track_name),
219 Err(e) => println!("Error: {:?}", e)
220 };
221 }
222
223 #[test]
224 fn test_latest_telemetry() {
225 Connection::new().expect("Unable to open telemetry").telemetry().expect("Couldn't get latest telem");
226 }
227}
228