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