mirror of
https://github.com/Noratrieb/haesli.git
synced 2026-01-16 12:45:04 +01:00
parse frame payload
This commit is contained in:
parent
706219c046
commit
ccee6c36f6
3 changed files with 55 additions and 33 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::error::{ConError, ProtocolError};
|
use crate::error::{ProtocolError, TransError};
|
||||||
use crate::frame;
|
use crate::frame;
|
||||||
use anyhow::{ensure, Context};
|
use anyhow::{ensure, Context};
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
@ -21,7 +21,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<(), ConError> {
|
pub async fn run(&mut self) -> Result<(), TransError> {
|
||||||
self.negotiate_version().await?;
|
self.negotiate_version().await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -30,7 +30,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn negotiate_version(&mut self) -> Result<(), ConError> {
|
async fn negotiate_version(&mut self) -> Result<(), TransError> {
|
||||||
const HEADER_SIZE: usize = 8;
|
const HEADER_SIZE: usize = 8;
|
||||||
const PROTOCOL_VERSION: &[u8] = &[0, 9, 1];
|
const PROTOCOL_VERSION: &[u8] = &[0, 9, 1];
|
||||||
const PROTOCOL_HEADER: &[u8] = b"AMQP\0\0\x09\x01";
|
const PROTOCOL_HEADER: &[u8] = b"AMQP\0\0\x09\x01";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum ConError {
|
pub enum TransError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Invalid(#[from] ProtocolError),
|
Invalid(#[from] ProtocolError),
|
||||||
#[error("connection error: `{0}`")]
|
#[error("connection error: `{0}`")]
|
||||||
|
|
@ -24,6 +24,10 @@ pub enum ConException {
|
||||||
FrameError,
|
FrameError,
|
||||||
#[error("503 Command invalid")]
|
#[error("503 Command invalid")]
|
||||||
CommandInvalid,
|
CommandInvalid,
|
||||||
|
#[error("503 Syntax error")]
|
||||||
|
SyntaxError,
|
||||||
|
#[error("504 Channel error")]
|
||||||
|
ChannelError,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,48 @@
|
||||||
use crate::error::{ConError, ConException, ProtocolError};
|
use crate::error::{ConException, ProtocolError, TransError};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
const REQUIRED_FRAME_END: u8 = 0xCE;
|
const REQUIRED_FRAME_END: u8 = 0xCE;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
mod frame_type {
|
||||||
#[repr(u8)]
|
pub const METHOD: u8 = 1;
|
||||||
pub enum FrameType {
|
pub const HEADER: u8 = 2;
|
||||||
Method = 1,
|
pub const BODY: u8 = 3;
|
||||||
Header = 2,
|
pub const HEARTBEAT: u8 = 4;
|
||||||
Body = 3,
|
|
||||||
Heartbeat = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<u8> for FrameType {
|
|
||||||
type Error = ConError;
|
|
||||||
|
|
||||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
|
||||||
Ok(match value {
|
|
||||||
1 => Self::Method,
|
|
||||||
2 => Self::Header,
|
|
||||||
3 => Self::Body,
|
|
||||||
4 => Self::Heartbeat,
|
|
||||||
_ => return Err(ProtocolError::Fatal.into()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
r#type: FrameType,
|
/// type
|
||||||
|
kind: FrameType,
|
||||||
channel: u16,
|
channel: u16,
|
||||||
size: u32,
|
|
||||||
payload: Vec<u8>,
|
payload: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_frame<R>(r: &mut R, max_frame_size: usize) -> Result<Frame, ConError>
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum FrameType {
|
||||||
|
/// 1
|
||||||
|
Method { class_id: u16, method_id: u16 },
|
||||||
|
/// 2
|
||||||
|
Header {
|
||||||
|
class_id: u16,
|
||||||
|
/// Unused, must always be 0
|
||||||
|
weight: u16,
|
||||||
|
body_size: u64,
|
||||||
|
/// Ordered from high to low
|
||||||
|
property_flags: u16,
|
||||||
|
},
|
||||||
|
/// 3
|
||||||
|
Body,
|
||||||
|
/// 4
|
||||||
|
Heartbeat,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_frame<R>(r: &mut R, max_frame_size: usize) -> Result<Frame, TransError>
|
||||||
where
|
where
|
||||||
R: AsyncReadExt + Unpin,
|
R: AsyncReadExt + Unpin,
|
||||||
{
|
{
|
||||||
let r#type = r.read_u8().await.context("read type")?;
|
let kind = r.read_u8().await.context("read type")?;
|
||||||
let channel = r.read_u16().await.context("read channel")?;
|
let channel = r.read_u16().await.context("read channel")?;
|
||||||
let size = r.read_u32().await.context("read size")?;
|
let size = r.read_u32().await.context("read size")?;
|
||||||
|
|
||||||
|
|
@ -56,14 +59,29 @@ where
|
||||||
return Err(ProtocolError::ConException(ConException::FrameError).into());
|
return Err(ProtocolError::ConException(ConException::FrameError).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let kind = parse_frame_type(kind, &payload)?;
|
||||||
|
|
||||||
Ok(Frame {
|
Ok(Frame {
|
||||||
r#type: r#type.try_into()?,
|
kind,
|
||||||
channel,
|
channel,
|
||||||
size,
|
|
||||||
payload,
|
payload,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_frame_type(kind: u8, payload: &[u8], channel: u16) -> Result<FrameType, TransError> {
|
||||||
|
match kind {
|
||||||
|
frame_type::METHOD => todo!(),
|
||||||
|
frame_type::HEARTBEAT => {
|
||||||
|
if channel != 0 {
|
||||||
|
Err(ProtocolError::ConException(ConException::FrameError).into())
|
||||||
|
} else {
|
||||||
|
Ok(FrameType::Heartbeat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::frame::{Frame, FrameType};
|
use crate::frame::{Frame, FrameType};
|
||||||
|
|
@ -88,7 +106,7 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
frame,
|
frame,
|
||||||
Frame {
|
Frame {
|
||||||
r#type: FrameType::Method,
|
kind: FrameType::Method,
|
||||||
channel: 0,
|
channel: 0,
|
||||||
size: 3,
|
size: 3,
|
||||||
payload: vec![1, 2, 3],
|
payload: vec![1, 2, 3],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue