#[cfg(test)]
mod chunk_test;
pub(crate) mod chunk_abort;
pub(crate) mod chunk_cookie_ack;
pub(crate) mod chunk_cookie_echo;
pub(crate) mod chunk_error;
pub(crate) mod chunk_forward_tsn;
pub(crate) mod chunk_header;
pub(crate) mod chunk_heartbeat;
pub(crate) mod chunk_heartbeat_ack;
pub(crate) mod chunk_init;
pub mod chunk_payload_data;
pub(crate) mod chunk_reconfig;
pub(crate) mod chunk_selective_ack;
pub(crate) mod chunk_shutdown;
pub(crate) mod chunk_shutdown_ack;
pub(crate) mod chunk_shutdown_complete;
pub(crate) mod chunk_type;
use crate::error::{Error, Result};
use chunk_header::*;
use bytes::{Buf, BufMut, Bytes, BytesMut};
use std::{any::Any, fmt};
pub(crate) trait Chunk: fmt::Display + fmt::Debug {
fn header(&self) -> ChunkHeader;
fn unmarshal(raw: &Bytes) -> Result<Self>
where
Self: Sized;
fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize>;
fn check(&self) -> Result<()>;
fn value_length(&self) -> usize;
fn as_any(&self) -> &(dyn Any + Send + Sync);
fn marshal(&self) -> Result<Bytes> {
let capacity = CHUNK_HEADER_SIZE + self.value_length();
let mut buf = BytesMut::with_capacity(capacity);
self.marshal_to(&mut buf)?;
Ok(buf.freeze())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub struct ErrorCauseCode(pub(crate) u16);
pub(crate) const INVALID_STREAM_IDENTIFIER: ErrorCauseCode = ErrorCauseCode(1);
pub(crate) const MISSING_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(2);
pub(crate) const STALE_COOKIE_ERROR: ErrorCauseCode = ErrorCauseCode(3);
pub(crate) const OUT_OF_RESOURCE: ErrorCauseCode = ErrorCauseCode(4);
pub(crate) const UNRESOLVABLE_ADDRESS: ErrorCauseCode = ErrorCauseCode(5);
pub(crate) const UNRECOGNIZED_CHUNK_TYPE: ErrorCauseCode = ErrorCauseCode(6);
pub(crate) const INVALID_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(7);
pub(crate) const UNRECOGNIZED_PARAMETERS: ErrorCauseCode = ErrorCauseCode(8);
pub(crate) const NO_USER_DATA: ErrorCauseCode = ErrorCauseCode(9);
pub(crate) const COOKIE_RECEIVED_WHILE_SHUTTING_DOWN: ErrorCauseCode = ErrorCauseCode(10);
pub(crate) const RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES: ErrorCauseCode = ErrorCauseCode(11);
pub(crate) const USER_INITIATED_ABORT: ErrorCauseCode = ErrorCauseCode(12);
pub(crate) const PROTOCOL_VIOLATION: ErrorCauseCode = ErrorCauseCode(13);
impl fmt::Display for ErrorCauseCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let others = format!("Unknown CauseCode: {}", self.0);
let s = match *self {
INVALID_STREAM_IDENTIFIER => "Invalid Stream Identifier",
MISSING_MANDATORY_PARAMETER => "Missing Mandatory Parameter",
STALE_COOKIE_ERROR => "Stale Cookie Error",
OUT_OF_RESOURCE => "Out Of Resource",
UNRESOLVABLE_ADDRESS => "Unresolvable IP",
UNRECOGNIZED_CHUNK_TYPE => "Unrecognized Chunk Type",
INVALID_MANDATORY_PARAMETER => "Invalid Mandatory Parameter",
UNRECOGNIZED_PARAMETERS => "Unrecognized Parameters",
NO_USER_DATA => "No User Data",
COOKIE_RECEIVED_WHILE_SHUTTING_DOWN => "Cookie Received While Shutting Down",
RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES => {
"Restart Of An Association With New Addresses"
}
USER_INITIATED_ABORT => "User Initiated Abort",
PROTOCOL_VIOLATION => "Protocol Violation",
_ => others.as_str(),
};
write!(f, "{}", s)
}
}
impl From<u16> for ErrorCauseCode {
fn from(v: u16) -> Self {
ErrorCauseCode(v)
}
}
#[derive(Debug, Clone, Default)]
pub(crate) struct ErrorCause {
pub(crate) code: ErrorCauseCode,
pub(crate) raw: Bytes,
}
pub(crate) type ErrorCauseInvalidMandatoryParameter = ErrorCause;
pub(crate) type ErrorCauseUnrecognizedChunkType = ErrorCause;
pub(crate) type ErrorCauseProtocolViolation = ErrorCause;
pub(crate) const ERROR_CAUSE_HEADER_LENGTH: usize = 4;
impl fmt::Display for ErrorCause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.code)
}
}
impl ErrorCause {
pub(crate) fn unmarshal(buf: &Bytes) -> Result<Self> {
if buf.len() < ERROR_CAUSE_HEADER_LENGTH {
return Err(Error::ErrErrorCauseTooSmall);
}
let reader = &mut buf.clone();
let code = ErrorCauseCode(reader.get_u16());
let len = reader.get_u16();
if len < ERROR_CAUSE_HEADER_LENGTH as u16 {
return Err(Error::ErrErrorCauseTooSmall);
}
let value_length = len as usize - ERROR_CAUSE_HEADER_LENGTH;
let raw = buf.slice(ERROR_CAUSE_HEADER_LENGTH..ERROR_CAUSE_HEADER_LENGTH + value_length);
Ok(ErrorCause { code, raw })
}
pub(crate) fn marshal(&self) -> Bytes {
let mut buf = BytesMut::with_capacity(self.length());
let _ = self.marshal_to(&mut buf);
buf.freeze()
}
pub(crate) fn marshal_to(&self, writer: &mut BytesMut) -> usize {
let len = self.raw.len() + ERROR_CAUSE_HEADER_LENGTH;
writer.put_u16(self.code.0);
writer.put_u16(len as u16);
writer.extend(self.raw.clone());
writer.len()
}
pub(crate) fn length(&self) -> usize {
self.raw.len() + ERROR_CAUSE_HEADER_LENGTH
}
pub(crate) fn error_cause_code(&self) -> ErrorCauseCode {
self.code
}
}