use br_crypto::hex;
#[derive(Debug)]
pub struct WebSocketMessage {
pub text: String,
}
impl WebSocketMessage {
pub fn parse_message(data: Vec<u8>) -> Result<WebSocketMessage, String> {
if data.len() < 2 {
return Err("长度不够".to_string());
}
let _fin = (data[0] & 0b1000_0000) != 0;
let opcode = data[0] & 0b0000_1111;
let masked = (data[1] & 0b1000_0000) != 0;
let payload_length = data[1] & 0b0111_1111;
let mut payload_data = Vec::new();
let message_tpye = MessageType::from(opcode);
match message_tpye {
MessageType::Text => {
let payload_start_index = if payload_length < 126 {
2
} else if payload_length >= 126 && payload_length as i32 <= 65535 {
4
} else {
10
};
if masked {
let t = i32::from_str_radix(&hex::encode(data[2..payload_start_index].to_vec()), 16).unwrap_or(0);
let payload = &data[payload_start_index + 4..];
if payload.len() != t as usize && payload_start_index > 2 {
return Err("继续加载".to_string());
}
let mask_key = &data[payload_start_index..payload_start_index + 4];
for i in 0..payload.len() {
payload_data.push(payload[i] ^ mask_key[i % 4]);
}
} else {
payload_data.extend_from_slice(&data[payload_start_index..]);
}
}
MessageType::Binary => {}
MessageType::Continuation => {}
MessageType::Close => {
return Err("关闭消息".to_string());
}
MessageType::Ping => {}
MessageType::Pong => {}
MessageType::None => {}
}
let text = match message_tpye {
MessageType::Text => {
unsafe { String::from_utf8_unchecked(payload_data.clone()) }
}
_ => "".to_string()
};
Ok(WebSocketMessage {
text,
})
}
}
#[derive(Debug)]
enum MessageType {
Text,
Continuation,
Close,
Binary,
Ping,
Pong,
None,
}
impl MessageType {
pub fn from(types: u8) -> Self {
match types {
0x0 => Self::Continuation,
0x1 => Self::Text,
0x2 => Self::Binary,
0x8 => Self::Close,
0x9 => Self::Ping,
0xa => Self::Pong,
_ => Self::None
}
}
}