1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
mod decode; mod error; mod layout; pub use decode::*; use error::*; pub use layout::*; use std::collections::HashMap; use std::convert::TryFrom; use std::io::Cursor; impl TryFrom<(&ReliableCommand, &mut Cursor<&[u8]>)> for Message { type Error = PhotonDecodeError; fn try_from(message: (&ReliableCommand, &mut Cursor<&[u8]>)) -> Result<Self, Self::Error> { let (command, cursor) = message; let _: u8 = cursor.decode()?; let msg_type: u8 = cursor.decode()?; match msg_type { 2 => { let v = cursor.decode().map_err(|e| e.extend("Request".into()))?; Ok(Message::Request(v)) } 3 => { let v = cursor.decode().map_err(|e| e.extend("Response".into()))?; Ok(Message::Response(v)) } 4 => { let v = cursor.decode().map_err(|e| e.extend("Event".into()))?; Ok(Message::Event(v)) } _ => { let msg_header_len = 2; cursor.set_position(cursor.position() + command.msg_len as u64 - msg_header_len); Err(PhotonDecodeError::from(format!( "Unknown message ({:#X})", msg_type ))) } } } } pub struct Photon { fragments: HashMap<u32, Vec<ReliableFragment>>, } impl Photon { pub fn new() -> Self { Self { fragments: HashMap::new(), } } pub fn try_decode( &mut self, payload: &[u8], ) -> PhotonDecodeResult<Vec<PhotonDecodeResult<Message>>> { let mut cursor = Cursor::new(payload); Ok( (0..Decode::<PhotonHeader>::decode(&mut cursor)?.command_count) .into_iter() .map(|_| { Decode::<Command>::decode(&mut cursor).map_or_else( |e| Some(Err(e)), |command| match command { Command::SendReliable(c) | Command::SendUnreliable(c) => Some( Message::try_from((&c, &mut cursor)) .map_err(|e| e.extend("SendReliable".into())), ), Command::SendReliableFragment(fragment) => { self.fragments .entry(fragment.sequence_number) .or_insert(vec![]) .push(fragment.clone()); self.decode_reliable_fragment(&fragment).map(|msg| { self.fragments.remove(&fragment.sequence_number).unwrap(); msg.map_err(|e| e.extend("Fragment".into())) }) } _ => None, }, ) }) .filter_map(|v| v) .collect(), ) } pub fn decode(&mut self, payload: &[u8]) -> Vec<Message> { if let Ok(messages) = self.try_decode(payload) { return messages.into_iter().filter_map(Result::ok).collect(); } vec![] } fn decode_reliable_fragment( &mut self, fragment: &ReliableFragment, ) -> Option<PhotonDecodeResult<Message>> { if let Some(fragments) = self.fragments.get(&fragment.sequence_number) { if fragments.len() == fragment.fragment_count as usize { let mut buf = Vec::<u8>::new(); for fragment in fragments { buf.extend(fragment.payload.iter()); } let mut c = Cursor::new(&buf[..]); return Some(Message::try_from((&fragment.reliable_command, &mut c))); } } None } }