use crate::protocol::{frame::coding::OpCodeData, message::Message};
use rama_core::error::{BoxError, ErrorExt};
use rama_net::conn::is_connection_error;
use rama_utils::str::utf8;
use std::{error, fmt, io};
#[derive(Debug)]
pub enum ProtocolError {
Utf8(BoxError),
Io(io::Error),
InvalidOpcode(u8),
InvalidCloseSequence,
MessageTooLong {
size: usize,
max_size: usize,
},
UnmaskedFrameFromClient,
WriteBufferFull(Message),
SendAfterClosing,
ReceivedAfterClosing,
NonZeroReservedBits,
MaskedFrameFromServer,
FragmentedControlFrame,
ControlFrameTooBig,
UnknownControlFrameType(u8),
ResetWithoutClosingHandshake,
UnexpectedContinueFrame,
ExpectedFragment(OpCodeData),
UnknownDataFrameType(u8),
DeflateError(BoxError),
}
impl ProtocolError {
pub fn is_connection_error(&self) -> bool {
if let Self::Io(err) = self {
is_connection_error(err)
} else {
false
}
}
}
impl From<utf8::DecodeError<'_>> for ProtocolError {
fn from(value: utf8::DecodeError<'_>) -> Self {
Self::Utf8(BoxError::from(value.to_string()))
}
}
impl From<std::str::Utf8Error> for ProtocolError {
fn from(value: std::str::Utf8Error) -> Self {
Self::Utf8(value.into_box_error())
}
}
impl From<io::Error> for ProtocolError {
fn from(value: io::Error) -> Self {
Self::Io(value)
}
}
impl fmt::Display for ProtocolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Utf8(err) => write!(f, "UTF-8 error: {err:?}"),
Self::Io(err) => write!(f, "I/O error: {err:?}"),
Self::InvalidOpcode(code) => write!(f, "Encountered invalid opcode: {code}"),
Self::InvalidCloseSequence => write!(f, "Invalid close sequence"),
Self::MessageTooLong { size, max_size } => {
write!(f, "Message too long: {size} > {max_size}")
}
Self::UnmaskedFrameFromClient => {
write!(f, "Received an unmasked frame from client")
}
Self::WriteBufferFull(_) => write!(f, "Write buffer is full"),
Self::SendAfterClosing => {
write!(f, "Sending after closing is not allowed")
}
Self::ReceivedAfterClosing => {
write!(f, "Remote sent after having closed")
}
Self::NonZeroReservedBits => {
write!(f, "Reserved bits are non-zero")
}
Self::MaskedFrameFromServer => {
write!(f, "Received a masked frame from server")
}
Self::FragmentedControlFrame => {
write!(f, "Fragmented control frame")
}
Self::ControlFrameTooBig => {
write!(
f,
"Control frame too big (payload must be 125 bytes or less)"
)
}
Self::UnknownControlFrameType(t) => {
write!(f, "Unknown control frame type: {t}")
}
Self::ResetWithoutClosingHandshake => {
write!(f, "Connection reset without closing handshake")
}
Self::UnexpectedContinueFrame => {
write!(f, "Continue frame but nothing to continue")
}
Self::ExpectedFragment(data) => {
write!(f, "While waiting for more fragments received: {data}")
}
Self::UnknownDataFrameType(t) => {
write!(f, "Unknown data frame type: {t}")
}
Self::DeflateError(err) => write!(f, "Deflate error: {err:?}"),
}
}
}
impl error::Error for ProtocolError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Self::Utf8(err) | Self::DeflateError(err) => Some(err.as_ref()),
Self::Io(err) => Some(err as &(dyn std::error::Error + 'static)),
Self::InvalidOpcode(_)
| Self::InvalidCloseSequence
| Self::MessageTooLong { .. }
| Self::UnmaskedFrameFromClient
| Self::WriteBufferFull(_)
| Self::SendAfterClosing
| Self::ReceivedAfterClosing
| Self::NonZeroReservedBits
| Self::MaskedFrameFromServer
| Self::FragmentedControlFrame
| Self::ControlFrameTooBig
| Self::UnknownControlFrameType(_)
| Self::ResetWithoutClosingHandshake
| Self::UnexpectedContinueFrame
| Self::ExpectedFragment(_)
| Self::UnknownDataFrameType(_) => None,
}
}
}