Skip to main content

fe2o3_amqp/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![deny(missing_docs, missing_debug_implementations)]
3#![warn(clippy::unused_async)]
4
5//! A rust implementation of AMQP 1.0 protocol based on serde and tokio.
6//!
7//! [![crate_version](https://img.shields.io/crates/v/fe2o3-amqp.svg?style=flat)](https://crates.io/crates/fe2o3-amqp)
8//! [![docs_version](https://img.shields.io/badge/docs-latest-blue.svg?style=flat)](https://docs.rs/fe2o3-amqp/latest/fe2o3_amqp/)
9//! [![discord](https://img.shields.io/discord/1016422034592497665?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2")](https://discord.gg/YMkaETwnFW)
10//!
11//! - [Quick Start](#quick-start)
12//! - [Documentation](https://docs.rs/fe2o3-amqp)
13//! - [Changelog](https://github.com/minghuaw/fe2o3-amqp/blob/main/fe2o3-amqp/Changelog.md)
14//! - [Examples](https://github.com/minghuaw/fe2o3-amqp/tree/main/examples)
15//!
16//! # Feature flags
17//!
18//! ```toml
19//! default = []
20//! ```
21//!
22//! | Feature | Description |
23//! |---------|-------------|
24//! |`"rustls"`| enables TLS integration with `tokio-rustls` and `rustls` |
25//! |`"native-tls"`| enables TLS integration with `tokio-native-tls` and `native-tls`|
26//! |`"acceptor"`| enables `ConnectionAcceptor`, `SessionAcceptor`, and `LinkAcceptor`|
27//! |`"transaction"`| enables `Controller`, `Transaction`, `OwnedTransaction` and `control_link_acceptor` |
28//! |`"scram"`| enables SCRAM auth |
29//! |`"tracing"`| enables logging with `tracing` |
30//! |`"log"`| enables logging with `log` |
31//!
32//! ## The crypto provider for `"rustls"`
33//!
34//! This crate does not name a crypto provider. It takes the default features of
35//! `rustls`, so the provider follows the `rustls` default. That default is
36//! `aws-lc-rs`.
37//!
38//! To use a different provider, install it with
39//! `rustls::crypto::CryptoProvider::install_default` and supply your own
40//! `tokio_rustls::TlsConnector` to the connection builder.
41//!
42//! The default features also include `prefer-post-quantum`. A client therefore
43//! sends an `X25519MLKEM768` key share in the first ClientHello. To send an
44//! `X25519` key share instead, build the config with
45//! `ClientConfig::builder_with_provider` and pass a `CryptoProvider` whose
46//! `kx_groups` field starts with `X25519`. A plain `ClientConfig::builder()` does
47//! not change the order, because it takes the order from the default provider.
48//!
49//! Neither TLS feature does anything on a `wasm32` target. See [WebAssembly
50//! support](#webassembly-support).
51//!
52//! # Quick start
53//!
54//! 1. [Client](#client)
55//! 2. [Listener](#listener)
56//! 3. [WebSocket binding](#websocket)
57//!
58//! More examples including one showing how to use it with Azure Service Bus can be found on the
59//! [GitHub repo](https://github.com/minghuaw/fe2o3-amqp/tree/main/examples).
60//!
61//! ## Client
62//!
63//! Below is an example with a local broker
64//! ([`TestAmqpBroker`](https://github.com/Azure/amqpnetlite/releases/download/test_broker.1609/TestAmqpBroker.zip))
65//! listening on the localhost. The broker is executed with the following command
66//!
67//! ```powershell
68//! ./TestAmqpBroker.exe amqp://localhost:5672 /creds:guest:guest /queues:q1
69//! ```
70//!
71//! The following code requires the [`tokio`] async runtime added to the dependencies.
72//!
73//! ```rust,no_run
74//! use fe2o3_amqp::{Connection, Session, Sender, Receiver};
75//! use fe2o3_amqp::types::messaging::Outcome;
76//!
77//! #[tokio::main]
78//! async fn main() {
79//!     let mut connection = Connection::open(
80//!         "connection-1",                     // container id
81//!         "amqp://guest:guest@localhost:5672" // url
82//!     ).await.unwrap();
83//!
84//!     let mut session = Session::begin(&mut connection).await.unwrap();
85//!
86//!     // Create a sender
87//!     let mut sender = Sender::attach(
88//!         &mut session,           // Session
89//!         "rust-sender-link-1",   // link name
90//!         "q1"                    // target address
91//!     ).await.unwrap();
92//!
93//!     // Create a receiver
94//!     let mut receiver = Receiver::attach(
95//!         &mut session,
96//!         "rust-receiver-link-1", // link name
97//!         "q1"                    // source address
98//!     ).await.unwrap();
99//!
100//!     // Send a message to the broker and wait for outcome (Disposition)
101//!     let outcome: Outcome = sender.send("hello AMQP").await.unwrap();
102//!     outcome.accepted_or_else(|state| state).unwrap(); // Handle delivery outcome
103//!
104//!     // Send a message with batchable field set to true
105//!     let fut = sender.send_batchable("hello batchable AMQP").await.unwrap();
106//!     let outcome: Outcome = fut.await.unwrap(); // Wait for outcome (Disposition)
107//!     outcome.accepted_or_else(|state| state).unwrap(); // Handle delivery outcome
108//!
109//!     // Receive the message from the broker
110//!     let delivery = receiver.recv::<String>().await.unwrap();
111//!     receiver.accept(&delivery).await.unwrap();
112//!
113//!     sender.close().await.unwrap(); // Detach sender with closing Detach performatives
114//!     receiver.close().await.unwrap(); // Detach receiver with closing Detach performatives
115//!     session.end().await.unwrap(); // End the session
116//!     connection.close().await.unwrap(); // Close the connection
117//! }
118//! ```
119//!
120//! ## Listener
121//!
122//! ```rust,no_run
123//! use tokio::net::TcpListener;
124//! use fe2o3_amqp::acceptor::{ConnectionAcceptor, SessionAcceptor, LinkAcceptor, LinkEndpoint};
125//!
126//! #[tokio::main]
127//! async fn main() {
128//!     let tcp_listener = TcpListener::bind("localhost:5672").await.unwrap();
129//!     let connection_acceptor = ConnectionAcceptor::new("example-listener");
130//!
131//!     while let Ok((stream, addr)) = tcp_listener.accept().await {
132//!         let mut connection = connection_acceptor.accept(stream).await.unwrap();
133//!         let handle = tokio::spawn(async move {
134//!             let session_acceptor = SessionAcceptor::new();
135//!             while let Ok(mut session) = session_acceptor.accept(&mut connection).await{
136//!                 let handle = tokio::spawn(async move {
137//!                     let link_acceptor = LinkAcceptor::new();
138//!                     match link_acceptor.accept(&mut session).await.unwrap() {
139//!                         LinkEndpoint::Sender(sender) => { },
140//!                         LinkEndpoint::Receiver(recver) => { },
141//!                     }
142//!                 });
143//!             }
144//!         });
145//!     }
146//! }
147//! ```
148//!
149//! ## WebSocket
150//!
151//! [`fe2o3-amqp-ws`](https://crates.io/crates/fe2o3-amqp-ws) is needed for WebSocket binding
152//!
153//! ```rust,ignore
154//! use fe2o3_amqp::{
155//!     types::{messaging::Outcome, primitives::Value},
156//!     Connection, Delivery, Receiver, Sender, Session,
157//! };
158//! use fe2o3_amqp_ws::WebSocketStream;
159//!
160//! #[tokio::main]
161//! async fn main() {
162//!     let (ws_stream, _response) = WebSocketStream::connect("ws://localhost:5673")
163//!         .await
164//!         .unwrap();
165//!     let mut connection = Connection::builder()
166//!         .container_id("connection-1")
167//!         .open_with_stream(ws_stream)
168//!         .await
169//!         .unwrap();
170//!
171//!     connection.close().await.unwrap();
172//! }
173//! ```
174//!
175//! # More examples
176//!
177//! More examples of sending and receiving can be found on the [GitHub
178//! repo](https://github.com/minghuaw/fe2o3-amqp/tree/main/examples/). Please note that most
179//! examples requires a local broker running. One broker that can be used on Windows is
180//! [TestAmqpBroker](https://azure.github.io/amqpnetlite/articles/hello_amqp.html).
181//!
182//! # WebAssembly support
183//!
184//! Experimental support for `wasm32-unknown-unknown` target is added since "0.8.11" and requires use of
185//! `fe2o3-amqp-ws` to establish WebSocket connection to the broker. An example of sending and
186//! receiving message in a browser tab can be found
187//! [examples/wasm32-in-browser](https://github.com/minghuaw/fe2o3-amqp/tree/main/examples/wasm32-in-browser).
188//!
189//! The `"rustls"` and `"native-tls"` features do nothing on a `wasm32` target. A browser
190//! cannot open a raw socket, so it terminates TLS itself. Use a `wss://` URL with
191//! `fe2o3-amqp-ws` to get an encrypted connection. If you enable a TLS feature and then
192//! open an `amqps://` URL on `wasm32`, the call returns
193//! [`connection::OpenError::TlsConnectorNotFound`].
194//!
195//! # Components
196//!
197//! | Name | Description |
198//! |------|-------------|
199//! |`serde_amqp_derive`| Custom derive macro for described types as defined in AMQP1.0 protocol |
200//! |`serde_amqp`| AMQP1.0 serializer and deserializer as well as primitive types |
201//! |`fe2o3-amqp-types`| AMQP1.0 data types |
202//! |`fe2o3-amqp`| Implementation of AMQP1.0 `Connection`, `Session`, and `Link` |
203//! |`fe2o3-amqp-ext`| Extension types and implementations |
204//! |`fe2o3-amqp-ws` | WebSocket binding for `fe2o3-amqp` transport |
205//! |`fe2o3-amqp-management`| Experimental implementation of AMQP1.0 management |
206//! |`fe2o3-amqp-cbs`| Experimental implementation of AMQP1.0 CBS |
207//!
208//! # Minimum rust version supported
209//!
210//! 1.85.0
211
212#[macro_use]
213mod macros;
214
215pub(crate) mod control;
216pub(crate) mod endpoint;
217pub(crate) mod util;
218
219pub mod auth;
220pub mod connection;
221pub mod frames;
222pub mod link;
223pub mod sasl_profile;
224pub mod session;
225pub mod transport;
226
227cfg_acceptor! {
228    pub mod acceptor;
229}
230
231cfg_transaction! {
232    pub mod transaction;
233}
234
235pub mod types {
236    //! Re-exporting `fe2o3-amqp-types`
237    pub use fe2o3_amqp_types::*;
238}
239
240pub use connection::Connection;
241pub use link::{
242    delivery::{Delivery, Sendable},
243    Receiver, ReceiverDisposer, Sender,
244};
245pub use session::Session;
246
247type Payload = bytes::Bytes;
248
249cfg_not_wasm32! {
250    /// A marker trait to indicate that the type is `Send` bound in non-wasm32 targets
251    pub trait SendBound: Send {}
252    impl<T> SendBound for T where T: Send {}
253}
254
255cfg_wasm32! {
256    /// A marker trait that is implemented for all types in wasm32 targets
257    pub trait SendBound {}
258    impl<T> SendBound for T {}
259}