1 use { 2 super::{amf0_markers, errors::Amf0ReadErrorValue, Amf0ReadError, Amf0ValueType}, 3 byteorder::BigEndian, 4 bytes::BytesMut, 5 networkio::bytes_reader::BytesReader, 6 std::collections::HashMap, 7 }; 8 9 pub struct Amf0Reader { 10 reader: BytesReader, 11 } 12 13 impl Amf0Reader { 14 pub fn new(reader: BytesReader) -> Self { 15 Self { reader: reader } 16 } 17 pub fn read_all(&mut self) -> Result<Vec<Amf0ValueType>, Amf0ReadError> { 18 let mut results = vec![]; 19 20 loop { 21 let result = self.read_any()?; 22 23 match result { 24 Amf0ValueType::END => { 25 break; 26 } 27 _ => { 28 results.push(result); 29 } 30 } 31 } 32 33 Ok(results) 34 } 35 pub fn read_any(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 36 if self.reader.len() == 0 { 37 return Ok(Amf0ValueType::END); 38 } 39 let markers = self.reader.read_u8()?; 40 41 if markers == amf0_markers::OBJECT_END { 42 return Ok(Amf0ValueType::END); 43 } 44 45 match markers { 46 amf0_markers::NUMBER => self.read_number(), 47 amf0_markers::BOOLEAN => self.read_bool(), 48 amf0_markers::STRING => self.read_string(), 49 amf0_markers::OBJECT => self.read_object(), 50 amf0_markers::NULL => self.read_null(), 51 amf0_markers::ECMA_ARRAY => self.read_ecma_array(), 52 amf0_markers::LONG_STRING => self.read_long_string(), 53 _ => Err(Amf0ReadError { 54 value: Amf0ReadErrorValue::UnknownMarker { marker: markers }, 55 }), 56 } 57 } 58 pub fn read_with_type(&mut self, specified_marker: u8) -> Result<Amf0ValueType, Amf0ReadError> { 59 let marker = self.reader.advance_u8()?; 60 61 if marker != specified_marker { 62 return Err(Amf0ReadError { 63 value: Amf0ReadErrorValue::WrongType, 64 }); 65 } 66 67 return self.read_any(); 68 } 69 70 pub fn read_number(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 71 let number = self.reader.read_f64::<BigEndian>()?; 72 let value = Amf0ValueType::Number(number); 73 Ok(value) 74 } 75 76 pub fn read_bool(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 77 let value = self.reader.read_u8()?; 78 79 match value { 80 1 => Ok(Amf0ValueType::Boolean(true)), 81 _ => Ok(Amf0ValueType::Boolean(false)), 82 } 83 } 84 85 pub fn read_raw_string(&mut self) -> Result<String, Amf0ReadError> { 86 let l = self.reader.read_u16::<BigEndian>()?; 87 88 let bytes = self.reader.read_bytes(l as usize)?; 89 let val = String::from_utf8(bytes.to_vec())?; 90 91 Ok(val) 92 } 93 94 pub fn read_string(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 95 let raw_string = self.read_raw_string()?; 96 Ok(Amf0ValueType::UTF8String(raw_string)) 97 } 98 99 pub fn read_null(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 100 Ok(Amf0ValueType::Null) 101 } 102 103 pub fn is_read_object_eof(&mut self) -> Result<bool, Amf0ReadError> { 104 let marker = self.reader.advance_u24::<BigEndian>()?; 105 if marker == amf0_markers::OBJECT_END as u32 { 106 self.reader.read_u24::<BigEndian>()?; 107 return Ok(true); 108 } 109 Ok(false) 110 } 111 112 pub fn read_object(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 113 let mut properties = HashMap::new(); 114 115 loop { 116 let is_eof = self.is_read_object_eof()?; 117 118 if is_eof { 119 break; 120 } 121 122 let key = self.read_raw_string()?; 123 let val = self.read_any()?; 124 125 properties.insert(key, val); 126 } 127 128 Ok(Amf0ValueType::Object(properties)) 129 } 130 131 pub fn read_ecma_array(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 132 let len = self.reader.read_u32::<BigEndian>()?; 133 134 let mut properties = HashMap::new(); 135 136 for _ in 0..len { 137 let key = self.read_raw_string()?; 138 let val = self.read_any()?; 139 properties.insert(key, val); 140 } 141 142 self.is_read_object_eof()?; 143 144 Ok(Amf0ValueType::Object(properties)) 145 } 146 147 pub fn read_long_string(&mut self) -> Result<Amf0ValueType, Amf0ReadError> { 148 let l = self.reader.read_u32::<BigEndian>()?; 149 150 let buff = self.reader.read_bytes(l as usize)?; 151 152 let val = String::from_utf8(buff.to_vec())?; 153 Ok(Amf0ValueType::LongUTF8String(val)) 154 } 155 156 pub fn get_remaining_bytes(&mut self) -> BytesMut { 157 return self.reader.get_remaining_bytes(); 158 } 159 } 160 161 #[cfg(test)] 162 mod tests { 163 164 #[test] 165 fn test_byte_order() { 166 use byteorder::{BigEndian, ByteOrder}; 167 168 let phi = 1.6180339887; 169 let mut buf = [0; 8]; 170 BigEndian::write_f64(&mut buf, phi); 171 assert_eq!(phi, BigEndian::read_f64(&buf)); 172 println!("tsetstt") 173 } 174 175 use super::amf0_markers; 176 use super::Amf0Reader; 177 use super::Amf0ValueType; 178 use bytes::BytesMut; 179 use networkio::bytes_reader::BytesReader; 180 use std::collections::HashMap; 181 182 #[test] 183 fn test_amf_reader() { 184 let data: [u8; 177] = [ 185 2, 0, 7, 99, 111, 110, 110, 101, 99, 116, 0, 63, 240, 0, 0, 0, 0, 0, 0, //body 186 3, 0, 3, 97, 112, 112, 2, 0, 6, 104, 97, 114, 108, 97, 110, 0, 4, 116, 121, 112, 101, 187 2, 0, 10, 110, 111, 110, 112, 114, 105, 118, 97, 116, 101, 0, 8, 102, 108, 97, 115, 188 104, 86, 101, 114, 2, 0, 31, 70, 77, 76, 69, 47, 51, 46, 48, 32, 40, 99, 111, 109, 112, 189 97, 116, 105, 98, 108, 101, 59, 32, 70, 77, 83, 99, 47, 49, 46, 48, 41, 0, 6, 115, 119, 190 102, 85, 114, 108, 2, 0, 28, 114, 116, 109, 112, 58, 47, 47, 108, 111, 99, 97, 108, 191 104, 111, 115, 116, 58, 49, 57, 51, 53, 47, 104, 97, 114, 108, 97, 110, 0, 5, 116, 99, 192 85, 114, 108, 2, 0, 28, 114, 116, 109, 112, 58, 47, 47, 108, 111, 99, 97, 108, 104, 193 111, 115, 116, 58, 49, 57, 51, 53, 47, 104, 97, 114, 108, 97, 110, 0, 0, 9, 194 ]; 195 196 let mut bytes_reader = BytesReader::new(BytesMut::new()); 197 bytes_reader.extend_from_slice(&data); 198 let mut amf_reader = Amf0Reader::new(bytes_reader); 199 200 let command_name = amf_reader.read_with_type(amf0_markers::STRING).unwrap(); 201 assert_eq!( 202 command_name, 203 Amf0ValueType::UTF8String(String::from("connect")) 204 ); 205 206 let transaction_id = amf_reader.read_with_type(amf0_markers::NUMBER).unwrap(); 207 assert_eq!(transaction_id, Amf0ValueType::Number(1.0)); 208 209 let command_obj_raw = amf_reader.read_with_type(amf0_markers::OBJECT).unwrap(); 210 let mut properties = HashMap::new(); 211 properties.insert( 212 String::from("app"), 213 Amf0ValueType::UTF8String(String::from("harlan")), 214 ); 215 properties.insert( 216 String::from("type"), 217 Amf0ValueType::UTF8String(String::from("nonprivate")), 218 ); 219 properties.insert( 220 String::from("flashVer"), 221 Amf0ValueType::UTF8String(String::from("FMLE/3.0 (compatible; FMSc/1.0)")), 222 ); 223 properties.insert( 224 String::from("swfUrl"), 225 Amf0ValueType::UTF8String(String::from("rtmp://localhost:1935/harlan")), 226 ); 227 properties.insert( 228 String::from("tcUrl"), 229 Amf0ValueType::UTF8String(String::from("rtmp://localhost:1935/harlan")), 230 ); 231 assert_eq!(command_obj_raw, Amf0ValueType::Object(properties)); 232 233 let _ = amf_reader.read_all(); 234 235 print!("test") 236 } 237 238 #[test] 239 fn test_player_connect_reader() { 240 // chunk header 241 // 0000 03 00 00 00 00 00 aa 14 00 00 00 00 242 //amf0 data 243 // 02 00 07 63 ...............c 244 // 0010 6f 6e 6e 65 63 74 00 3f f0 00 00 00 00 00 00 03 onnect.?........ 245 // 0020 00 03 61 70 70 02 00 04 6c 69 76 65 00 05 74 63 ..app...live..tc 246 // 0030 55 72 6c 02 00 1a 72 74 6d 70 3a 2f 2f 6c 6f 63 Url...rtmp://loc 247 // 0040 61 6c 68 6f 73 74 3a 31 39 33 35 2f 6c 69 76 65 alhost:1935/live 248 // 0050 00 04 66 70 61 64 01 00 00 0c 63 61 70 61 62 69 ..fpad....capabi 249 // 0060 6c 69 74 69 65 73 00 40 2e 00 00 00 00 00 00 00 lities.@........ 250 // 0070 0b 61 75 64 69 6f 43 6f 64 65 63 73 00 40 a8 ee .audioCodecs.@.. 251 // 0080 00 00 00 00 00 00 0b 76 69 64 65 6f 43 6f 64 65 .......videoCode 118 105 252 // 0090 63 73 00 40 6f 80 00 00 00 00 00 00 0d 76 69 64 [email protected] 253 // 00a0 65 6f 46 75 6e 63 74 69 6f 6e 00 3f f0 00 00 00 eoFunction.?.... 254 // 0b00 00 00 00 00 00 09 ...... 255 256 let data: [u8; 171] = [ 257 2, 0, 7, 99, 111, 110, 110, 101, 99, 116, 0, 63, 240, 0, 0, 0, 0, 0, 0, 3, 0, 3, 97, 258 112, 112, 2, 0, 4, 108, 105, 118, 101, 0, 5, 116, 99, 85, 114, 108, 2, 0, 26, 114, 116, 259 109, 112, 58, 47, 47, 108, 111, 99, 97, 108, 104, 111, 115, 116, 58, 49, 57, 51, 53, 260 47, 108, 105, 118, 101, 0, 4, 102, 112, 97, 100, 1, 0, 0, 12, 99, 97, 112, 97, 98, 105, 261 108, 105, 116, 105, 101, 115, 0, 64, 46, 0, 0, 0, 0, 0, 0, 0, 11, 97, 117, 100, 105, 262 111, 67, 111, 100, 101, 99, 115, 0, 64, 168, 238, 0, 0, 0, 0, 0, 0, 11, 118, 105, 100, 263 101, 111, 195, 67, 111, 100, 101, 99, 115, 0, 64, 111, 128, 0, 0, 0, 0, 0, 0, 13, 118, 264 105, 100, 101, 111, 70, 117, 110, 99, 116, 105, 111, 110, 0, 63, 240, 0, 0, 0, 0, 0, 0, 265 0, 0, 9, 266 ]; 267 268 //76 69 64 65 6f 43 6f 64 65 63 73 269 // 118 105 100 101 111 67 111 100 101 99 115 270 271 let mut bytes_reader = BytesReader::new(BytesMut::new()); 272 bytes_reader.extend_from_slice(&data); 273 let mut amf_reader = Amf0Reader::new(bytes_reader); 274 275 let command_name = amf_reader.read_with_type(amf0_markers::STRING).unwrap(); 276 assert_eq!( 277 command_name, 278 Amf0ValueType::UTF8String(String::from("connect")) 279 ); 280 281 let transaction_id = amf_reader.read_with_type(amf0_markers::NUMBER).unwrap(); 282 assert_eq!(transaction_id, Amf0ValueType::Number(1.0)); 283 284 let command_obj_raw = amf_reader.read_with_type(amf0_markers::OBJECT); 285 let mut properties = HashMap::new(); 286 properties.insert( 287 String::from("app"), 288 Amf0ValueType::UTF8String(String::from("live")), 289 ); 290 properties.insert( 291 String::from("tcUrl"), 292 Amf0ValueType::UTF8String(String::from("rtmp://localhost:1935/live")), 293 ); 294 properties.insert(String::from("fpad"), Amf0ValueType::Boolean(false)); 295 properties.insert(String::from("capabilities"), Amf0ValueType::Number(15.0)); 296 properties.insert(String::from("audioCodecs"), Amf0ValueType::Number(3191.0)); 297 298 properties.insert(String::from("videoCodecs"), Amf0ValueType::Number(252.0)); 299 300 properties.insert(String::from("videoFunction"), Amf0ValueType::Number(1.0)); 301 302 assert_eq!(command_obj_raw.unwrap(), Amf0ValueType::Object(properties)); 303 } 304 } 305