g_rust/extension/
extension.rs

1use std::collections::HashMap;
2use std::env;
3use std::fmt::{Debug, Error, Formatter};
4use super::parsers::baseparser::BaseParser;
5use crate::misc::connection::GEarthConnection;
6use crate::misc::connectioninfo::ConnectionInfo;
7use crate::misc::consoleformat::ConsoleColour;
8use crate::misc::hclient::CUR_CLIENT;
9use crate::misc::hostinfo::HostInfo;
10use crate::misc::messages::*;
11use crate::protocol::hdirection::HDirection;
12use crate::protocol::hmessage::HMessage;
13use crate::protocol::hpacket::HPacket;
14use crate::protocol::vars::packetvariable::PacketVariable;
15use crate::protocol::vars::longstring::LongString;
16use crate::services::packetinfo::packetinfomanager::PacketInfoManager;
17
18macro_rules! trigger_listeners {
19    ($listener:expr$(, $args:expr)*) => {
20        for listener in $listener.clone().iter() {
21            (listener)($($args),*)
22        }
23    }
24}
25
26const PORT_FLAG: [&str; 2] = ["--port", "-p"];
27const FILE_FLAG: [&str; 2] = ["--filename", "-f"];
28const COOKIE_FLAG: [&str; 2] = ["--auth-token", "-c"];
29
30#[derive(Debug, Clone)]
31pub struct ExtensionInfo {
32    pub name: String,
33    pub description: String,
34    pub author: String,
35    pub version: String
36}
37
38impl Default for ExtensionInfo {
39    fn default() -> Self {
40        Self {
41            name: env::var("CARGO_PKG_NAME").unwrap_or("undefined".to_string()),
42            description: env::var("CARGO_PKG_DESCRIPTION").unwrap_or("undefined".to_string()),
43            author: env::var("CARGO_PKG_AUTHORS").unwrap_or("undefined".to_string()),
44            version: env::var("CARGO_PKG_VERSION").unwrap_or("undefined".to_string())
45        }
46    }
47}
48
49pub struct Extension<W: Debug + Default> {
50    pub info: ExtensionInfo,
51    pub args: Vec<String>,
52    pub globals: W,
53    connection: Option<GEarthConnection>,
54    packet_info_manager: Option<PacketInfoManager>,
55
56    delayed_init: bool,
57    host_info: Option<HostInfo>,
58
59    on_init: Vec<fn(&mut Self)>,
60    on_connect: Vec<fn(&mut Self, ConnectionInfo)>,
61    on_start: Vec<fn(&mut Self)>,
62    on_end: Vec<fn(&mut Self)>,
63    on_click: Vec<fn(&mut Self)>,
64    on_host_info_update: Vec<fn(&mut Self, HostInfo)>,
65    on_socket_disconnect: Vec<fn(&mut Self)>,
66
67    intercepts_by_id: HashMap<HDirection, HashMap<i16, Vec<Box<dyn Fn(&mut Self, &mut HMessage) + Send + Sync>>>>,
68    intercepts_by_name: HashMap<HDirection, HashMap<String, Vec<Box<dyn Fn(&mut Self, &mut HMessage) + Send + Sync>>>>,
69
70    flag_callback: Option<fn(&mut Self, Vec<String>)>
71}
72
73impl <W: Debug + Default> Debug for Extension<W> {
74    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
75        f.debug_struct("Extension")
76            .field("info", &self.info)
77            .field("args", &self.args)
78            .field("globals", &self.globals)
79            .finish()
80    }
81}
82
83impl <W: Debug + Default + 'static> Extension<W> {
84    pub fn new() -> Self {
85        Extension {
86            info: ExtensionInfo::default(),
87            connection: None,
88            globals: W::default(),
89            args: env::args().collect(),
90            packet_info_manager: None,
91
92            delayed_init: false,
93            host_info: None,
94
95            on_init: Vec::new(),
96            on_connect: Vec::new(),
97            on_start: Vec::new(),
98            on_end: Vec::new(),
99            on_click: Vec::new(),
100            on_host_info_update: Vec::new(),
101            on_socket_disconnect: Vec::new(),
102
103            intercepts_by_id: HashMap::new(),
104            intercepts_by_name: HashMap::new(),
105
106            flag_callback: None
107        }
108    }
109
110    fn get_argument(&mut self, flags: [&str; 2]) -> String {
111        for i in 0..self.args.len() - 1 {
112            for flag in flags {
113                if self.args[i].to_lowercase() == flag.to_lowercase() {
114                    return self.args[i + 1].clone();
115                }
116            }
117        }
118
119        String::new()
120    }
121
122    pub fn run(&mut self) {
123        if self.connection.is_none() {
124            self.connection = Some(GEarthConnection::new(self.get_argument(PORT_FLAG)));
125            //let read_handle = thread::spawn(move || {
126            self.read_loop();
127            trigger_listeners!(self.on_socket_disconnect, self);
128            //});
129
130            //read_handle.join().unwrap();
131        }
132    }
133
134    pub fn get_packet_info_manager(&self) -> Option<PacketInfoManager> {
135        return self.packet_info_manager.clone()
136    }
137
138    pub fn get_host_info(&self) -> Option<HostInfo> {
139        return self.host_info.clone()
140    }
141
142    fn read_loop(&mut self) {
143        loop {
144            let length_bytes: Result<Vec<u8>, Error> = self.connection.clone().unwrap().read(4);
145            if length_bytes.is_err() {
146                break;
147            }
148            let length = i32::from_packet(length_bytes.clone().unwrap()).0;
149            let body_bytes: Result<Vec<u8>, Error> = self.connection.clone().unwrap().read(length as u64);
150            if body_bytes.is_err() {
151                break;
152            }
153            let mut bytes = length_bytes.unwrap();
154            bytes.append(&mut body_bytes.unwrap());
155            self.on_g_packet(HPacket::from_bytes(bytes));
156        }
157    }
158
159    fn on_g_packet(&mut self, mut packet: HPacket) {
160        match packet.header_id() {
161            IncomingMessageIds::INFO_REQUEST => self.on_info_request_packet(),
162            IncomingMessageIds::CONNECTION_START => self.on_connection_start_packet(packet),
163            IncomingMessageIds::CONNECTION_END => self.on_connection_end_packet(),
164            IncomingMessageIds::FLAGS_CHECK => self.on_flags_check_packet(packet),
165            IncomingMessageIds::INIT => self.on_init_packet(packet),
166            IncomingMessageIds::ON_DOUBLE_CLICK => self.on_double_click_packet(),
167            IncomingMessageIds::PACKET_INTERCEPT => self.on_packet_intercept_packet(packet),
168            IncomingMessageIds::UPDATE_HOST_INFO => self.on_update_host_info_packet(packet),
169            _ => println!("Unknown incoming message")
170        }
171    }
172
173    fn on_info_request_packet(&mut self) {
174        let file = self.get_argument(FILE_FLAG);
175        let cookie = self.get_argument(COOKIE_FLAG);
176        let mut response = HPacket::from_header_id(OutgoingMessageIds::EXTENSION_INFO);
177        response.append((
178            self.info.name.clone(),
179            self.info.author.clone(),
180            self.info.version.clone(),
181            self.info.description.clone(),
182            !self.on_click.is_empty(), // onclick
183            file != "", // file == null
184            String::from(file), // file
185            String::from(cookie), // cookie
186            true, // can leave
187            true // can delete
188        ));
189        self.connection.clone().unwrap().write(response.get_bytes());
190    }
191
192    fn on_connection_start_packet(&mut self, mut packet: HPacket) {
193        let connection_info: ConnectionInfo = packet.read();
194        self.packet_info_manager = packet.read();
195        *CUR_CLIENT.lock().unwrap() = connection_info.client.clone();
196
197        if self.delayed_init {
198            trigger_listeners!(self.on_init.clone(), self);
199            self.delayed_init = false;
200        }
201
202        trigger_listeners!(self.on_connect, self, connection_info.clone());
203        trigger_listeners!(self.on_start, self);
204    }
205
206    fn on_connection_end_packet(&mut self) {
207        self.packet_info_manager = None;
208        trigger_listeners!(self.on_end, self);
209    }
210
211    fn on_flags_check_packet(&mut self, mut packet: HPacket) {
212        if self.flag_callback.is_some() {
213            let count: i32 = packet.read();
214            let mut flags: Vec<String> = Vec::new();
215            for _ in 0..count {
216                flags.push(packet.read());
217            }
218            (self.flag_callback.unwrap())(self, flags);
219        }
220        self.flag_callback = None;
221    }
222
223    fn on_init_packet(&mut self, mut packet: HPacket) {
224        (self.delayed_init, self.host_info) = packet.read();
225        trigger_listeners!(self.on_host_info_update, self, self.host_info.clone().unwrap());
226        if !self.delayed_init {
227            trigger_listeners!(self.on_init, self);
228        }
229
230        self.connection.clone().unwrap().write_to_console_formatted(format!("Extension \"{}\" successfully initialized", self.info.name), ConsoleColour::Green);
231    }
232
233    fn on_double_click_packet(&mut self) {
234        trigger_listeners!(self.on_click, self);
235    }
236
237    fn on_packet_intercept_packet(&mut self, mut packet: HPacket) {
238        let string_message: LongString = packet.read();
239        let mut h_message = HMessage::from_string(string_message.clone());
240
241        self.modify_message(&mut h_message);
242
243        let mut response_packet = HPacket::from_header_id(OutgoingMessageIds::MANIPULATED_PACKET);
244        response_packet.append(LongString(h_message.stringify()));
245
246        self.connection.clone().unwrap().write(response_packet.get_bytes());
247    }
248
249    fn modify_message(&mut self, msg: &mut HMessage) {
250        let names_and_hashes: Vec<String> = if self.packet_info_manager.is_some() {
251            let packet_infos = self.packet_info_manager.clone().unwrap()
252                .get_all_packet_info_from_header_id(
253                    msg.get_destination(),
254                    msg.get_packet().header_id() as i32
255                );
256            packet_infos.iter()
257                .flat_map(| packet_info | vec![packet_info.name.clone(), packet_info.hash.clone()])
258                .filter(| n | n != "NULL")
259                .collect()
260        } else { Vec::new() };
261
262        let mut matching_listeners_by_id: Vec<Box<dyn Fn(&mut Self, &mut HMessage) + Send + Sync>> = Vec::new();
263        let header_id = msg.get_packet().header_id();
264        let intercepts_by_id = self.intercepts_by_id.get_mut(&msg.get_destination());
265        if intercepts_by_id.is_some() {
266            for (id, listeners) in intercepts_by_id.unwrap() {
267                if *id == msg.get_packet().header_id() {
268                    matching_listeners_by_id.append(listeners)
269                }
270            }
271        }
272
273        for listener in matching_listeners_by_id {
274            (listener)(self, msg);
275            self.intercept_raw(msg.get_destination(), header_id as i32, listener);
276        }
277
278        let mut matching_listeners_by_name: Vec<Box<dyn Fn(&mut Self, &mut HMessage) + Send + Sync>> = Vec::new();
279        let intercepts_by_name = self.intercepts_by_name.get_mut(&msg.get_destination());
280        let mut name = String::default();
281        if intercepts_by_name.is_some() {
282            for (name_or_hash, listeners) in intercepts_by_name.unwrap() {
283                if names_and_hashes.contains(name_or_hash) {
284                    name = name_or_hash.clone();
285                    matching_listeners_by_name.append(listeners)
286                }
287            }
288        }
289
290        for listener in matching_listeners_by_name {
291            (listener)(self, msg);
292            self.intercept_raw(msg.get_destination(), name.clone(), listener);
293        }
294    }
295
296    fn on_update_host_info_packet(&mut self, mut packet: HPacket) {
297        self.host_info = packet.read();
298        trigger_listeners!(self.on_host_info_update, self, self.host_info.clone().unwrap());
299    }
300
301    pub fn write_to_console(&self, s: String) {
302        self.connection.clone().expect("Extension not connected yet...").write_to_console(format!("[{}] {s}", self.info.name));
303    }
304
305    pub fn write_to_console_formatted(&self, s: String, colour: ConsoleColour) {
306        self.connection.clone().expect("Extension not connected yet...").write_to_console_formatted(format!("[{}] {s}", self.info.name), colour);
307    }
308
309    pub fn on_init(&mut self, listener: fn(ext: &mut Self)) {
310        self.on_init.push(listener);
311    }
312
313    pub fn on_socket_disconnect(&mut self, listener: fn(ext: &mut Self)) {
314        self.on_socket_disconnect.push(listener);
315    }
316
317    pub fn on_connect(&mut self, listener: fn(ext: &mut Self, connection_info: ConnectionInfo)) {
318        self.on_connect.push(listener);
319    }
320
321    pub fn on_start(&mut self, listener: fn(ext: &mut Self)) {
322        self.on_start.push(listener);
323    }
324
325    pub fn on_end(&mut self, listener: fn(ext: &mut Self)) {
326        self.on_end.push(listener);
327    }
328
329    pub fn on_host_info_update(&mut self, listener: fn(ext: &mut Self, host_info: HostInfo)) {
330        self.on_host_info_update.push(listener);
331    }
332
333    pub fn on_click(&mut self, listener: fn(ext: &mut Self)) {
334        self.on_click.push(listener);
335    }
336
337    pub fn request_flags(&mut self, callback: fn(ext: &mut Self, flags: Vec<String>)) {
338        self.flag_callback = Some(callback);
339        let request_packet = HPacket::from_header_id(OutgoingMessageIds::REQUEST_FLAGS);
340        self.connection.clone().unwrap().write(request_packet.get_bytes());
341    }
342
343    pub fn intercept<T: BaseParser + 'static>(&mut self, listener: fn(ext: &mut Self, msg: &mut HMessage, object: &mut T)) {
344        self.intercept_raw(T::get_direction(), T::get_packet_name(), Self::wrap_listener(listener));
345    }
346
347    pub fn intercept_by_id<T: BaseParser + 'static>(&mut self, id: i32, listener: fn(ext: &mut Self, msg: &mut HMessage, object: &mut T)) {
348        self.intercept_raw(T::get_direction(), id, Self::wrap_listener(listener));
349    }
350
351    fn wrap_listener<T: BaseParser + 'static>(listener: fn(ext: &mut Self, msg: &mut HMessage, object: &mut T)) -> impl Fn(&mut Self, &mut HMessage) + 'static {
352        move | ext: &mut Self, msg: &mut HMessage | {
353            let mut original_packet = msg.get_packet().clone();
354            let mut object: T = original_packet.read();
355            let original_object = object.clone();
356            (listener)(ext, msg, &mut object);
357
358            if original_object != object {
359                msg.get_packet().replace(6, object);
360            }
361        }
362    }
363
364    pub fn intercept_raw<I: InterceptIndicator>(&mut self, direction: HDirection, indicator: I, listener: impl Fn(&mut Self, &mut HMessage) + Send + Sync + 'static) {
365        let intercepts = if I::is_raw_habbo_header_id() {
366            self.intercepts_by_id
367                .entry(direction)
368                .or_insert_with(|| HashMap::new())
369                .entry(indicator.get_habbo_header_id(HDirection::None, &mut PacketInfoManager::default()).unwrap())
370                .or_insert_with( || Vec::new())
371        } else {
372            self.intercepts_by_name
373                .entry(direction)
374                .or_insert_with(|| HashMap::new())
375                .entry(indicator.get_habbo_header_name())
376                .or_insert_with( || Vec::new())
377        };
378
379        intercepts.push(Box::new(listener));
380    }
381
382    pub fn send_to_client(&self, packet: HPacket) -> bool {
383        self.send_internal(packet, HDirection::ToClient)
384    }
385
386    pub fn send_to_server(&self, packet: HPacket) -> bool {
387        self.send_internal(packet, HDirection::ToServer)
388    }
389
390    fn send_internal(&self, mut packet: HPacket, direction: HDirection) -> bool {
391        if packet.is_corrupted() || self.connection.clone().is_none() {
392            return false;
393        }
394
395        if !packet.is_complete()
396            && self.packet_info_manager.clone().is_some()
397            && packet.can_complete(self.packet_info_manager.clone().unwrap()) {
398            packet.complete_packet(self.packet_info_manager.clone().unwrap());
399        }
400        if !packet.is_complete() {
401            return false;
402        }
403
404        let mut sending_packet = HPacket::from_header_id(OutgoingMessageIds::SEND_MESSAGE);
405        sending_packet.append((direction as u8, packet.bytes_length() as i32));
406        sending_packet.append_bytes(packet.get_bytes());
407
408        self.connection.clone().unwrap().write(sending_packet.get_bytes());
409
410        return true;
411    }
412
413    pub fn send<B: BaseParser>(&self, packet_object: B) -> bool {
414        if self.packet_info_manager.is_none() {
415            println!(
416                "Couldn't send {} packet, packet info manager has not yet been initialized",
417                B::get_packet_name()
418            );
419            return false;
420        }
421
422        let packet_info = self.packet_info_manager.clone().unwrap()
423            .get_packet_info_from_name(B::get_direction(), B::get_packet_name());
424
425        if packet_info.is_none() {
426            println!(
427                "Couldn't send {}, packet info not found",
428                B::get_packet_name()
429            );
430            return false;
431        }
432
433        self.send_with_id(packet_object, packet_info.unwrap().header_id)
434    }
435
436    pub fn send_with_id<B: BaseParser>(&self, packet_object: B, header_id: i32) -> bool {
437        let mut packet = HPacket::from_header_id(header_id as i16);
438        packet_object.append_to_packet(&mut packet);
439        self.send_internal(packet, B::get_direction())
440    }
441}
442
443pub trait InterceptIndicator {
444    fn get_habbo_header_id(&self, direction: HDirection, packet_info_manager: &mut PacketInfoManager) -> Option<i16>;
445
446    fn matches_habbo_header_id(&self, direction: HDirection, packet_info_manager: &mut PacketInfoManager, header_id: i16) -> bool {
447        let id = self.get_habbo_header_id(direction, packet_info_manager);
448        id.is_some() && id.unwrap() == header_id
449    }
450
451    fn is_raw_habbo_header_id() -> bool {
452        false
453    }
454
455    fn get_habbo_header_name(&self) -> String {
456        String::new()
457    }
458}
459
460impl InterceptIndicator for String {
461    fn get_habbo_header_id(&self, direction: HDirection, packet_info_manager: &mut PacketInfoManager) -> Option<i16> {
462        let mut packet_info = packet_info_manager.get_packet_info_from_name(direction.clone(), self.clone());
463        if packet_info.is_some() {
464            return Some(packet_info.unwrap().header_id as i16);
465        }
466        packet_info = packet_info_manager.get_packet_info_from_hash(direction.clone(), self.clone());
467        if packet_info.is_some() {
468            return Some(packet_info.unwrap().header_id as i16);
469        }
470        None
471    }
472
473    fn get_habbo_header_name(&self) -> String {
474        self.clone()
475    }
476}
477
478impl InterceptIndicator for &str {
479    fn get_habbo_header_id(&self, direction: HDirection, packet_info_manager: &mut PacketInfoManager) -> Option<i16> {
480        self.to_string().get_habbo_header_id(direction, packet_info_manager)
481    }
482
483    fn get_habbo_header_name(&self) -> String {
484        self.to_string()
485    }
486}
487
488impl InterceptIndicator for i32 {
489    fn get_habbo_header_id(&self, _direction: HDirection, _packet_info_manager: &mut PacketInfoManager) -> Option<i16> {
490        Some(*self as i16)
491    }
492
493    fn is_raw_habbo_header_id() -> bool {
494        true
495    }
496}