Created
February 8, 2023 00:03
-
-
Save incertia/bbd9157e4293dbe0241754273af1585b to your computer and use it in GitHub Desktop.
oodle network decompression in rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use ffi_opaque::opaque; | |
opaque! { | |
struct OodleNetwork1UDP_StateCompacted; | |
struct OodleNetwork1UDP_State; | |
struct OodleNetwork1_Shared; | |
} | |
#[link(name = "oo2netlinux64", kind = "static")] | |
extern "C" { | |
fn OodleNetwork1UDP_State_Size() -> libc::intptr_t; | |
fn OodleNetwork1UDP_State_Uncompact_ForVersion( | |
to: *mut OodleNetwork1UDP_State, | |
from: *const OodleNetwork1UDP_StateCompacted, | |
version: i32 | |
) -> bool; | |
fn OodleNetwork1_Shared_Size(htbits: i32) -> usize; | |
fn OodleNetwork1_Shared_SetWindow( | |
data: *mut OodleNetwork1_Shared, | |
htbits: i32, | |
window: *const libc::c_void, | |
window_size: i32 | |
) -> (); | |
fn OodleNetwork1UDP_Decode( | |
state: *const OodleNetwork1UDP_State, | |
shared: *const OodleNetwork1_Shared, | |
comp: *const libc::c_void, | |
comp_len: libc::intptr_t, | |
raw: *mut libc::c_void, | |
raw_len: libc::intptr_t | |
) -> bool; | |
} | |
pub struct Oodle { | |
_dict: Vec<u8>, | |
state: *mut OodleNetwork1UDP_State, | |
shared: *mut OodleNetwork1_Shared, | |
} | |
unsafe impl Send for Oodle {} | |
unsafe impl Sync for Oodle {} | |
impl Oodle { | |
pub fn new(state: &[u8]) -> Option<Self> { | |
// magic number check | |
let magic = u32::from_le_bytes(state[..4].try_into().ok()?); | |
if magic != 0x11235801 { | |
return None; | |
} | |
let htbits = i32::from_le_bytes(state[8..12].try_into().ok()?); | |
let dict_size = u32::from_le_bytes(state[12..16].try_into().ok()?) as usize; | |
let version = i32::from_le_bytes(state[16..20].try_into().ok()?); | |
let _dict_complen = u32::from_le_bytes(state[20..24].try_into().ok()?); | |
let statecompacted_size = i32::from_le_bytes(state[24..28].try_into().ok()?) as usize; | |
let _statecompacted_complen = i32::from_le_bytes(state[28..32].try_into().ok()?); | |
let mut dict = Vec::with_capacity(dict_size); | |
let mut on1udpnew_compacted = Vec::with_capacity(statecompacted_size); | |
unsafe { | |
dict.set_len(dict_size); | |
dict.as_mut_slice().copy_from_slice(&state[32..32 + dict_size]); | |
on1udpnew_compacted.set_len(statecompacted_size as usize); | |
on1udpnew_compacted.as_mut_slice().copy_from_slice(&state[32 + dict_size..32 + dict_size + statecompacted_size]); | |
}; | |
let state = unsafe { libc::malloc(OodleNetwork1UDP_State_Size() as usize) as *mut OodleNetwork1UDP_State }; | |
let uncompact_result = unsafe { | |
OodleNetwork1UDP_State_Uncompact_ForVersion( | |
state, | |
on1udpnew_compacted.as_ptr() as *const OodleNetwork1UDP_StateCompacted, | |
version | |
) | |
}; | |
if !uncompact_result { | |
return None; | |
} | |
let shared_size = unsafe { OodleNetwork1_Shared_Size(htbits) }; | |
let shared = unsafe { libc::malloc(shared_size) as *mut OodleNetwork1_Shared }; | |
unsafe { | |
OodleNetwork1_Shared_SetWindow(shared, htbits, dict.as_ptr() as *const libc::c_void, dict_size as i32); | |
} | |
Some(Self { | |
_dict: dict, | |
state, | |
shared, | |
}) | |
} | |
pub fn decode(&self, comp: &[u8]) -> Option<Vec<u8>> { | |
match comp { | |
[o1, o2, o3, o4, data @ ..] => { | |
let out_len = u32::from_le_bytes([*o1, *o2, *o3, *o4]); | |
let mut out = Vec::with_capacity(out_len as usize); | |
let result = unsafe { OodleNetwork1UDP_Decode( | |
self.state, | |
self.shared, | |
data.as_ptr() as *const libc::c_void, | |
data.len() as isize, | |
out.as_mut_ptr() as *mut libc::c_void, | |
out_len as isize | |
) }; | |
if result { | |
unsafe { | |
out.set_len(out_len as usize); | |
} | |
Some(out) | |
} else { | |
None | |
} | |
}, | |
_ => None, | |
} | |
} | |
} | |
impl Drop for Oodle { | |
fn drop(&mut self) { | |
unsafe { | |
libc::free(self.shared as *mut libc::c_void); | |
libc::free(self.state as *mut libc::c_void); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment