use std::collections::VecDeque;
use std::io::{Error, Result, ErrorKind};
use bytes::BufMut;
use httparse::Request;
use futures::future::LocalBoxFuture;
use pi_rand::SecureRng;
use tcp::{Socket, SocketHandle, SocketEvent,
utils::SocketContext};
use crate::{connect::WsSocket,
frame::{CLOSE_OPCODE, TEXT_OPCODE, BINARY_OPCODE, PING_OPCODE, PONG_OPCODE}};
pub trait ChildProtocol<S: Socket>: Send + Sync + 'static {
fn protocol_name(&self) -> &str;
fn non_standard_handshake_protocol(&self,
_request: &Request) -> Result<(String, Vec<u8>)> {
Err(Error::new(ErrorKind::Other,
"Handle non-standard handshake protocol failed, reason: empty protocol"))
}
fn handshake_protocol(&self,
_handle: SocketHandle<S>,
_request: &Request,
protocols: &Vec<&str>) -> Result<()> {
Ok(())
}
fn is_strict(&self) -> bool;
fn decode_protocol(&self,
connect: WsSocket<S>,
context: &mut WsSession) -> LocalBoxFuture<'static, Result<()>>;
fn close_protocol(&self,
connect: WsSocket<S>,
context: WsSession,
reason: Result<()>) -> LocalBoxFuture<'static, ()>;
fn protocol_timeout(&self,
connect: WsSocket<S>,
context: &mut WsSession,
event: SocketEvent) -> LocalBoxFuture<'static, Result<()>>;
}
#[derive(Debug, Clone)]
pub enum WsStatus {
HandShaking, HandShaked, Closing, Closed, }
unsafe impl Send for WsStatus {}
#[derive(Debug, Clone)]
pub enum WsFrameType {
Undefined, Close, Ping, Pong, Text, Binary, }
unsafe impl Send for WsFrameType {}
impl From<u8> for WsFrameType {
fn from(opcode: u8) -> Self {
match opcode {
CLOSE_OPCODE => {
WsFrameType::Close
},
PING_OPCODE => {
WsFrameType::Ping
},
PONG_OPCODE => {
WsFrameType::Pong
},
TEXT_OPCODE => {
WsFrameType::Text
},
_ => {
WsFrameType::Binary
}
}
}
}
impl From<WsFrameType> for u8 {
fn from(frame_type: WsFrameType) -> Self {
match frame_type {
WsFrameType::Ping => PING_OPCODE,
WsFrameType::Pong => PONG_OPCODE,
WsFrameType::Text => TEXT_OPCODE,
WsFrameType::Binary => BINARY_OPCODE,
_ => CLOSE_OPCODE,
}
}
}
impl WsFrameType {
pub fn is_control(&self) -> bool {
match self {
&WsFrameType::Text | &WsFrameType::Binary => false,
_ => true,
}
}
}
pub struct WsSession {
status: WsStatus, r#type: WsFrameType, seed: u64, nonce_count: u64, rng: Option<SecureRng>, msg: Option<Vec<u8>>, queue: VecDeque<Vec<u8>>, context: SocketContext, }
unsafe impl Send for WsSession {}
unsafe impl Sync for WsSession {}
impl Default for WsSession {
fn default() -> Self {
WsSession {
status: WsStatus::HandShaking,
r#type: WsFrameType::Undefined,
seed: 0,
nonce_count: 0,
rng: None,
msg: Some(Vec::with_capacity(32)),
queue: VecDeque::with_capacity(8),
context: SocketContext::empty(),
}
}
}
impl WsSession {
pub fn with_seed(seed: u64) -> Self {
let rng = SecureRng::with_seed(seed);
WsSession {
status: WsStatus::HandShaking,
r#type: WsFrameType::Undefined,
seed,
nonce_count: 0,
rng: Some(rng),
msg: Some(Vec::with_capacity(32)),
queue: VecDeque::with_capacity(8),
context: SocketContext::empty(),
}
}
pub fn is_handshaked(&self) -> bool {
match &self.status {
WsStatus::HandShaked => true,
_ => false,
}
}
pub fn is_closing(&self) -> bool {
if let WsStatus::Closing = self.status {
true
} else {
false
}
}
pub fn is_closed(&self) -> bool {
if let WsStatus::Closed = self.status {
true
} else {
false
}
}
pub fn set_status(&mut self, status: WsStatus) {
self.status = status;
}
pub fn is_control(&self) -> bool {
self.r#type.is_control()
}
pub fn is_binary(&self) -> bool {
!self.r#type.is_control()
}
pub fn get_type(&self) -> WsFrameType {
self.r#type.clone()
}
pub fn set_type(&mut self, frame_type: u8) {
self.r#type = frame_type.into();
}
pub fn get_seed(&self) -> u64 {
self.seed
}
pub fn get_nonce_count(&self) -> u64 {
self.nonce_count
}
pub fn check_nonce(&mut self, nonce: u32) -> bool {
if let Some(rng) = &mut self.rng {
self.nonce_count += 1;
if rng.get_u32() == nonce {
true
} else {
false
}
} else {
true
}
}
pub fn len(&self) -> usize {
self.queue.len()
}
pub fn as_first_msg(&self) -> &[u8] {
if self.queue.is_empty() {
self.as_msg()
} else {
self.queue[0].as_slice()
}
}
pub fn as_msg(&self) -> &[u8] {
self
.msg
.as_ref()
.unwrap()
.as_slice()
}
pub fn as_msg_mut(&mut self) -> &mut [u8] {
self
.msg
.as_mut()
.unwrap()
.as_mut_slice()
}
pub fn pop_msg(&mut self) -> Vec<u8> {
if let Some(buf) = self.queue.pop_front() {
buf
} else {
Vec::new()
}
}
pub fn fill_msg<B: AsRef<[u8]>>(&mut self, frame: B) {
if let Some(msg) = &mut self.msg {
msg.put_slice(frame.as_ref());
} else {
unimplemented!()
}
}
pub fn finish_msg(&mut self) {
if let Some(msg) = self.msg.take() {
self.msg = Some(Vec::with_capacity(32));
self.queue.push_back(msg);
} else {
self.msg = Some(Vec::with_capacity(32));
}
}
pub fn reset(&mut self) {
self.r#type = WsFrameType::Undefined;
}
pub fn get_context(&self) -> &SocketContext {
&self.context
}
pub fn get_context_mut(&mut self) -> &mut SocketContext {
&mut self.context
}
}