Update documentation

This commit is contained in:
Ondrej Babec 2022-05-05 07:47:07 +02:00
parent 63314fc867
commit e47667156d
No known key found for this signature in database
GPG Key ID: 13E577E3769B2079
5 changed files with 73 additions and 5 deletions

View File

@ -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> { pub async fn connect_to_broker<'b>(&'b mut self) -> Result<(), ReasonCode> {
match self.config.mqtt_version { match self.config.mqtt_version {
MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion),
@ -175,6 +179,10 @@ where
Ok(()) 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> { pub async fn disconnect<'b>(&'b mut self) -> Result<(), ReasonCode> {
match self.config.mqtt_version { match self.config.mqtt_version {
MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion),
@ -242,7 +250,10 @@ where
} }
Ok(()) 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>( pub async fn send_message<'b>(
&'b mut self, &'b mut self,
topic_name: &'b str, topic_name: &'b str,
@ -314,6 +325,10 @@ where
Ok(()) 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>( pub async fn subscribe_to_topics<'b, const TOPICS: usize>(
&'b mut self, &'b mut self,
topic_names: &'b Vec<&'b str, TOPICS>, 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>( pub async fn unsubscribe_from_topic<'b>(
&'b mut self, &'b mut self,
topic_name: &'b str, 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, &'b mut self,
topic_name: &'b str, topic_name: &'b str,
) -> Result<(), ReasonCode> { ) -> 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>( pub async fn subscribe_to_topic<'b>(
&'b mut self, &'b mut self,
topic_name: &'b str, topic_name: &'b str,
@ -471,6 +492,9 @@ where
return Ok(packet.message.unwrap()); 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> { pub async fn receive_message<'b>(&'b mut self) -> Result<&'b [u8], ReasonCode> {
match self.config.mqtt_version { match self.config.mqtt_version {
MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), 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> { pub async fn send_ping<'b>(&'b mut self) -> Result<(), ReasonCode> {
match self.config.mqtt_version { match self.config.mqtt_version {
MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion), MqttVersion::MQTTv3 => Err(ReasonCode::UnsupportedProtocolVersion),

View File

@ -34,7 +34,16 @@ pub enum MqttVersion {
MQTTv3, MQTTv3,
MQTTv5, 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)] #[derive(Clone)]
pub struct ClientConfig<'a, const MAX_PROPERTIES: usize, T: RngCore> { pub struct ClientConfig<'a, const MAX_PROPERTIES: usize, T: RngCore> {
pub qos: QualityOfService, pub qos: QualityOfService,
@ -69,6 +78,8 @@ impl<'a, const MAX_PROPERTIES: usize, T: RngCore> ClientConfig<'a, MAX_PROPERTIE
self.qos = qos; 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) { pub fn add_username(&mut self, username: &'a str) {
let mut username_s: EncodedString = EncodedString::new(); let mut username_s: EncodedString = EncodedString::new();
username_s.string = username; 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_flag = true;
self.username = username_s; 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) { pub fn add_password(&mut self, password: &'a str) {
let mut password_s: BinaryData = BinaryData::new(); let mut password_s: BinaryData = BinaryData::new();
password_s.bin = password.as_bytes(); 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; 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>) { pub fn add_property(&mut self, prop: Property<'a>) {
if self.properties.len() < MAX_PROPERTIES { if self.properties.len() < MAX_PROPERTIES {
self.properties.push(prop); 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 { pub fn add_max_packet_size_as_prop(&mut self) -> u32 {
if self.properties.len() < MAX_PROPERTIES { if self.properties.len() < MAX_PROPERTIES {
let prop = Property::MaximumPacketSize(self.max_packet_size); let prop = Property::MaximumPacketSize(self.max_packet_size);

View File

@ -34,7 +34,8 @@ pub enum NetworkError {
IDNotMatchedOnAck, IDNotMatchedOnAck,
NoMatchingSubs, NoMatchingSubs,
} }
/// NetworkConnectionFactory implementation should create a TCP connection and return
/// the `Connection` trait implementation. Otherwise return `ReasonCode`.
pub trait NetworkConnectionFactory: Sized { pub trait NetworkConnectionFactory: Sized {
type Connection: NetworkConnection; type Connection: NetworkConnection;
@ -42,9 +43,11 @@ pub trait NetworkConnectionFactory: Sized {
where where
Self: 'm; 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>; 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 { pub trait NetworkConnection {
type SendFuture<'m>: Future<Output = Result<(), ReasonCode>> type SendFuture<'m>: Future<Output = Result<(), ReasonCode>>
where where
@ -56,9 +59,12 @@ pub trait NetworkConnection {
type CloseFuture<'m>: Future<Output = Result<(), ReasonCode>>; type CloseFuture<'m>: Future<Output = Result<(), ReasonCode>>;
/// Send function should enable sending the data from `buffer` via TCP connection.
fn send<'m>(&'m mut self, buffer: &'m [u8]) -> Self::SendFuture<'m>; 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>; 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>; fn close<'m>(self) -> Self::CloseFuture<'m>;
} }

View File

@ -34,6 +34,8 @@ use tokio::net::TcpStream;
use crate::network::{NetworkConnection, NetworkConnectionFactory}; use crate::network::{NetworkConnection, NetworkConnectionFactory};
use crate::packet::v5::reason_codes::ReasonCode; 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 { pub struct TokioNetwork {
stream: TcpStream, 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 {} pub struct TokioNetworkFactory {}
impl TokioNetworkFactory { impl TokioNetworkFactory {

View File

@ -28,6 +28,8 @@ use crate::encoding::variable_byte_integer::{VariableByteInteger, VariableByteIn
use crate::packet::v5::property::Property; use crate::packet::v5::property::Property;
use crate::utils::types::{BinaryData, BufferError, EncodedString, StringPair, TopicFilter}; 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> { pub struct BuffWriter<'a> {
buffer: &'a mut [u8], buffer: &'a mut [u8],
pub position: usize, pub position: usize,
@ -47,6 +49,7 @@ impl<'a> BuffWriter<'a> {
self.position = self.position + increment; 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 { pub fn get_n_byte(&mut self, n: usize) -> u8 {
if self.position >= n { if self.position >= n {
return self.buffer[n]; return self.buffer[n];
@ -54,6 +57,7 @@ impl<'a> BuffWriter<'a> {
return 0; 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<VariableByteInteger, ()> { pub fn get_rem_len(&mut self) -> Result<VariableByteInteger, ()> {
let max = if self.position >= 5 { let max = if self.position >= 5 {
4 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> { pub fn insert_ref(&mut self, len: usize, array: &[u8]) -> Result<(), BufferError> {
let mut x: usize = 0; let mut x: usize = 0;
if self.position + len > self.len { if self.position + len > self.len {
@ -95,6 +100,7 @@ impl<'a> BuffWriter<'a> {
return Ok(()); return Ok(());
} }
/// Writes a single Byte to the buffer.
pub fn write_u8(&mut self, byte: u8) -> Result<(), BufferError> { pub fn write_u8(&mut self, byte: u8) -> Result<(), BufferError> {
return if self.position >= self.len { return if self.position >= self.len {
Err(BufferError::InsufficientBufferSize) 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> { pub fn write_u16(&mut self, two_bytes: u16) -> Result<(), BufferError> {
let bytes: [u8; 2] = two_bytes.to_be_bytes(); let bytes: [u8; 2] = two_bytes.to_be_bytes();
return self.insert_ref(2, &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> { pub fn write_u32(&mut self, four_bytes: u32) -> Result<(), BufferError> {
let bytes: [u8; 4] = four_bytes.to_be_bytes(); let bytes: [u8; 4] = four_bytes.to_be_bytes();
return self.insert_ref(4, &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> { pub fn write_string_ref(&mut self, str: &EncodedString<'a>) -> Result<(), BufferError> {
self.write_u16(str.len)?; self.write_u16(str.len)?;
if str.len != 0 { if str.len != 0 {
@ -124,16 +133,19 @@ impl<'a> BuffWriter<'a> {
return Ok(()); return Ok(());
} }
/// Writes BinaryData to the buffer.
pub fn write_binary_ref(&mut self, bin: &BinaryData<'a>) -> Result<(), BufferError> { pub fn write_binary_ref(&mut self, bin: &BinaryData<'a>) -> Result<(), BufferError> {
self.write_u16(bin.len)?; self.write_u16(bin.len)?;
return self.insert_ref(bin.len as usize, bin.bin); 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> { pub fn write_string_pair_ref(&mut self, str_pair: &StringPair<'a>) -> Result<(), BufferError> {
self.write_string_ref(&str_pair.name)?; self.write_string_ref(&str_pair.name)?;
return self.write_string_ref(&str_pair.value); 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> { pub fn write_variable_byte_int(&mut self, int: u32) -> Result<(), BufferError> {
let x: VariableByteInteger = VariableByteIntegerEncoder::encode(int)?; let x: VariableByteInteger = VariableByteIntegerEncoder::encode(int)?;
let len = VariableByteIntegerEncoder::len(x); let len = VariableByteIntegerEncoder::len(x);
@ -146,6 +158,7 @@ impl<'a> BuffWriter<'a> {
return property.encode(self); return property.encode(self);
} }
/// Writes all properties from the `properties` Vec into the buffer.
pub fn write_properties<const LEN: usize>( pub fn write_properties<const LEN: usize>(
&mut self, &mut self,
properties: &Vec<Property<'a>, LEN>, properties: &Vec<Property<'a>, LEN>,
@ -165,6 +178,8 @@ impl<'a> BuffWriter<'a> {
Ok(()) 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( fn write_topic_filter_ref(
&mut self, &mut self,
sub: bool, sub: bool,
@ -177,6 +192,8 @@ impl<'a> BuffWriter<'a> {
return Ok(()); 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<const MAX: usize>( pub fn write_topic_filters_ref<const MAX: usize>(
&mut self, &mut self,
sub: bool, sub: bool,