1use bytes::{BufMut, Bytes, BytesMut};
58use skrillax_codec::SilkroadFrame;
59use skrillax_security::handshake::CheckBytesInitialization;
60use skrillax_security::{Checksum, ChecksumBuilder, MessageCounter, SilkroadEncryption};
61use std::sync::Mutex;
62use thiserror::Error;
63
64#[cfg(feature = "derive")]
65pub use skrillax_packet_derive::Packet;
66#[cfg(feature = "serde")]
67use skrillax_serde::{ByteSize, Deserialize, SerializationError, Serialize};
68
69#[derive(Error, Debug)]
70pub enum PacketError {
71 #[cfg(feature = "serde")]
72 #[error("An error occurred while trying to (de)serialize the packet")]
73 SerializationError(#[from] SerializationError),
74 #[error(
75 "An encrypted packet was either attempted to be sent or received, but no security has \
76 been established yet"
77 )]
78 MissingSecurity,
79}
80
81pub trait Packet {
90 const ID: u16;
92 const NAME: &'static str;
95 const MASSIVE: bool;
98 const ENCRYPTED: bool;
100}
101
102#[derive(Eq, PartialEq, Debug)]
106pub struct IncomingPacket {
107 opcode: u16,
108 data: Bytes,
109}
110
111impl IncomingPacket {
112 pub fn new(opcode: u16, data: Bytes) -> Self {
114 Self { opcode, data }
115 }
116
117 pub fn consume(self) -> (u16, Bytes) {
119 (self.opcode, self.data)
120 }
121
122 pub fn opcode(&self) -> u16 {
123 self.opcode
124 }
125
126 pub fn data(&self) -> &[u8] {
127 &self.data
128 }
129}
130
131#[derive(Eq, PartialEq, Debug)]
138pub enum OutgoingPacket {
139 Encrypted { opcode: u16, data: Bytes },
141 Simple { opcode: u16, data: Bytes },
143 Massive { opcode: u16, packets: Vec<Bytes> },
146}
147
148pub trait AsPacket {
158 fn as_packet(&self) -> OutgoingPacket;
160}
161
162impl<T: AsPacket> From<T> for OutgoingPacket {
163 fn from(value: T) -> Self {
164 value.as_packet()
165 }
166}
167
168pub trait TryFromPacket {
176 fn try_deserialize(data: &[u8]) -> Result<(usize, Self), PacketError>
185 where
186 Self: Sized;
187}
188
189#[cfg(feature = "serde")]
190impl<T> TryFromPacket for T
191where
192 T: Packet + Deserialize + Send + Sized,
193{
194 fn try_deserialize(data: &[u8]) -> Result<(usize, Self), PacketError> {
195 use bytes::Buf;
196 let mut reader = data.reader();
197 let read = Self::read_from(&mut reader)?;
198 let consumed = data.len() - reader.into_inner().len();
199 Ok((consumed, read))
200 }
201}
202
203#[cfg(feature = "serde")]
204impl<T> AsPacket for [T]
205where
206 T: Packet + Serialize + ByteSize,
207{
208 fn as_packet(&self) -> OutgoingPacket {
209 use std::cmp::{max, min};
210 assert!(T::MASSIVE, "Can only transform massive packets");
211 let total_size = self.iter().map(|p| p.byte_size()).sum();
212 let mut buffer = BytesMut::with_capacity(total_size);
213 for p in self {
214 p.write_to(&mut buffer);
215 }
216
217 let mut data = buffer.freeze();
218 let required_packets = max(data.len() / 0x7FFF, 1);
219
220 let mut result = Vec::with_capacity(required_packets);
221 for _ in 0..required_packets {
222 result.push(data.split_to(min(0x7FFF, data.len())));
223 }
224
225 OutgoingPacket::Massive {
226 opcode: T::ID,
227 packets: result,
228 }
229 }
230}
231
232#[cfg(feature = "serde")]
233impl<T> AsPacket for T
234where
235 T: Packet + Serialize + ByteSize,
236{
237 fn as_packet(&self) -> OutgoingPacket {
238 use std::cmp::{max, min};
239
240 let mut buffer = BytesMut::with_capacity(self.byte_size());
241 self.write_to(&mut buffer);
242 if Self::MASSIVE {
243 let mut data = buffer.freeze();
244 let required_packets = max(data.len() / 0x7FFF, 1);
245
246 let mut result = Vec::with_capacity(required_packets);
247 for _ in 0..required_packets {
248 result.push(data.split_to(min(0x7FFF, data.len())));
249 }
250
251 OutgoingPacket::Massive {
252 opcode: Self::ID,
253 packets: result,
254 }
255 } else if Self::ENCRYPTED {
256 OutgoingPacket::Encrypted {
257 opcode: Self::ID,
258 data: buffer.freeze(),
259 }
260 } else {
261 OutgoingPacket::Simple {
262 opcode: Self::ID,
263 data: buffer.freeze(),
264 }
265 }
266 }
267}
268
269#[derive(Error, Debug)]
270pub enum FramingError {
271 #[error("Tried to create an encrypted frame but no encrypted was set up")]
272 MissingEncryption,
273}
274
275pub trait AsFrames {
278 fn as_frames(&self, context: SecurityContext) -> Result<Vec<SilkroadFrame>, FramingError>;
287}
288
289impl AsFrames for OutgoingPacket {
290 fn as_frames(&self, context: SecurityContext) -> Result<Vec<SilkroadFrame>, FramingError> {
291 let count = context
292 .checkers()
293 .map(|check| check.generate_count_byte())
294 .unwrap_or(0);
295
296 match self {
297 OutgoingPacket::Encrypted { opcode, data } => {
298 let Some(encryption) = context.encryption() else {
299 return Err(FramingError::MissingEncryption);
300 };
301 let content_length = data.len() + 4;
302 let length_with_padding = SilkroadEncryption::find_encrypted_length(content_length);
303 let mut new_buffer = BytesMut::with_capacity(length_with_padding);
304 new_buffer.put_u16_le(*opcode);
305 new_buffer.put_u8(count);
306 new_buffer.put_u8(0);
307 new_buffer.put_slice(data);
308
309 if let Some(mut checksum_builder) = context
310 .checkers()
311 .map(|checkers| checkers.checksum_builder())
312 {
313 checksum_builder.update(&(data.len() as u16 | 0x8000).to_le_bytes());
314 checksum_builder.update(&new_buffer);
315 new_buffer[3] = checksum_builder.digest();
316 }
317
318 for _ in 0..(length_with_padding - content_length) {
319 new_buffer.put_u8(0);
320 }
321
322 encryption
323 .encrypt_mut(&mut new_buffer)
324 .expect("Should be able to encrypt");
325 Ok(vec![SilkroadFrame::Encrypted {
326 content_size: data.len(),
327 encrypted_data: new_buffer.freeze(),
328 }])
329 },
330 OutgoingPacket::Simple { opcode, data } => {
331 let crc = if let Some(mut checksum_builder) = context
332 .checkers()
333 .map(|checkers| checkers.checksum_builder())
334 {
335 checksum_builder.update(&(data.len() as u16).to_le_bytes());
336 checksum_builder.update(&opcode.to_le_bytes());
337 checksum_builder.update_byte(count);
338 checksum_builder.update_byte(0);
339 checksum_builder.update(data);
340 checksum_builder.digest()
341 } else {
342 0
343 };
344
345 Ok(vec![SilkroadFrame::Packet {
346 count,
347 crc,
348 opcode: *opcode,
349 data: data.clone(),
350 }])
351 },
352 OutgoingPacket::Massive { opcode, packets } => {
353 let mut frames = Vec::with_capacity(1 + packets.len());
354
355 let crc = if let Some(mut checksum_builder) = context
356 .checkers()
357 .map(|checkers| checkers.checksum_builder())
358 {
359 checksum_builder.update(&5u16.to_le_bytes());
360 checksum_builder.update(&0x600Du16.to_le_bytes());
361 checksum_builder.update_byte(count);
362 checksum_builder.update_byte(0);
363 checksum_builder.update_byte(1);
364 checksum_builder.update(&opcode.to_le_bytes());
365 checksum_builder.update(&(packets.len() as u16).to_le_bytes());
366 checksum_builder.digest()
367 } else {
368 0
369 };
370
371 frames.push(SilkroadFrame::MassiveHeader {
372 count,
373 crc,
374 contained_opcode: *opcode,
375 contained_count: packets.len() as u16,
376 });
377
378 for packet in packets.iter() {
379 let count = context
380 .checkers()
381 .map(|check| check.generate_count_byte())
382 .unwrap_or(0);
383
384 let crc = if let Some(mut checksum_builder) = context
385 .checkers()
386 .map(|checkers| checkers.checksum_builder())
387 {
388 checksum_builder.update(&((packet.len() + 1) as u16).to_le_bytes());
389 checksum_builder.update(&0x600Du16.to_le_bytes());
390 checksum_builder.update_byte(count);
391 checksum_builder.update_byte(0);
392 checksum_builder.update_byte(0);
393 checksum_builder.update(packet);
394 checksum_builder.digest()
395 } else {
396 0
397 };
398
399 frames.push(SilkroadFrame::MassiveContainer {
400 count,
401 crc,
402 inner: packet.clone(),
403 });
404 }
405
406 Ok(frames)
407 },
408 }
409 }
410}
411
412#[derive(Error, Debug)]
413pub enum ReframingError {
414 #[error("We don't have enough packets to complete the re-framing")]
415 Incomplete(Option<usize>),
416 #[error("Cannot handle a massive container without a header")]
417 StrayMassiveContainer,
418 #[error("Found a mixture of massive and non-massive frames")]
419 MixedFrames,
420 #[error("Encountered an encrypted packet but was not provided a security setup")]
421 MissingSecurity,
422 #[error("The decryption of an encrypted packet did not yield a simple frame")]
423 InvalidEncryptedData,
424 #[error("The CRC byte was {received} by we expected to to be {expected}")]
425 CrcCheckFailed { expected: u8, received: u8 },
426 #[error("The count byte was {received} by we expected to to be {expected}")]
427 CounterCheckFailed { expected: u8, received: u8 },
428}
429
430pub trait FromFrames {
432 type Output;
433 fn from_frames(
445 frames: &[SilkroadFrame],
446 security: SecurityContext,
447 ) -> Result<Self::Output, ReframingError>;
448}
449
450struct MassiveInfo {
451 opcode: u16,
452 remaining: u16,
453}
454
455impl FromFrames for IncomingPacket {
456 type Output = IncomingPacket;
457
458 fn from_frames(
459 frames: &[SilkroadFrame],
460 security: SecurityContext,
461 ) -> Result<Self, ReframingError> {
462 let mut massive_information: Option<MassiveInfo> = None;
463 let mut massive_buffer: Option<BytesMut> = None;
464 for (i, frame) in frames.iter().enumerate() {
465 match frame {
466 SilkroadFrame::Packet { .. } | SilkroadFrame::Encrypted { .. }
467 if massive_information.is_some() =>
468 {
469 return Err(ReframingError::MixedFrames);
470 },
471 SilkroadFrame::Packet {
472 opcode,
473 data,
474 count,
475 crc,
476 } => {
477 if let Some(checkers) = security.checkers() {
478 let expected_count = checkers.generate_count_byte();
479 if *count != expected_count {
480 return Err(ReframingError::CounterCheckFailed {
481 expected: expected_count,
482 received: *count,
483 });
484 }
485
486 let mut checksum_builder = checkers.checksum_builder();
487 checksum_builder.update(&(data.len() as u16).to_le_bytes());
488 checksum_builder.update(&opcode.to_le_bytes());
489 checksum_builder.update_byte(*count);
490 checksum_builder.update_byte(0);
491 checksum_builder.update(data);
492 let expected_crc = checksum_builder.digest();
493 if *crc != expected_crc {
494 return Err(ReframingError::CrcCheckFailed {
495 expected: expected_crc,
496 received: *crc,
497 });
498 }
499 }
500
501 return Ok(IncomingPacket::new(*opcode, data.clone()));
502 },
503 SilkroadFrame::Encrypted {
504 encrypted_data,
505 content_size,
506 } => {
507 let Some(encryption) = security.encryption() else {
508 return Err(ReframingError::MissingSecurity);
509 };
510
511 let decrypted = encryption
512 .decrypt(encrypted_data)
513 .expect("Should be able to decrypt bytes");
514
515 let frame = SilkroadFrame::from_data(&decrypted[0..(*content_size + 4)]);
516 return match frame {
517 SilkroadFrame::Packet {
518 opcode,
519 data,
520 count,
521 crc,
522 } => {
523 if let Some(checkers) = security.checkers() {
524 let expected_count = checkers.generate_count_byte();
525 if count != expected_count {
526 return Err(ReframingError::CounterCheckFailed {
527 expected: expected_count,
528 received: count,
529 });
530 }
531
532 let mut checksum_builder = checkers.checksum_builder();
533 checksum_builder
534 .update(&(data.len() as u16 | 0x8000).to_le_bytes());
535 checksum_builder.update(&opcode.to_le_bytes());
536 checksum_builder.update_byte(count);
537 checksum_builder.update_byte(0);
538 checksum_builder.update(&data);
539 let expected_crc = checksum_builder.digest();
540 if crc != expected_crc {
541 return Err(ReframingError::CrcCheckFailed {
542 expected: expected_crc,
543 received: crc,
544 });
545 }
546 }
547 Ok(IncomingPacket::new(opcode, data))
548 },
549 _ => Err(ReframingError::InvalidEncryptedData),
550 };
551 },
552 SilkroadFrame::MassiveHeader {
553 contained_count,
554 contained_opcode,
555 count,
556 crc,
557 } => {
558 let required_frames = *contained_count as usize;
559 let remaining_frames = frames.len() - (i + 1);
560 if required_frames > remaining_frames {
561 return Err(ReframingError::Incomplete(Some(required_frames)));
562 }
563
564 if let Some(checkers) = security.checkers() {
565 let expected_count = checkers.generate_count_byte();
566 if *count != expected_count {
567 return Err(ReframingError::CounterCheckFailed {
568 expected: expected_count,
569 received: *count,
570 });
571 }
572
573 let mut checksum_builder = checkers.checksum_builder();
574 checksum_builder.update(&5u16.to_le_bytes());
575 checksum_builder.update(&0x600Du16.to_le_bytes());
576 checksum_builder.update_byte(*count);
577 checksum_builder.update_byte(0);
578 checksum_builder.update_byte(1);
579 checksum_builder.update(&contained_opcode.to_le_bytes());
580 checksum_builder.update(&contained_count.to_le_bytes());
581 let expected_crc = checksum_builder.digest();
582 if *crc != expected_crc {
583 return Err(ReframingError::CrcCheckFailed {
584 expected: expected_crc,
585 received: *crc,
586 });
587 }
588 }
589
590 massive_information = Some(MassiveInfo {
591 opcode: *contained_opcode,
592 remaining: *contained_count,
593 });
594 },
595 SilkroadFrame::MassiveContainer { inner, count, crc } => {
596 if let Some(mut massive) = massive_information.take() {
597 let mut current_buffer = massive_buffer.take().unwrap_or_default();
598 current_buffer.extend_from_slice(inner);
599
600 massive.remaining = massive.remaining.saturating_sub(1);
601
602 if let Some(checkers) = security.checkers() {
603 let expected_count = checkers.generate_count_byte();
604 if *count != expected_count {
605 return Err(ReframingError::CounterCheckFailed {
606 expected: expected_count,
607 received: *count,
608 });
609 }
610
611 let mut checksum_builder = checkers.checksum_builder();
612 checksum_builder.update(&(1u16 + inner.len() as u16).to_le_bytes());
613 checksum_builder.update(&0x600Du16.to_le_bytes());
614 checksum_builder.update_byte(*count);
615 checksum_builder.update_byte(0);
616 checksum_builder.update_byte(1);
617 checksum_builder.update(inner);
618 let expected_crc = checksum_builder.digest();
619 if *crc != expected_crc {
620 return Err(ReframingError::CrcCheckFailed {
621 expected: expected_crc,
622 received: *crc,
623 });
624 }
625 }
626
627 if massive.remaining == 0 {
628 return Ok(IncomingPacket::new(
629 massive.opcode,
630 current_buffer.freeze(),
631 ));
632 } else {
633 massive_buffer = Some(current_buffer);
634 massive_information = Some(massive);
635 }
636 } else {
637 return Err(ReframingError::StrayMassiveContainer);
638 }
639 },
640 }
641 }
642
643 Err(ReframingError::Incomplete(
644 massive_information.map(|massive| massive.remaining as usize),
645 ))
646 }
647}
648
649pub struct SecurityBytes {
651 counter: Mutex<MessageCounter>,
652 checksum: Checksum,
653}
654
655impl SecurityBytes {
656 pub fn from_seeds(crc_seed: u32, count_seed: u32) -> Self {
657 Self {
658 counter: Mutex::new(MessageCounter::new(count_seed)),
659 checksum: Checksum::new(crc_seed),
660 }
661 }
662
663 pub fn generate_count_byte(&self) -> u8 {
670 self.counter
671 .lock()
672 .expect("Should be able to lock the counter for increasing it")
673 .next_byte()
674 }
675
676 pub fn generate_checksum(&self, data: &[u8]) -> u8 {
677 self.checksum.generate_byte(data)
678 }
679
680 pub fn checksum_builder(&self) -> ChecksumBuilder {
681 self.checksum.builder()
682 }
683}
684
685impl From<CheckBytesInitialization> for SecurityBytes {
688 fn from(value: CheckBytesInitialization) -> Self {
689 SecurityBytes::from_seeds(value.crc_seed, value.count_seed)
690 }
691}
692
693#[derive(Default)]
703pub struct SecurityContext<'a> {
704 encryption: Option<&'a SilkroadEncryption>,
705 checkers: Option<&'a SecurityBytes>,
706}
707
708impl<'a> SecurityContext<'a> {
709 pub fn new(
710 encryption: Option<&'a SilkroadEncryption>,
711 security_bytes: Option<&'a SecurityBytes>,
712 ) -> Self {
713 Self {
714 encryption,
715 checkers: security_bytes,
716 }
717 }
718
719 pub fn encryption(&self) -> Option<&SilkroadEncryption> {
721 self.encryption
722 }
723
724 pub fn checkers(&self) -> Option<&SecurityBytes> {
726 self.checkers
727 }
728}