mirror of
https://github.com/Noratrieb/haesli.git
synced 2026-01-17 05:05:03 +01:00
things
This commit is contained in:
parent
89820b06ca
commit
606438f301
14 changed files with 173 additions and 114 deletions
|
|
@ -1,32 +1,29 @@
|
|||
use crate::error::{ConException, ProtocolError, Result};
|
||||
use crate::frame::{ChannelId, ContentHeader, Frame, FrameType};
|
||||
use crate::{frame, methods, sasl};
|
||||
use amqp_core::message::{RawMessage, RoutingInformation};
|
||||
use amqp_core::methods::{FieldValue, Method, Table};
|
||||
use amqp_core::GlobalData;
|
||||
use anyhow::Context;
|
||||
use bytes::Bytes;
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use bytes::Bytes;
|
||||
use smallvec::SmallVec;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time;
|
||||
use tracing::{debug, error, info, warn};
|
||||
use uuid::Uuid;
|
||||
|
||||
use amqp_core::message::{RawMessage, RoutingInformation};
|
||||
use amqp_core::methods::{FieldValue, Method, Table};
|
||||
use amqp_core::GlobalData;
|
||||
|
||||
use crate::error::{ConException, ProtocolError, Result};
|
||||
use crate::frame::{ChannelId, ContentHeader, Frame, FrameType};
|
||||
use crate::{frame, methods, sasl};
|
||||
|
||||
fn ensure_conn(condition: bool) -> Result<()> {
|
||||
if condition {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConException::Todo.into_trans())
|
||||
Err(ConException::Todo.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +164,7 @@ impl Connection {
|
|||
let plain_user = sasl::parse_sasl_plain_response(&response)?;
|
||||
info!(username = %plain_user.authentication_identity, "SASL Authentication successful")
|
||||
} else {
|
||||
return Err(ConException::Todo.into_trans());
|
||||
return Err(ConException::Todo.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -262,21 +259,20 @@ impl Connection {
|
|||
Some(channel) => {
|
||||
channel.status = ChannelStatus::NeedHeader(BASIC_CLASS_ID, Box::new(method))
|
||||
}
|
||||
None => return Err(ConException::Todo.into_trans()),
|
||||
None => return Err(ConException::Todo.into()),
|
||||
},
|
||||
_ => {
|
||||
let channel_handle = self
|
||||
.channels
|
||||
.get(&frame.channel)
|
||||
.ok_or_else(|| ConException::Todo.into_trans())?
|
||||
.ok_or(ConException::Todo)?
|
||||
.handle
|
||||
.clone();
|
||||
|
||||
tokio::spawn(amqp_messaging::methods::handle_method(
|
||||
channel_handle,
|
||||
method,
|
||||
));
|
||||
// we don't handle this here, forward it to *somewhere*
|
||||
// call into amqp_messaging to handle the method
|
||||
// amqp_messaging then branches and spawns a new task for longer running things,
|
||||
// so the connection task will only be "blocked" for a short amount of time
|
||||
amqp_messaging::methods::handle_method(channel_handle, method).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -285,11 +281,11 @@ impl Connection {
|
|||
fn dispatch_header(&mut self, frame: Frame) -> Result<()> {
|
||||
self.channels
|
||||
.get_mut(&frame.channel)
|
||||
.ok_or_else(|| ConException::Todo.into_trans())
|
||||
.ok_or_else(|| ConException::Todo.into())
|
||||
.and_then(|channel| match channel.status.take() {
|
||||
ChannelStatus::Default => {
|
||||
warn!(channel = %frame.channel, "unexpected header");
|
||||
Err(ConException::UnexpectedFrame.into_trans())
|
||||
Err(ConException::UnexpectedFrame.into())
|
||||
}
|
||||
ChannelStatus::NeedHeader(class_id, method) => {
|
||||
let header = ContentHeader::parse(&frame.payload)?;
|
||||
|
|
@ -300,7 +296,7 @@ impl Connection {
|
|||
}
|
||||
ChannelStatus::NeedsBody(_, _, _) => {
|
||||
warn!(channel = %frame.channel, "already got header");
|
||||
Err(ConException::UnexpectedFrame.into_trans())
|
||||
Err(ConException::UnexpectedFrame.into())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -309,16 +305,16 @@ impl Connection {
|
|||
let channel = self
|
||||
.channels
|
||||
.get_mut(&frame.channel)
|
||||
.ok_or_else(|| ConException::Todo.into_trans())?;
|
||||
.ok_or(ConException::Todo)?;
|
||||
|
||||
match channel.status.take() {
|
||||
ChannelStatus::Default => {
|
||||
warn!(channel = %frame.channel, "unexpected body");
|
||||
Err(ConException::UnexpectedFrame.into_trans())
|
||||
Err(ConException::UnexpectedFrame.into())
|
||||
}
|
||||
ChannelStatus::NeedHeader(_, _) => {
|
||||
warn!(channel = %frame.channel, "unexpected body");
|
||||
Err(ConException::UnexpectedFrame.into_trans())
|
||||
Err(ConException::UnexpectedFrame.into())
|
||||
}
|
||||
ChannelStatus::NeedsBody(method, header, mut vec) => {
|
||||
vec.push(frame.payload);
|
||||
|
|
@ -331,7 +327,7 @@ impl Connection {
|
|||
Ordering::Equal => {
|
||||
self.process_method_with_body(*method, *header, vec, frame.channel)
|
||||
}
|
||||
Ordering::Greater => Err(ConException::Todo.into_trans()),
|
||||
Ordering::Greater => Err(ConException::Todo.into()),
|
||||
Ordering::Less => Ok(()), // wait for next body
|
||||
}
|
||||
}
|
||||
|
|
@ -369,10 +365,7 @@ impl Connection {
|
|||
};
|
||||
let message = Arc::new(message);
|
||||
|
||||
let channel = self
|
||||
.channels
|
||||
.get(&channel)
|
||||
.ok_or_else(|| ConException::Todo.into_trans())?;
|
||||
let channel = self.channels.get(&channel).ok_or(ConException::Todo)?;
|
||||
|
||||
// Spawn the handler for the publish. The connection task goes back to handling
|
||||
// just the connection.
|
||||
|
|
@ -382,7 +375,7 @@ impl Connection {
|
|||
));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConException::Todo.into_trans())
|
||||
Err(ConException::Todo.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +396,7 @@ impl Connection {
|
|||
let prev = self.channels.insert(channel_id, channel);
|
||||
if let Some(prev) = prev {
|
||||
self.channels.insert(channel_id, prev); // restore previous state
|
||||
return Err(ConException::ChannelError.into_trans());
|
||||
return Err(ConException::ChannelError.into());
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -444,7 +437,7 @@ impl Connection {
|
|||
drop(channel);
|
||||
self.send_method(channel_id, Method::ChannelCloseOk).await?;
|
||||
} else {
|
||||
return Err(ConException::Todo.into_trans());
|
||||
return Err(ConException::Todo.into());
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
use std::io::Error;
|
||||
|
||||
pub use amqp_core::error::{ConException, ProtocolError};
|
||||
|
||||
pub type StdResult<T, E> = std::result::Result<T, E>;
|
||||
|
||||
pub type Result<T> = StdResult<T, TransError>;
|
||||
|
|
@ -9,7 +11,7 @@ pub type Result<T> = StdResult<T, TransError>;
|
|||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TransError {
|
||||
#[error("{0}")]
|
||||
Invalid(#[from] ProtocolError),
|
||||
Protocol(#[from] ProtocolError),
|
||||
#[error("connection error: `{0}`")]
|
||||
Other(#[from] anyhow::Error),
|
||||
}
|
||||
|
|
@ -20,42 +22,8 @@ impl From<std::io::Error> for TransError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ProtocolError {
|
||||
#[error("fatal error")]
|
||||
Fatal,
|
||||
#[error("{0}")]
|
||||
ConException(#[from] ConException),
|
||||
#[error("{0}")]
|
||||
ChannelException(#[from] ChannelException),
|
||||
#[error("Connection must be closed")]
|
||||
CloseNow,
|
||||
#[error("Graceful connection closing requested")]
|
||||
GracefulClose,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ConException {
|
||||
#[error("501 Frame error")]
|
||||
FrameError,
|
||||
#[error("503 Command invalid")]
|
||||
CommandInvalid,
|
||||
#[error("503 Syntax error | {0:?}")]
|
||||
/// A method was received but there was a syntax error. The string stores where it occurred.
|
||||
SyntaxError(Vec<String>),
|
||||
#[error("504 Channel error")]
|
||||
ChannelError,
|
||||
#[error("505 Unexpected Frame")]
|
||||
UnexpectedFrame,
|
||||
#[error("xxx Not decided yet")]
|
||||
Todo,
|
||||
}
|
||||
|
||||
impl ConException {
|
||||
pub fn into_trans(self) -> TransError {
|
||||
TransError::Invalid(ProtocolError::ConException(self))
|
||||
impl From<amqp_core::error::ConException> for TransError {
|
||||
fn from(err: ConException) -> Self {
|
||||
Self::Protocol(ProtocolError::ConException(err))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ChannelException {}
|
||||
|
|
|
|||
|
|
@ -148,14 +148,11 @@ impl ContentHeader {
|
|||
Ok((_, _)) => {
|
||||
Err(
|
||||
ConException::SyntaxError(vec!["could not consume all input".to_string()])
|
||||
.into_trans(),
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
Err(nom::Err::Incomplete(_)) => {
|
||||
Err(
|
||||
ConException::SyntaxError(vec!["there was not enough data".to_string()])
|
||||
.into_trans(),
|
||||
)
|
||||
Err(ConException::SyntaxError(vec!["there was not enough data".to_string()]).into())
|
||||
}
|
||||
Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err),
|
||||
}
|
||||
|
|
@ -197,7 +194,7 @@ where
|
|||
}
|
||||
|
||||
if max_frame_size != 0 && payload.len() > max_frame_size {
|
||||
return Err(ConException::FrameError.into_trans());
|
||||
return Err(ConException::FrameError.into());
|
||||
}
|
||||
|
||||
let kind = parse_frame_type(kind, channel)?;
|
||||
|
|
@ -225,7 +222,7 @@ fn parse_frame_type(kind: u8, channel: ChannelId) -> Result<FrameType> {
|
|||
Err(ProtocolError::ConException(ConException::FrameError).into())
|
||||
}
|
||||
}
|
||||
_ => Err(ConException::FrameError.into_trans()),
|
||||
_ => Err(ConException::FrameError.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::error::{ConException, TransError};
|
||||
use crate::error::TransError;
|
||||
use amqp_core::error::ConException;
|
||||
use amqp_core::methods::{FieldValue, Method, Table};
|
||||
use rand::Rng;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -18,16 +19,10 @@ pub fn parse_method(payload: &[u8]) -> Result<Method, TransError> {
|
|||
match nom_result {
|
||||
Ok(([], method)) => Ok(method),
|
||||
Ok((_, _)) => {
|
||||
Err(
|
||||
ConException::SyntaxError(vec!["could not consume all input".to_string()])
|
||||
.into_trans(),
|
||||
)
|
||||
Err(ConException::SyntaxError(vec!["could not consume all input".to_string()]).into())
|
||||
}
|
||||
Err(nom::Err::Incomplete(_)) => {
|
||||
Err(
|
||||
ConException::SyntaxError(vec!["there was not enough data".to_string()])
|
||||
.into_trans(),
|
||||
)
|
||||
Err(ConException::SyntaxError(vec!["there was not enough data".to_string()]).into())
|
||||
}
|
||||
Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::error::{ConException, ProtocolError, TransError};
|
||||
use crate::error::TransError;
|
||||
use crate::methods::generated::parse::IResult;
|
||||
use amqp_core::error::{ConException, ProtocolError};
|
||||
use amqp_core::methods::{
|
||||
Bit, FieldValue, Long, Longlong, Longstr, Octet, Short, Shortstr, Table, TableFieldName,
|
||||
Timestamp,
|
||||
|
|
@ -15,7 +16,7 @@ use std::collections::HashMap;
|
|||
|
||||
impl<T> nom::error::ParseError<T> for TransError {
|
||||
fn from_error_kind(_input: T, _kind: ErrorKind) -> Self {
|
||||
ConException::SyntaxError(vec![]).into_trans()
|
||||
ConException::SyntaxError(vec![]).into()
|
||||
}
|
||||
|
||||
fn append(_input: T, _kind: ErrorKind, other: Self) -> Self {
|
||||
|
|
@ -28,7 +29,7 @@ pub fn fail_err<S: Into<String>>(msg: S) -> impl FnOnce(Err<TransError>) -> Err<
|
|||
let msg = msg.into();
|
||||
let stack = match err {
|
||||
Err::Error(e) | Err::Failure(e) => match e {
|
||||
TransError::Invalid(ProtocolError::ConException(ConException::SyntaxError(
|
||||
TransError::Protocol(ProtocolError::ConException(ConException::SyntaxError(
|
||||
mut stack,
|
||||
))) => {
|
||||
stack.push(msg);
|
||||
|
|
@ -38,20 +39,20 @@ pub fn fail_err<S: Into<String>>(msg: S) -> impl FnOnce(Err<TransError>) -> Err<
|
|||
},
|
||||
_ => vec![msg],
|
||||
};
|
||||
Err::Failure(ConException::SyntaxError(stack).into_trans())
|
||||
Err::Failure(ConException::SyntaxError(stack).into())
|
||||
}
|
||||
}
|
||||
pub fn err_other<E, S: Into<String>>(msg: S) -> impl FnOnce(E) -> Err<TransError> {
|
||||
move |_| Err::Error(ConException::SyntaxError(vec![msg.into()]).into_trans())
|
||||
move |_| Err::Error(ConException::SyntaxError(vec![msg.into()]).into())
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fail {
|
||||
($cause:expr) => {
|
||||
return Err(nom::Err::Failure(
|
||||
crate::error::ProtocolError::ConException(crate::error::ConException::SyntaxError(
|
||||
vec![String::from($cause)],
|
||||
))
|
||||
::amqp_core::error::ProtocolError::ConException(
|
||||
::amqp_core::error::ConException::SyntaxError(vec![String::from($cause)]),
|
||||
)
|
||||
.into(),
|
||||
))
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
//!
|
||||
//! Currently only supports PLAIN (see [RFC 4616](https://datatracker.ietf.org/doc/html/rfc4616))
|
||||
|
||||
use crate::error::{ConException, Result};
|
||||
use crate::error::Result;
|
||||
use amqp_core::error::ConException;
|
||||
|
||||
pub struct PlainUser {
|
||||
pub authorization_identity: String,
|
||||
|
|
@ -13,17 +14,11 @@ pub struct PlainUser {
|
|||
pub fn parse_sasl_plain_response(response: &[u8]) -> Result<PlainUser> {
|
||||
let mut parts = response
|
||||
.split(|&n| n == 0)
|
||||
.map(|bytes| String::from_utf8(bytes.into()).map_err(|_| ConException::Todo.into_trans()));
|
||||
.map(|bytes| String::from_utf8(bytes.into()).map_err(|_| ConException::Todo));
|
||||
|
||||
let authorization_identity = parts
|
||||
.next()
|
||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
||||
let authentication_identity = parts
|
||||
.next()
|
||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
||||
let password = parts
|
||||
.next()
|
||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
||||
let authorization_identity = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||
let authentication_identity = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||
let password = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||
|
||||
Ok(PlainUser {
|
||||
authorization_identity,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue