]> git.lizzy.rs Git - connect-rs.git/commitdiff
improve documentation and logging
authorSachandhan Ganesh <sachan.ganesh@gmail.com>
Sun, 14 Feb 2021 20:37:14 +0000 (12:37 -0800)
committerSachandhan Ganesh <sachan.ganesh@gmail.com>
Sun, 14 Feb 2021 21:50:27 +0000 (13:50 -0800)
Cargo.toml
README.md
examples/tcp-client-blaster/src/main.rs
src/lib.rs
src/reader.rs
src/writer.rs

index 7e6631d2993186f5ddfcbac70e7c6b302572bbfc..f970a8652cfdba11b53d4cd803ac1e6f004a6123 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "connect"
-version = "0.2.1"
+version = "0.2.2"
 edition = "2018"
 authors = ["Sachandhan Ganesh <sachan.ganesh@gmail.com>"]
 description = "message queue abstraction over async network streams"
index 65b42dcb7e51d9cd0ab30c12d50d95cc5ee92e07..418f5e23c289bee9f06322103d59f9d4ffaef3d6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -8,19 +8,75 @@
 [docs-badge]: https://docs.rs/connect/badge.svg
 [docs-url]: https://docs.rs/connect
 
-This Rust crate provides a simple, brokerless message-queue abstraction over asynchronous network
-streams.
+This Rust crate provides a simple, brokerless message-queue abstraction over asynchronous
+network streams. It guarantees ordered message delivery and reception, and both TCP and TLS
+transports are supported.
 
 ## Examples
-Please use the [example programs](https://github.com/sachanganesh/connect-rs/tree/main/examples)
-provided to help understand crate usage.
+
+````rust
+// create a client connection to the server
+let mut conn = Connection::tcp_client(ip_address).await?;
+
+// construct a new message
+let msg = String::from("Hello world!");
+let envelope: ConnectDatagram = ConnectDatagram::new(65535, msg.into_bytes())?;
+
+// send a message to the server
+conn.writer().send(envelope).await?;
+
+// wait for the echo-server to reply with an echo
+if let Some(mut envelope) = conn.reader().next().await {
+    // take the message payload from the envelope
+    let data: Vec<u8> = envelope.take_data().unwrap();
+
+    // reconstruct the original message
+    let msg = String::from_utf8(data)?;
+    assert_eq!("Hello world!", msg.as_str());
+}
+````
+
+In addition to the [crate documentation](https://docs.rs/connect/latest/connect/), please use
+the provided [example programs](https://github.com/sachanganesh/connect-rs/tree/main/examples)
+as a practical reference for crate usage.
+
+- TCP
+    - [TCP Echo Server](https://github.com/sachanganesh/connect-rs/tree/main/examples/tcp-echo-server)
+    - [TCP Client](https://github.com/sachanganesh/connect-rs/tree/main/examples/tcp-client)
+- TLS
+    - [TLS Echo Server](https://github.com/sachanganesh/connect-rs/tree/main/examples/tls-echo-server)
+    - [TLS Client](https://github.com/sachanganesh/connect-rs/tree/main/examples/tls-client)
 
 ## Why?
+
 When building networked applications, developers shouldn't have to focus on repeatedly solving
-the problem of reliable, fault-tolerant message delivery over byte-streams. By using a message
+the problem of reliable, ordered message delivery over byte-streams. By using a message
 queue abstraction, crate users can focus on core application logic and leave the low-level
 networking and message-queue guarantees to the abstraction.
 
+Connect provides a `ConnectionWriter` and `ConnectionReader` interface to concurrently send
+and receive messages over a network connection. Each user-provided message is prefixed by 8
+bytes, containing a size-prefix (4 bytes), version tag (2 bytes), and recipient tag (2 bytes).
+The size-prefix and version tag are used internally to deserialize messages received from the
+network connection. The recipient tag is intended for crate users to identify the message
+recipient, although the library leaves that up to the user's discretion.
+
+Library users must serialize their custom messages into bytes (`Vec<u8>`), prior to
+constructing a `ConnectDatagram`, which can then be passed to a `ConnectionWriter`.
+Consequently, `ConnectionReader`s will return `ConnectDatagram`s containing the message payload
+(`Vec<u8>` again) to the user to deserialize.
+
+Requiring crate users to serialize data before constructing a datagram may appear redundant, but
+gives the developer the freedom to use a serialization format of their choosing. This means that
+library users can do interesting things such as:
+
+- Use the recipient tag to signify which serialization format was used for that message
+- Use the recipient tag to signify the type of message being sent
+
+## Contributing
+
+This crate gladly accepts contributions. Don't hesitate to open issues or PRs.
+
 ## Feature Status
 
 | Feature                                              | Status        |
index d93b85e34be792737185cc73aaf8622420ecbb05..d68ad7a2715bf4f476a0eb27fd05991183404fdb 100644 (file)
@@ -54,7 +54,7 @@ async fn main() -> anyhow::Result<()> {
 
     // send messages to the server
     for i in 0..NUM_MESSAGES {
-        // info!("Sending message: {}", i);
+        info!("Sending message: {}", i);
         let data = i.to_be_bytes().to_vec();
         let envelope = ConnectDatagram::new(i, data)?;
         writer.send(envelope).await?;
index b3c3232504eda596d25d1227fd4e4b7a0b82d975..b99dd986ef6b9c5189b54edd59e990f4cbe8689c 100644 (file)
@@ -1,16 +1,68 @@
-//! This crate provides a simple, brokerless message-queue abstraction over asynchronous network
-//! streams.
+//! This Rust crate provides a simple, brokerless message-queue abstraction over asynchronous
+//! network streams. It guarantees ordered message delivery and reception, and both TCP and TLS
+//! transports are supported.
 //!
 //! # Examples
-//! Please use the [example programs](https://github.com/sachanganesh/connect-rs/tree/main/examples)
-//! provided to help understand crate usage.
+//!
+//! ````ignore
+//! // create a client connection to the server
+//! let mut conn = Connection::tcp_client(ip_address).await?;
+//!
+//! // construct a new message
+//! let msg = String::from("Hello world!");
+//! let envelope: ConnectDatagram = ConnectDatagram::new(65535, msg.into_bytes())?;
+//!
+//! // send a message to the server
+//! conn.writer().send(envelope).await?;
+//!
+//! // wait for the echo-server to reply with an echo
+//! if let Some(mut envelope) = conn.reader().next().await {
+//!     // take the message payload from the envelope
+//!     let data: Vec<u8> = envelope.take_data().unwrap();
+//!
+//!     // reconstruct the original message
+//!     let msg = String::from_utf8(data)?;
+//!     assert_eq!("Hello world!", msg.as_str());
+//! }
+//! ````
+//!
+//! In addition to the [crate documentation](https://docs.rs/connect/latest/connect/), please use
+//! the provided [example programs](https://github.com/sachanganesh/connect-rs/tree/main/examples)
+//! as a practical reference for crate usage.
+//!
+//! - TCP
+//!     - [TCP Echo Server](https://github.com/sachanganesh/connect-rs/tree/main/examples/tcp-echo-server)
+//!     - [TCP Client](https://github.com/sachanganesh/connect-rs/tree/main/examples/tcp-client)
+//! - TLS
+//!     - [TLS Echo Server](https://github.com/sachanganesh/connect-rs/tree/main/examples/tls-echo-server)
+//!     - [TLS Client](https://github.com/sachanganesh/connect-rs/tree/main/examples/tls-client)
 //!
 //! # Why?
+//!
 //! When building networked applications, developers shouldn't have to focus on repeatedly solving
-//! the problem of reliable, fault-tolerant message delivery over byte-streams. By using a message
+//! the problem of reliable, ordered message delivery over byte-streams. By using a message
 //! queue abstraction, crate users can focus on core application logic and leave the low-level
 //! networking and message-queue guarantees to the abstraction.
 //!
+//! Connect provides a `ConnectionWriter` and `ConnectionReader` interface to concurrently send
+//! and receive messages over a network connection. Each user-provided message is prefixed by 8
+//! bytes, containing a size-prefix (4 bytes), version tag (2 bytes), and recipient tag (2 bytes).
+//! The size-prefix and version tag are used internally to deserialize messages received from the
+//! network connection. The recipient tag is intended for crate users to identify the message
+//! recipient, although the library leaves that up to the user's discretion.
+//!
+//! Library users must serialize their custom messages into bytes (`Vec<u8>`), prior to
+//! constructing a `ConnectDatagram`, which can then be passed to a `ConnectionWriter`.
+//! Consequently, `ConnectionReader`s will return `ConnectDatagram`s containing the message payload
+//! (`Vec<u8>` again) to the user to deserialize.
+//!
+//! Requiring crate users to serialize data before constructing a datagram may appear redundant, but
+//! gives the developer the freedom to use a serialization format of their choosing. This means that
+//! library users can do interesting things such as:
+//!
+//! - Use the recipient tag to signify which serialization format was used for that message
+//! - Use the recipient tag to signify the type of message being sent
+//!
 
 #![feature(doc_cfg)]
 
index 3954c4eee7ac3a22a03f34b82386e00da68e87cb..1e9c03155e6ef63e6268fd35ddc6f2aed0086048 100644 (file)
@@ -14,7 +14,7 @@ const BUFFER_SIZE: usize = 8192;
 
 /// An interface to read messages from the network connection.
 ///
-/// Implements the [`Stream`] trait to asynchronously read messages from the network connection.
+/// Implements the `Stream` trait to asynchronously read messages from the network connection.
 ///
 /// # Example
 ///
@@ -72,13 +72,13 @@ impl ConnectionReader {
         self.peer_addr.clone()
     }
 
-    /// Check if the [`Stream`] of messages from the network is closed.
+    /// Check if the `Stream` of messages from the network is closed.
     pub fn is_closed(&self) -> bool {
         self.closed
     }
 
     pub(crate) fn close_stream(&mut self) {
-        trace!("closing the stream for connection with {}", self.peer_addr);
+        debug!("Closing the stream for connection with {}", self.peer_addr);
         self.buffer.take();
         self.pending_datagram.take();
         self.pending_read.take();
index 87ad3e6a029c93b1b6069a48832ebffa8a74d3e9..57dd4a275ec14e0c9f7a37c685fe6695a176fe8c 100644 (file)
@@ -36,7 +36,7 @@ impl std::fmt::Display for ConnectionWriteError {
 
 /// An interface to write messages to the network connection.
 ///
-/// Implements the [`Sink`] trait to asynchronously write messages to the network connection.
+/// Implements the `Sink` trait to asynchronously write messages to the network connection.
 ///
 /// # Example
 ///
@@ -84,7 +84,7 @@ impl ConnectionWriter {
         self.peer_addr.clone()
     }
 
-    /// Check if the [`Sink`] of messages to the network is closed.
+    /// Check if the `Sink` of messages to the network is closed.
     pub fn is_closed(&self) -> bool {
         self.closed
     }
@@ -165,6 +165,7 @@ impl Sink<ConnectDatagram> for ConnectionWriter {
 
     fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
         self.closed = true;
+        debug!("Closing the sink for connection with {}", self.peer_addr);
 
         match self.write_pending_bytes(cx) {
             Poll::Pending => Poll::Pending,