Skip to main content

flash_lso/packet/
write.rs

1//! Handles writing of AMF packets
2
3use crate::amf0;
4use crate::errors::Error;
5use crate::packet::{Header, Message, Packet};
6use crate::types::AMFVersion;
7
8fn write_header(
9    header: &Header,
10    out: &mut Vec<u8>,
11    exact_lengths: bool,
12) -> Result<(), Error<'static>> {
13    // Name
14    let name_length = u16::try_from(header.name.len()).map_err(|_| Error::PacketTooLarge)?;
15    out.extend(name_length.to_be_bytes());
16    out.extend(header.name.as_bytes());
17
18    // Must understand
19    if header.must_understand {
20        out.push(1);
21    } else {
22        out.push(0);
23    }
24
25    // Value
26    let mut value = Vec::new();
27    amf0::write::write_value(&mut value, &header.value)
28        .map_err(|e| Error::IoError(e.to_string(), e.kind()))?;
29    if exact_lengths {
30        let value_length = u32::try_from(value.len()).map_err(|_| Error::PacketTooLarge)?;
31        out.extend(value_length.to_be_bytes());
32    } else {
33        out.extend(u32::MAX.to_be_bytes());
34    }
35    out.append(&mut value);
36
37    Ok(())
38}
39
40fn write_message(
41    message: &Message,
42    out: &mut Vec<u8>,
43    exact_lengths: bool,
44) -> Result<(), Error<'static>> {
45    // Target URI
46    let target_length =
47        u16::try_from(message.target_uri.len()).map_err(|_| Error::PacketTooLarge)?;
48    out.extend(target_length.to_be_bytes());
49    out.extend(message.target_uri.as_bytes());
50
51    // Response URI
52    let response_length =
53        u16::try_from(message.response_uri.len()).map_err(|_| Error::PacketTooLarge)?;
54    out.extend(response_length.to_be_bytes());
55    out.extend(message.response_uri.as_bytes());
56
57    // Contents
58    let mut contents = Vec::new();
59    amf0::write::write_value(&mut contents, &message.contents)
60        .map_err(|e| Error::IoError(e.to_string(), e.kind()))?;
61    if exact_lengths {
62        let contents_length = u32::try_from(contents.len()).map_err(|_| Error::PacketTooLarge)?;
63        out.extend(contents_length.to_be_bytes());
64    } else {
65        out.extend(u32::MAX.to_be_bytes());
66    }
67    out.append(&mut contents);
68
69    Ok(())
70}
71
72/// Write a packet to a vec of bytes
73pub fn write_to_bytes(packet: &Packet, exact_lengths: bool) -> Result<Vec<u8>, Error<'static>> {
74    let mut buffer = Vec::new();
75
76    // Version
77    buffer.push(0);
78    match packet.version {
79        AMFVersion::AMF0 => buffer.push(0),
80        #[cfg(feature = "amf3")]
81        AMFVersion::AMF3 => buffer.push(3),
82    }
83
84    // Headers
85    let header_count = u16::try_from(packet.headers.len()).map_err(|_| Error::PacketTooLarge)?;
86    buffer.extend(header_count.to_be_bytes());
87    for header in &packet.headers {
88        write_header(header, &mut buffer, exact_lengths)?;
89    }
90
91    // Messages
92    let message_count = u16::try_from(packet.messages.len()).map_err(|_| Error::PacketTooLarge)?;
93    buffer.extend(message_count.to_be_bytes());
94    for message in &packet.messages {
95        write_message(message, &mut buffer, exact_lengths)?;
96    }
97
98    Ok(buffer)
99}