mirror of
https://github.com/Noratrieb/haesli.git
synced 2026-01-14 19:55:03 +01:00
things
This commit is contained in:
parent
89820b06ca
commit
606438f301
14 changed files with 173 additions and 114 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -31,6 +31,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"thiserror",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,5 @@ edition = "2021"
|
||||||
bytes = "1.1.0"
|
bytes = "1.1.0"
|
||||||
parking_lot = "0.12.0"
|
parking_lot = "0.12.0"
|
||||||
smallvec = { version = "1.8.0", features = ["union"] }
|
smallvec = { version = "1.8.0", features = ["union"] }
|
||||||
|
thiserror = "1.0.30"
|
||||||
uuid = "0.8.2"
|
uuid = "0.8.2"
|
||||||
|
|
|
||||||
35
amqp_core/src/error.rs
Normal file
35
amqp_core/src/error.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#[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("540 Not implemented")]
|
||||||
|
NotImplemented,
|
||||||
|
#[error("xxx Not decided yet")]
|
||||||
|
Todo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ChannelException {}
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(rust_2018_idioms)]
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod methods;
|
pub mod methods;
|
||||||
|
pub mod queue;
|
||||||
|
|
||||||
|
use crate::queue::Queue;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
@ -47,6 +50,7 @@ pub struct Connection {
|
||||||
pub peer_addr: SocketAddr,
|
pub peer_addr: SocketAddr,
|
||||||
pub global_data: GlobalData,
|
pub global_data: GlobalData,
|
||||||
pub channels: HashMap<u16, ChannelHandle>,
|
pub channels: HashMap<u16, ChannelHandle>,
|
||||||
|
pub exclusive_queues: Vec<Queue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
|
|
@ -60,6 +64,7 @@ impl Connection {
|
||||||
peer_addr,
|
peer_addr,
|
||||||
global_data,
|
global_data,
|
||||||
channels: HashMap::new(),
|
channels: HashMap::new(),
|
||||||
|
exclusive_queues: vec![],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
25
amqp_core/src/queue.rs
Normal file
25
amqp_core/src/queue.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
use crate::message::Message;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use std::sync::atomic::AtomicUsize;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub type Queue = Arc<RawQueue>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RawQueue {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub messages: Mutex<Vec<Message>>, // use a concurrent linked list???
|
||||||
|
pub durable: bool,
|
||||||
|
/// Whether the queue will automatically be deleted when no consumers uses it anymore.
|
||||||
|
/// The queue can always be manually deleted.
|
||||||
|
/// If auto-delete is enabled, it keeps track of the consumer count.
|
||||||
|
pub deletion: QueueDeletion,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum QueueDeletion {
|
||||||
|
Auto(AtomicUsize),
|
||||||
|
Manual,
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
|
use amqp_core::error::{ConException, ProtocolError};
|
||||||
use amqp_core::message::Message;
|
use amqp_core::message::Message;
|
||||||
use amqp_core::methods::Method;
|
use amqp_core::methods::Method;
|
||||||
use amqp_core::ChannelHandle;
|
use amqp_core::ChannelHandle;
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::time;
|
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
pub async fn handle_basic_publish(_channel_handle: ChannelHandle, message: Message) {
|
pub async fn handle_basic_publish(_channel_handle: ChannelHandle, message: Message) {
|
||||||
|
|
@ -12,7 +11,50 @@ pub async fn handle_basic_publish(_channel_handle: ChannelHandle, message: Messa
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_method(_channel_handle: ChannelHandle, _method: Method) {
|
pub async fn handle_method(
|
||||||
debug!("handling method or something in that cool new future");
|
_channel_handle: ChannelHandle,
|
||||||
time::sleep(Duration::from_secs(10)).await;
|
method: Method,
|
||||||
|
) -> Result<(), ProtocolError> {
|
||||||
|
match method {
|
||||||
|
Method::ExchangeDeclare { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::ExchangeDeclareOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::ExchangeDelete { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::ExchangeDeleteOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueDeclare { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueDeclareOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueBind { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueBindOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueUnbind { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueUnbindOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueuePurge { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueuePurgeOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueDelete { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::QueueDeleteOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicQos { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicQosOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicConsume { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicConsumeOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicCancel { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicCancelOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicReturn { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicDeliver { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicGet { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicGetOk { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicGetEmpty { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicAck { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicReject { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicRecoverAsync { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicRecover { .. } => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicRecoverOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::TxSelect
|
||||||
|
| Method::TxSelectOk
|
||||||
|
| Method::TxCommit
|
||||||
|
| Method::TxCommitOk
|
||||||
|
| Method::TxRollback
|
||||||
|
| Method::TxRollbackOk => Err(ConException::NotImplemented.into()),
|
||||||
|
Method::BasicPublish { .. } => {
|
||||||
|
unreachable!("Basic.Publish is handled somewhere else because it has a body")
|
||||||
|
}
|
||||||
|
_ => unreachable!("Method handled by transport layer"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use bytes::Bytes;
|
|
||||||
use smallvec::SmallVec;
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::time;
|
use tokio::time;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use uuid::Uuid;
|
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<()> {
|
fn ensure_conn(condition: bool) -> Result<()> {
|
||||||
if condition {
|
if condition {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} 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)?;
|
let plain_user = sasl::parse_sasl_plain_response(&response)?;
|
||||||
info!(username = %plain_user.authentication_identity, "SASL Authentication successful")
|
info!(username = %plain_user.authentication_identity, "SASL Authentication successful")
|
||||||
} else {
|
} else {
|
||||||
return Err(ConException::Todo.into_trans());
|
return Err(ConException::Todo.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -262,21 +259,20 @@ impl Connection {
|
||||||
Some(channel) => {
|
Some(channel) => {
|
||||||
channel.status = ChannelStatus::NeedHeader(BASIC_CLASS_ID, Box::new(method))
|
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
|
let channel_handle = self
|
||||||
.channels
|
.channels
|
||||||
.get(&frame.channel)
|
.get(&frame.channel)
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())?
|
.ok_or(ConException::Todo)?
|
||||||
.handle
|
.handle
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
tokio::spawn(amqp_messaging::methods::handle_method(
|
// call into amqp_messaging to handle the method
|
||||||
channel_handle,
|
// amqp_messaging then branches and spawns a new task for longer running things,
|
||||||
method,
|
// so the connection task will only be "blocked" for a short amount of time
|
||||||
));
|
amqp_messaging::methods::handle_method(channel_handle, method).await?;
|
||||||
// we don't handle this here, forward it to *somewhere*
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -285,11 +281,11 @@ impl Connection {
|
||||||
fn dispatch_header(&mut self, frame: Frame) -> Result<()> {
|
fn dispatch_header(&mut self, frame: Frame) -> Result<()> {
|
||||||
self.channels
|
self.channels
|
||||||
.get_mut(&frame.channel)
|
.get_mut(&frame.channel)
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())
|
.ok_or_else(|| ConException::Todo.into())
|
||||||
.and_then(|channel| match channel.status.take() {
|
.and_then(|channel| match channel.status.take() {
|
||||||
ChannelStatus::Default => {
|
ChannelStatus::Default => {
|
||||||
warn!(channel = %frame.channel, "unexpected header");
|
warn!(channel = %frame.channel, "unexpected header");
|
||||||
Err(ConException::UnexpectedFrame.into_trans())
|
Err(ConException::UnexpectedFrame.into())
|
||||||
}
|
}
|
||||||
ChannelStatus::NeedHeader(class_id, method) => {
|
ChannelStatus::NeedHeader(class_id, method) => {
|
||||||
let header = ContentHeader::parse(&frame.payload)?;
|
let header = ContentHeader::parse(&frame.payload)?;
|
||||||
|
|
@ -300,7 +296,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
ChannelStatus::NeedsBody(_, _, _) => {
|
ChannelStatus::NeedsBody(_, _, _) => {
|
||||||
warn!(channel = %frame.channel, "already got header");
|
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
|
let channel = self
|
||||||
.channels
|
.channels
|
||||||
.get_mut(&frame.channel)
|
.get_mut(&frame.channel)
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())?;
|
.ok_or(ConException::Todo)?;
|
||||||
|
|
||||||
match channel.status.take() {
|
match channel.status.take() {
|
||||||
ChannelStatus::Default => {
|
ChannelStatus::Default => {
|
||||||
warn!(channel = %frame.channel, "unexpected body");
|
warn!(channel = %frame.channel, "unexpected body");
|
||||||
Err(ConException::UnexpectedFrame.into_trans())
|
Err(ConException::UnexpectedFrame.into())
|
||||||
}
|
}
|
||||||
ChannelStatus::NeedHeader(_, _) => {
|
ChannelStatus::NeedHeader(_, _) => {
|
||||||
warn!(channel = %frame.channel, "unexpected body");
|
warn!(channel = %frame.channel, "unexpected body");
|
||||||
Err(ConException::UnexpectedFrame.into_trans())
|
Err(ConException::UnexpectedFrame.into())
|
||||||
}
|
}
|
||||||
ChannelStatus::NeedsBody(method, header, mut vec) => {
|
ChannelStatus::NeedsBody(method, header, mut vec) => {
|
||||||
vec.push(frame.payload);
|
vec.push(frame.payload);
|
||||||
|
|
@ -331,7 +327,7 @@ impl Connection {
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
self.process_method_with_body(*method, *header, vec, frame.channel)
|
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
|
Ordering::Less => Ok(()), // wait for next body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -369,10 +365,7 @@ impl Connection {
|
||||||
};
|
};
|
||||||
let message = Arc::new(message);
|
let message = Arc::new(message);
|
||||||
|
|
||||||
let channel = self
|
let channel = self.channels.get(&channel).ok_or(ConException::Todo)?;
|
||||||
.channels
|
|
||||||
.get(&channel)
|
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())?;
|
|
||||||
|
|
||||||
// Spawn the handler for the publish. The connection task goes back to handling
|
// Spawn the handler for the publish. The connection task goes back to handling
|
||||||
// just the connection.
|
// just the connection.
|
||||||
|
|
@ -382,7 +375,7 @@ impl Connection {
|
||||||
));
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ConException::Todo.into_trans())
|
Err(ConException::Todo.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,7 +396,7 @@ impl Connection {
|
||||||
let prev = self.channels.insert(channel_id, channel);
|
let prev = self.channels.insert(channel_id, channel);
|
||||||
if let Some(prev) = prev {
|
if let Some(prev) = prev {
|
||||||
self.channels.insert(channel_id, prev); // restore previous state
|
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);
|
drop(channel);
|
||||||
self.send_method(channel_id, Method::ChannelCloseOk).await?;
|
self.send_method(channel_id, Method::ChannelCloseOk).await?;
|
||||||
} else {
|
} else {
|
||||||
return Err(ConException::Todo.into_trans());
|
return Err(ConException::Todo.into());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
|
|
||||||
|
pub use amqp_core::error::{ConException, ProtocolError};
|
||||||
|
|
||||||
pub type StdResult<T, E> = std::result::Result<T, E>;
|
pub type StdResult<T, E> = std::result::Result<T, E>;
|
||||||
|
|
||||||
pub type Result<T> = StdResult<T, TransError>;
|
pub type Result<T> = StdResult<T, TransError>;
|
||||||
|
|
@ -9,7 +11,7 @@ pub type Result<T> = StdResult<T, TransError>;
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum TransError {
|
pub enum TransError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Invalid(#[from] ProtocolError),
|
Protocol(#[from] ProtocolError),
|
||||||
#[error("connection error: `{0}`")]
|
#[error("connection error: `{0}`")]
|
||||||
Other(#[from] anyhow::Error),
|
Other(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
@ -20,42 +22,8 @@ impl From<std::io::Error> for TransError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
impl From<amqp_core::error::ConException> for TransError {
|
||||||
pub enum ProtocolError {
|
fn from(err: ConException) -> Self {
|
||||||
#[error("fatal error")]
|
Self::Protocol(ProtocolError::ConException(err))
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum ChannelException {}
|
|
||||||
|
|
|
||||||
|
|
@ -148,14 +148,11 @@ impl ContentHeader {
|
||||||
Ok((_, _)) => {
|
Ok((_, _)) => {
|
||||||
Err(
|
Err(
|
||||||
ConException::SyntaxError(vec!["could not consume all input".to_string()])
|
ConException::SyntaxError(vec!["could not consume all input".to_string()])
|
||||||
.into_trans(),
|
.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Err(nom::Err::Incomplete(_)) => {
|
Err(nom::Err::Incomplete(_)) => {
|
||||||
Err(
|
Err(ConException::SyntaxError(vec!["there was not enough data".to_string()]).into())
|
||||||
ConException::SyntaxError(vec!["there was not enough data".to_string()])
|
|
||||||
.into_trans(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err),
|
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 {
|
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)?;
|
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(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 amqp_core::methods::{FieldValue, Method, Table};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -18,16 +19,10 @@ pub fn parse_method(payload: &[u8]) -> Result<Method, TransError> {
|
||||||
match nom_result {
|
match nom_result {
|
||||||
Ok(([], method)) => Ok(method),
|
Ok(([], method)) => Ok(method),
|
||||||
Ok((_, _)) => {
|
Ok((_, _)) => {
|
||||||
Err(
|
Err(ConException::SyntaxError(vec!["could not consume all input".to_string()]).into())
|
||||||
ConException::SyntaxError(vec!["could not consume all input".to_string()])
|
|
||||||
.into_trans(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Err(nom::Err::Incomplete(_)) => {
|
Err(nom::Err::Incomplete(_)) => {
|
||||||
Err(
|
Err(ConException::SyntaxError(vec!["there was not enough data".to_string()]).into())
|
||||||
ConException::SyntaxError(vec!["there was not enough data".to_string()])
|
|
||||||
.into_trans(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Err(nom::Err::Failure(err) | nom::Err::Error(err)) => Err(err),
|
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 crate::methods::generated::parse::IResult;
|
||||||
|
use amqp_core::error::{ConException, ProtocolError};
|
||||||
use amqp_core::methods::{
|
use amqp_core::methods::{
|
||||||
Bit, FieldValue, Long, Longlong, Longstr, Octet, Short, Shortstr, Table, TableFieldName,
|
Bit, FieldValue, Long, Longlong, Longstr, Octet, Short, Shortstr, Table, TableFieldName,
|
||||||
Timestamp,
|
Timestamp,
|
||||||
|
|
@ -15,7 +16,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
impl<T> nom::error::ParseError<T> for TransError {
|
impl<T> nom::error::ParseError<T> for TransError {
|
||||||
fn from_error_kind(_input: T, _kind: ErrorKind) -> Self {
|
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 {
|
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 msg = msg.into();
|
||||||
let stack = match err {
|
let stack = match err {
|
||||||
Err::Error(e) | Err::Failure(e) => match e {
|
Err::Error(e) | Err::Failure(e) => match e {
|
||||||
TransError::Invalid(ProtocolError::ConException(ConException::SyntaxError(
|
TransError::Protocol(ProtocolError::ConException(ConException::SyntaxError(
|
||||||
mut stack,
|
mut stack,
|
||||||
))) => {
|
))) => {
|
||||||
stack.push(msg);
|
stack.push(msg);
|
||||||
|
|
@ -38,20 +39,20 @@ pub fn fail_err<S: Into<String>>(msg: S) -> impl FnOnce(Err<TransError>) -> Err<
|
||||||
},
|
},
|
||||||
_ => vec![msg],
|
_ => 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> {
|
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_export]
|
||||||
macro_rules! fail {
|
macro_rules! fail {
|
||||||
($cause:expr) => {
|
($cause:expr) => {
|
||||||
return Err(nom::Err::Failure(
|
return Err(nom::Err::Failure(
|
||||||
crate::error::ProtocolError::ConException(crate::error::ConException::SyntaxError(
|
::amqp_core::error::ProtocolError::ConException(
|
||||||
vec![String::from($cause)],
|
::amqp_core::error::ConException::SyntaxError(vec![String::from($cause)]),
|
||||||
))
|
)
|
||||||
.into(),
|
.into(),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
//!
|
//!
|
||||||
//! Currently only supports PLAIN (see [RFC 4616](https://datatracker.ietf.org/doc/html/rfc4616))
|
//! 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 struct PlainUser {
|
||||||
pub authorization_identity: String,
|
pub authorization_identity: String,
|
||||||
|
|
@ -13,17 +14,11 @@ pub struct PlainUser {
|
||||||
pub fn parse_sasl_plain_response(response: &[u8]) -> Result<PlainUser> {
|
pub fn parse_sasl_plain_response(response: &[u8]) -> Result<PlainUser> {
|
||||||
let mut parts = response
|
let mut parts = response
|
||||||
.split(|&n| n == 0)
|
.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
|
let authorization_identity = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||||
.next()
|
let authentication_identity = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
let password = parts.next().ok_or_else(|| ConException::Todo)??;
|
||||||
let authentication_identity = parts
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
|
||||||
let password = parts
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ConException::Todo.into_trans())??;
|
|
||||||
|
|
||||||
Ok(PlainUser {
|
Ok(PlainUser {
|
||||||
authorization_identity,
|
authorization_identity,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { connectAmqp, sleep } from './utils/utils.js';
|
import { connectAmqp } from './utils/utils.js';
|
||||||
|
|
||||||
const connection = await connectAmqp();
|
const connection = await connectAmqp();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ pub fn main() -> Result<()> {
|
||||||
|
|
||||||
let mut amqp_server = Command::new("cargo")
|
let mut amqp_server = Command::new("cargo")
|
||||||
.arg("run")
|
.arg("run")
|
||||||
|
.env("RUST_LOG", "trace")
|
||||||
.spawn()
|
.spawn()
|
||||||
.context("`cargo run` amqp")?;
|
.context("`cargo run` amqp")?;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue