|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
use std::fmt; |
|
|
|
|
use std::borrow::Cow; |
|
|
|
|
use std::mem::transmute; |
|
|
|
|
use std::io::{Cursor, Read, Write}; |
|
|
|
|
use std::default::Default; |
|
|
|
@ -25,6 +26,15 @@ fn generate_mask() -> [u8; 4] { |
|
|
|
|
unsafe { transmute(rand::random::<u32>()) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// A struct representing the close command.
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
|
|
pub struct CloseFrame<'t> { |
|
|
|
|
/// The reason as a code.
|
|
|
|
|
pub code: CloseCode, |
|
|
|
|
/// The reason as text string.
|
|
|
|
|
pub reason: Cow<'t, str>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// A struct representing a WebSocket frame.
|
|
|
|
|
#[derive(Debug, Clone)] |
|
|
|
|
pub struct Frame { |
|
|
|
@ -194,7 +204,7 @@ impl Frame { |
|
|
|
|
|
|
|
|
|
/// Consume the frame into a closing frame.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn into_close(self) -> Result<Option<(CloseCode, String)>> { |
|
|
|
|
pub fn into_close(self) -> Result<Option<CloseFrame<'static>>> { |
|
|
|
|
match self.payload.len() { |
|
|
|
|
0 => Ok(None), |
|
|
|
|
1 => Err(Error::Protocol("Invalid close sequence".into())), |
|
|
|
@ -203,7 +213,7 @@ impl Frame { |
|
|
|
|
let code = NetworkEndian::read_u16(&data[0..2]).into(); |
|
|
|
|
data.drain(0..2); |
|
|
|
|
let text = String::from_utf8(data)?; |
|
|
|
|
Ok(Some((code, text))) |
|
|
|
|
Ok(Some(CloseFrame { code: code, reason: text.into() })) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -246,8 +256,8 @@ impl Frame { |
|
|
|
|
|
|
|
|
|
/// Create a new Close control frame.
|
|
|
|
|
#[inline] |
|
|
|
|
pub fn close(msg: Option<(CloseCode, &str)>) -> Frame { |
|
|
|
|
let payload = if let Some((code, reason)) = msg { |
|
|
|
|
pub fn close(msg: Option<CloseFrame>) -> Frame { |
|
|
|
|
let payload = if let Some(CloseFrame { code, reason }) = msg { |
|
|
|
|
let raw: [u8; 2] = unsafe { |
|
|
|
|
let u: u16 = code.into(); |
|
|
|
|
transmute(u.to_be()) |
|
|
|
|