frame: cleanup frame API

Signed-off-by: Alexey Galakhov <agalakhov@snapview.de>
pull/43/head
Alexey Galakhov 7 years ago
parent 75aa0d54f3
commit 50d1371e52
  1. 129
      src/protocol/frame/frame.rs
  2. 15
      src/protocol/mod.rs

@ -50,7 +50,7 @@ pub struct FrameHeader {
/// WebSocket protocol opcode.
pub opcode: OpCode,
/// A frame mask, if any.
pub mask: Option<[u8; 4]>,
mask: Option<[u8; 4]>,
}
impl Default for FrameHeader {
@ -120,6 +120,13 @@ impl FrameHeader {
Ok(())
}
/// Generate a random frame mask and store this in the header.
///
/// Of course this does not change frame contents. It just generates a mask.
pub(crate) fn set_random_mask(&mut self) {
self.mask = Some(generate_mask())
}
}
impl FrameHeader {
@ -218,34 +225,16 @@ impl Frame {
self.header.len(length as u64) + length
}
/// Test whether the frame is a final frame.
#[inline]
pub fn is_final(&self) -> bool {
self.header.is_final
}
/// Test whether the first reserved bit is set.
/// Get a reference to the frame's header.
#[inline]
pub fn has_rsv1(&self) -> bool {
self.header.rsv1
pub fn header(&self) -> &FrameHeader {
&self.header
}
/// Test whether the second reserved bit is set.
/// Get a mutable reference to the frame's header.
#[inline]
pub fn has_rsv2(&self) -> bool {
self.header.rsv2
}
/// Test whether the third reserved bit is set.
#[inline]
pub fn has_rsv3(&self) -> bool {
self.header.rsv3
}
/// Get the OpCode of the frame.
#[inline]
pub fn opcode(&self) -> OpCode {
self.header.opcode
pub fn header_mut(&mut self) -> &mut FrameHeader {
&mut self.header
}
/// Get a reference to the frame's payload.
@ -254,86 +243,34 @@ impl Frame {
&self.payload
}
// Test whether the frame is masked.
#[doc(hidden)]
#[inline]
pub fn is_masked(&self) -> bool {
self.header.mask.is_some()
}
// Get an optional reference to the frame's mask.
#[doc(hidden)]
#[allow(dead_code)]
#[inline]
pub fn mask(&self) -> Option<&[u8; 4]> {
self.header.mask.as_ref()
}
/// Make this frame a final frame.
#[allow(dead_code)]
/// Get a mutable reference to the frame's payload.
#[inline]
pub fn set_final(&mut self, is_final: bool) -> &mut Frame {
self.header.is_final = is_final;
self
}
/// Set the first reserved bit.
#[inline]
pub fn set_rsv1(&mut self, has_rsv1: bool) -> &mut Frame {
self.header.rsv1 = has_rsv1;
self
}
/// Set the second reserved bit.
#[inline]
pub fn set_rsv2(&mut self, has_rsv2: bool) -> &mut Frame {
self.header.rsv2 = has_rsv2;
self
}
/// Set the third reserved bit.
#[inline]
pub fn set_rsv3(&mut self, has_rsv3: bool) -> &mut Frame {
self.header.rsv3 = has_rsv3;
self
pub fn payload_mut(&mut self) -> &mut Vec<u8> {
&mut self.payload
}
/// Set the OpCode.
#[allow(dead_code)]
/// Test whether the frame is masked.
#[inline]
pub fn set_opcode(&mut self, opcode: OpCode) -> &mut Frame {
self.header.opcode = opcode;
self
pub(crate) fn is_masked(&self) -> bool {
self.header.mask.is_some()
}
/// Edit the frame's payload.
#[allow(dead_code)]
/// Generate a random mask for the frame.
///
/// This just generates a mask, payload is not changed. The actual masking is performed
/// either on `format()` or on `apply_mask()` call.
#[inline]
pub fn payload_mut(&mut self) -> &mut Vec<u8> {
&mut self.payload
pub(crate) fn set_random_mask(&mut self) {
self.header.set_random_mask()
}
// Generate a new mask for this frame.
//
// This method simply generates and stores the mask. It does not change the payload data.
// Instead, the payload data will be masked with the generated mask when the frame is sent
// to the other endpoint.
#[doc(hidden)]
/// This method unmasks the payload and should only be called on frames that are actually
/// masked. In other words, those frames that have just been received from a client endpoint.
#[inline]
pub fn set_mask(&mut self) -> &mut Frame {
self.header.mask = Some(generate_mask());
self
pub(crate) fn apply_mask(&mut self) {
if let Some(mask) = self.header.mask.take() {
apply_mask(&mut self.payload, &mask)
}
// This method unmasks the payload and should only be called on frames that are actually
// masked. In other words, those frames that have just been received from a client endpoint.
#[doc(hidden)]
#[inline]
pub fn remove_mask(&mut self) {
self.header.mask.and_then(|mask| {
Some(apply_mask(&mut self.payload, &mask))
});
self.header.mask = None;
}
/// Consume the frame into its payload as binary.
@ -350,7 +287,7 @@ impl Frame {
/// Consume the frame into a closing frame.
#[inline]
pub fn into_close(self) -> Result<Option<CloseFrame<'static>>> {
pub(crate) fn into_close(self) -> Result<Option<CloseFrame<'static>>> {
match self.payload.len() {
0 => Ok(None),
1 => Err(Error::Protocol("Invalid close sequence".into())),
@ -435,7 +372,7 @@ impl Frame {
/// Write a frame out to a buffer
pub fn format(mut self, output: &mut impl Write) -> Result<()> {
self.header.format(self.payload.len() as u64, output)?;
self.remove_mask();
self.apply_mask();
output.write_all(self.payload())?;
Ok(())
}

@ -246,16 +246,19 @@ impl<Stream: Read + Write> WebSocket<Stream> {
// the negotiated extensions defines the meaning of such a nonzero
// value, the receiving endpoint MUST _Fail the WebSocket
// Connection_.
if frame.has_rsv1() || frame.has_rsv2() || frame.has_rsv3() {
{
let hdr = frame.header();
if hdr.rsv1 || hdr.rsv2 || hdr.rsv3 {
return Err(Error::Protocol("Reserved bits are non-zero".into()))
}
}
match self.role {
Role::Server => {
if frame.is_masked() {
// A server MUST remove masking for data frames received from a client
// as described in Section 5.3. (RFC 6455)
frame.remove_mask()
frame.apply_mask()
} else {
// The server MUST close the connection upon receiving a
// frame that is not masked. (RFC 6455)
@ -270,13 +273,13 @@ impl<Stream: Read + Write> WebSocket<Stream> {
}
}
match frame.opcode() {
match frame.header().opcode {
OpCode::Control(ctl) => {
match ctl {
// All control frames MUST have a payload length of 125 bytes or less
// and MUST NOT be fragmented. (RFC 6455)
_ if !frame.is_final() => {
_ if !frame.header().is_final => {
Err(Error::Protocol("Fragmented control frame".into()))
}
_ if frame.payload().len() > 125 => {
@ -309,7 +312,7 @@ impl<Stream: Read + Write> WebSocket<Stream> {
}
OpCode::Data(data) => {
let fin = frame.is_final();
let fin = frame.header().is_final;
match data {
OpData::Continue => {
if let Some(ref mut msg) = self.incomplete {
@ -423,7 +426,7 @@ impl<Stream: Read + Write> WebSocket<Stream> {
Role::Client => {
// 5. If the data is being sent by the client, the frame(s) MUST be
// masked as defined in Section 5.3. (RFC 6455)
frame.set_mask();
frame.set_random_mask();
}
}
let res = self.socket.write_frame(frame);

Loading…
Cancel
Save