From e47667156d438b348f7af4773c74808b810a9d42 Mon Sep 17 00:00:00 2001 From: Ondrej Babec Date: Thu, 5 May 2022 07:47:07 +0200 Subject: [PATCH] Update documentation --- src/client/client.rs | 31 +++++++++++++++++++++++++++++-- src/client/client_config.rs | 18 ++++++++++++++++-- src/network/mod.rs | 8 +++++++- src/tokio_net/tokio_network.rs | 4 ++++ src/utils/buffer_writer.rs | 17 +++++++++++++++++ 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/client/client.rs b/src/client/client.rs index 8a948eb..b88b418 100644 --- a/src/client/client.rs +++ b/src/client/client.rs @@ -141,6 +141,10 @@ where } } + /// Method allows client connect to server. Client is connecting to the specified broker + /// in the `ClientConfig`. Method selects proper implementation of the MQTT version based on the config. + /// If the connection to the broker fails, method returns Err variable that contains + /// Reason codes returned from the broker. pub async fn connect_to_broker<'b>(&'b mut self) -> Result<(), ReasonCode> { match self.config.mqtt_version { MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), @@ -175,6 +179,10 @@ where Ok(()) } + /// Method allows client disconnect from the server. Client disconnects from the specified broker + /// in the `ClientConfig`. Method selects proper implementation of the MQTT version based on the config. + /// If the disconnect from the broker fails, method returns Err variable that contains + /// Reason codes returned from the broker. pub async fn disconnect<'b>(&'b mut self) -> Result<(), ReasonCode> { match self.config.mqtt_version { MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), @@ -242,7 +250,10 @@ where } Ok(()) } - + /// Method allows sending message to broker specified from the ClientConfig. Client sends the + /// message from the parameter `message` to the topic `topic_name` on the broker + /// specified in the ClientConfig. If the send fails method returns Err with reason code + /// received by broker. pub async fn send_message<'b>( &'b mut self, topic_name: &'b str, @@ -314,6 +325,10 @@ where Ok(()) } + /// Method allows client subscribe to multiple topics specified in the parameter + /// `topic_names` on the broker specified in the `ClientConfig`. Generics `TOPICS` + /// sets the value of the `topics_names` vector. MQTT protocol implementation + /// is selected automatically. pub async fn subscribe_to_topics<'b, const TOPICS: usize>( &'b mut self, topic_names: &'b Vec<&'b str, TOPICS>, @@ -324,6 +339,9 @@ where } } + /// Method allows client unsubscribe from the topic specified in the parameter + /// `topic_name` on the broker from the `ClientConfig`. MQTT protocol implementation + /// is selected automatically. pub async fn unsubscribe_from_topic<'b>( &'b mut self, topic_name: &'b str, @@ -334,7 +352,7 @@ where } } - pub async fn unsubscribe_from_topic_v5<'b>( + async fn unsubscribe_from_topic_v5<'b>( &'b mut self, topic_name: &'b str, ) -> Result<(), ReasonCode> { @@ -422,6 +440,9 @@ where } } + /// Method allows client subscribe to multiple topics specified in the parameter + /// `topic_name` on the broker specified in the `ClientConfig`. MQTT protocol implementation + /// is selected automatically. pub async fn subscribe_to_topic<'b>( &'b mut self, topic_name: &'b str, @@ -471,6 +492,9 @@ where return Ok(packet.message.unwrap()); } + /// Method allows client receive a message. The work of this method strictly depends on the + /// network implementation passed in the `ClientConfig`. It expects the PUBLISH packet + /// from the broker. pub async fn receive_message<'b>(&'b mut self) -> Result<&'b [u8], ReasonCode> { match self.config.mqtt_version { MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), @@ -505,6 +529,9 @@ where } } + /// Method allows client send PING message to the broker specified in the `ClientConfig`. + /// If there is expectation for long running connection. Method should be executed + /// regularly by the timer that counts down the session expiry interval. pub async fn send_ping<'b>(&'b mut self) -> Result<(), ReasonCode> { match self.config.mqtt_version { MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), diff --git a/src/client/client_config.rs b/src/client/client_config.rs index 45b5417..304a5f8 100644 --- a/src/client/client_config.rs +++ b/src/client/client_config.rs @@ -34,7 +34,16 @@ pub enum MqttVersion { MQTTv3, MQTTv5, } - +/// Client config is main configuration for the `MQTTClient` structure. +/// All of the properties are optional if they are not set they are not gonna +/// be used. Configuration contains also MQTTv5 properties. Generic constant +/// `MAX_PROPERTIES` sets the length for the properties Vec. User can insert +/// all the properties and client will automatically use variables that are +/// usable for the specific packet types. `mqtt_version` sets the version +/// of the MQTT protocol that is gonna be used. Config also expects the rng +/// implementation. This implementation is used for generating packet identifiers. +/// There is counting rng implementation in the `utils` module that can be used. +/// Examples of the configurations can be found in the integration tests. #[derive(Clone)] pub struct ClientConfig<'a, const MAX_PROPERTIES: usize, T: RngCore> { pub qos: QualityOfService, @@ -69,6 +78,8 @@ impl<'a, const MAX_PROPERTIES: usize, T: RngCore> ClientConfig<'a, MAX_PROPERTIE self.qos = qos; } + /// Method adds the username array and also sets the username flag so client + /// will use it for the authentication pub fn add_username(&mut self, username: &'a str) { let mut username_s: EncodedString = EncodedString::new(); username_s.string = username; @@ -76,7 +87,8 @@ impl<'a, const MAX_PROPERTIES: usize, T: RngCore> ClientConfig<'a, MAX_PROPERTIE self.username_flag = true; self.username = username_s; } - + /// Method adds the password array and also sets the password flag so client + /// will use it for the authentication pub fn add_password(&mut self, password: &'a str) { let mut password_s: BinaryData = BinaryData::new(); password_s.bin = password.as_bytes(); @@ -85,12 +97,14 @@ impl<'a, const MAX_PROPERTIES: usize, T: RngCore> ClientConfig<'a, MAX_PROPERTIE self.password_flag = true; } + /// Method adds the property to the properties Vec if there is still space. Otherwise do nothing. pub fn add_property(&mut self, prop: Property<'a>) { if self.properties.len() < MAX_PROPERTIES { self.properties.push(prop); } } + /// Method encode the `max_packet_size` attribute as property to the properties Vec. pub fn add_max_packet_size_as_prop(&mut self) -> u32 { if self.properties.len() < MAX_PROPERTIES { let prop = Property::MaximumPacketSize(self.max_packet_size); diff --git a/src/network/mod.rs b/src/network/mod.rs index 13b1c13..e7f82d8 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -34,7 +34,8 @@ pub enum NetworkError { IDNotMatchedOnAck, NoMatchingSubs, } - +/// NetworkConnectionFactory implementation should create a TCP connection and return +/// the `Connection` trait implementation. Otherwise return `ReasonCode`. pub trait NetworkConnectionFactory: Sized { type Connection: NetworkConnection; @@ -42,9 +43,11 @@ pub trait NetworkConnectionFactory: Sized { where Self: 'm; + /// Connect function estabilish TCP connection and return the `Connection`. fn connect<'m>(&'m mut self, ip: [u8; 4], port: u16) -> Self::ConnectionFuture<'m>; } +/// Network connection represents estabilished TCP connection created with `NetworkConnectionFactory`. pub trait NetworkConnection { type SendFuture<'m>: Future> where @@ -56,9 +59,12 @@ pub trait NetworkConnection { type CloseFuture<'m>: Future>; + /// Send function should enable sending the data from `buffer` via TCP connection. fn send<'m>(&'m mut self, buffer: &'m [u8]) -> Self::SendFuture<'m>; + /// Receive should enable receiving data to the `buffer` from TCP connection. fn receive<'m>(&'m mut self, buffer: &'m mut [u8]) -> Self::ReceiveFuture<'m>; + /// Close function should close the TCP connection. fn close<'m>(self) -> Self::CloseFuture<'m>; } diff --git a/src/tokio_net/tokio_network.rs b/src/tokio_net/tokio_network.rs index 3a3e9ef..be83fa6 100644 --- a/src/tokio_net/tokio_network.rs +++ b/src/tokio_net/tokio_network.rs @@ -34,6 +34,8 @@ use tokio::net::TcpStream; use crate::network::{NetworkConnection, NetworkConnectionFactory}; use crate::packet::v5::reason_codes::ReasonCode; +/// TokioNetwork is an implementation of the `NetworkConnection` trait. This implementation +/// allows communication through the `Tokio` TcpStream. pub struct TokioNetwork { stream: TcpStream, } @@ -86,6 +88,8 @@ impl NetworkConnection for TokioNetwork { } } +/// TokioNetworkFactory is an implementation of the `NetworkConnectionFactory` trait. This implementation +/// allows to establish the `Tokio` TcpStream connection. pub struct TokioNetworkFactory {} impl TokioNetworkFactory { diff --git a/src/utils/buffer_writer.rs b/src/utils/buffer_writer.rs index 5738ccc..316b695 100644 --- a/src/utils/buffer_writer.rs +++ b/src/utils/buffer_writer.rs @@ -28,6 +28,8 @@ use crate::encoding::variable_byte_integer::{VariableByteInteger, VariableByteIn use crate::packet::v5::property::Property; use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair, TopicFilter}; +/// Buff writer is writing corresponding types to buffer (Byte array) and stores current position +/// (later as cursor) pub struct BuffWriter<'a> { buffer: &'a mut [u8], pub position: usize, @@ -47,6 +49,7 @@ impl<'a> BuffWriter<'a> { self.position = self.position + increment; } + /// Returns n-th Byte from the buffer to which is currently written. pub fn get_n_byte(&mut self, n: usize) -> u8 { if self.position >= n { return self.buffer[n]; @@ -54,6 +57,7 @@ impl<'a> BuffWriter<'a> { return 0; } + /// Return the remaining lenght of the packet from the buffer to which is packet written. pub fn get_rem_len(&mut self) -> Result { let max = if self.position >= 5 { 4 @@ -77,6 +81,7 @@ impl<'a> BuffWriter<'a> { } } + /// Writes an array to the buffer. pub fn insert_ref(&mut self, len: usize, array: &[u8]) -> Result<(), BufferError> { let mut x: usize = 0; if self.position + len > self.len { @@ -95,6 +100,7 @@ impl<'a> BuffWriter<'a> { return Ok(()); } + /// Writes a single Byte to the buffer. pub fn write_u8(&mut self, byte: u8) -> Result<(), BufferError> { return if self.position >= self.len { Err(BufferError::InsufficientBufferSize) @@ -105,16 +111,19 @@ impl<'a> BuffWriter<'a> { }; } + /// Writes the two Byte value to the buffer. pub fn write_u16(&mut self, two_bytes: u16) -> Result<(), BufferError> { let bytes: [u8; 2] = two_bytes.to_be_bytes(); return self.insert_ref(2, &bytes); } + /// Writes the four Byte value to the buffer. pub fn write_u32(&mut self, four_bytes: u32) -> Result<(), BufferError> { let bytes: [u8; 4] = four_bytes.to_be_bytes(); return self.insert_ref(4, &bytes); } + /// Writes the UTF-8 string type to the buffer. pub fn write_string_ref(&mut self, str: &EncodedString<'a>) -> Result<(), BufferError> { self.write_u16(str.len)?; if str.len != 0 { @@ -124,16 +133,19 @@ impl<'a> BuffWriter<'a> { return Ok(()); } + /// Writes BinaryData to the buffer. pub fn write_binary_ref(&mut self, bin: &BinaryData<'a>) -> Result<(), BufferError> { self.write_u16(bin.len)?; return self.insert_ref(bin.len as usize, bin.bin); } + /// Writes the string pair to the buffer. pub fn write_string_pair_ref(&mut self, str_pair: &StringPair<'a>) -> Result<(), BufferError> { self.write_string_ref(&str_pair.name)?; return self.write_string_ref(&str_pair.value); } + /// Encodes the u32 value into the VariableByteInteger and this value writes to the buffer. pub fn write_variable_byte_int(&mut self, int: u32) -> Result<(), BufferError> { let x: VariableByteInteger = VariableByteIntegerEncoder::encode(int)?; let len = VariableByteIntegerEncoder::len(x); @@ -146,6 +158,7 @@ impl<'a> BuffWriter<'a> { return property.encode(self); } + /// Writes all properties from the `properties` Vec into the buffer. pub fn write_properties( &mut self, properties: &Vec, LEN>, @@ -165,6 +178,8 @@ impl<'a> BuffWriter<'a> { Ok(()) } + /// Writes the MQTT `TopicFilter` into the buffer. If the `sub` option is set to `false`, it will + /// not write the `sub_options` only topic name. fn write_topic_filter_ref( &mut self, sub: bool, @@ -177,6 +192,8 @@ impl<'a> BuffWriter<'a> { return Ok(()); } + /// Writes the topic filter Vec to the buffer. If the `sub` option is set to `false`, it will not + /// write the `sub_options` only topic names. pub fn write_topic_filters_ref( &mut self, sub: bool,