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 self.read_loop();
127 trigger_listeners!(self.on_socket_disconnect, self);
128 }
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(), file != "", String::from(file), String::from(cookie), true, true ));
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}