websocket_base/ws/dataframe.rs
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
//! Describes the generic DataFrame, defining a trait
//! that all dataframes should share. This is so one can
//! optimize the memory footprint of a dataframe for their
//! own needs, and be able to use custom dataframes quickly
use crate::result::WebSocketResult;
use crate::ws::util::header as dfh;
use crate::ws::util::mask;
use crate::ws::util::mask::Masker;
use std::io::Write;
/// A generic DataFrame. Every dataframe should be able to
/// provide these methods. (If the payload is not known in advance then
/// rewrite the write_payload method)
pub trait DataFrame {
/// Is this dataframe the final dataframe of the message?
fn is_last(&self) -> bool;
/// What type of data does this dataframe contain?
fn opcode(&self) -> u8;
/// Reserved bits of this dataframe
fn reserved(&self) -> &[bool; 3];
/// How long (in bytes) is this dataframe's payload
fn size(&self) -> usize;
/// Get's the size of the entire dataframe in bytes,
/// i.e. header and payload.
fn frame_size(&self, masked: bool) -> usize {
// one byte for the opcode & reserved & fin
1
// depending on the size of the payload, add the right payload len bytes
+ match self.size() {
s if s <= 125 => 1,
s if s <= 65535 => 3,
_ => 9,
}
// add the mask size if there is one
+ if masked {
4
} else {
0
}
// finally add the payload len
+ self.size()
}
/// Write the payload to a writer
fn write_payload(&self, socket: &mut dyn Write) -> WebSocketResult<()>;
/// Takes the payload out into a vec
fn take_payload(self) -> Vec<u8>;
/// Writes a DataFrame to a Writer.
fn write_to(&self, writer: &mut dyn Write, mask: bool) -> WebSocketResult<()> {
let mut flags = dfh::DataFrameFlags::empty();
if self.is_last() {
flags.insert(dfh::DataFrameFlags::FIN);
}
{
let reserved = self.reserved();
if reserved[0] {
flags.insert(dfh::DataFrameFlags::RSV1);
}
if reserved[1] {
flags.insert(dfh::DataFrameFlags::RSV2);
}
if reserved[2] {
flags.insert(dfh::DataFrameFlags::RSV3);
}
}
let masking_key = if mask { Some(mask::gen_mask()) } else { None };
let header = dfh::DataFrameHeader {
flags,
opcode: self.opcode() as u8,
mask: masking_key,
len: self.size() as u64,
};
let mut data = Vec::<u8>::new();
dfh::write_header(&mut data, header)?;
match masking_key {
Some(mask) => {
let mut masker = Masker::new(mask, &mut data);
self.write_payload(&mut masker)?
}
None => self.write_payload(&mut data)?,
};
writer.write_all(data.as_slice())?;
Ok(())
}
}