Skip to content

Commit

Permalink
feat(rumqttc/client): allow using 0 byte string and whitespace as `cl…
Browse files Browse the repository at this point in the history
…ient_id`

We now provide an additional function, `try_set_clean_session` that
returns error if `client_id` is a 0 byte string and `clean_session` is
not `true`.
  • Loading branch information
arunanshub committed Feb 2, 2024
1 parent 09a6153 commit af14471
Showing 1 changed file with 34 additions and 18 deletions.
52 changes: 34 additions & 18 deletions rumqttc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,18 +498,13 @@ impl MqttOptions {
/// let options = MqttOptions::new("", "localhost", 1883);
/// ```
pub fn new<S: Into<String>, T: Into<String>>(id: S, host: T, port: u16) -> MqttOptions {
let id = id.into();
if id.starts_with(' ') || id.is_empty() {
panic!("Invalid client id");
}

MqttOptions {
broker_addr: host.into(),
port,
transport: Transport::tcp(),
keep_alive: Duration::from_secs(60),
clean_session: true,
client_id: id,
client_id: id.into(),
credentials: None,
max_incoming_packet_size: 10 * 1024,
max_outgoing_packet_size: 10 * 1024,
Expand Down Expand Up @@ -624,11 +619,44 @@ impl MqttOptions {
/// When set `false`, broker will hold the client state and performs pending
/// operations on the client when reconnection with same `client_id`
/// happens. Local queue state is also held to retransmit packets after reconnection.
///
/// NOTE: It panicks if the `client_id` is a zero byte string and `clean_session` is
/// not `true`.
///
/// ```should_panic
/// # use rumqttc::MqttOptions;
/// let mut options = MqttOptions::new("", "localhost", 1883);
/// options.set_clean_session(false);
/// ```
pub fn set_clean_session(&mut self, clean_session: bool) -> &mut Self {
if self.client_id.is_empty() {
assert!(
clean_session,
"Cannot unset clean session when client id is empty"
);
}
self.clean_session = clean_session;
self
}

/// Does the same thing as [`Self::set_clean_session`], however it returns an error
/// if `clean_session = false` and `client_id` is a zero byte string.
///
/// ```
/// # use rumqttc::{MqttOptions, OptionError};
/// let mut options = MqttOptions::new("", "localhost", 1883);
/// let error = options.try_set_clean_session(false).unwrap_err();
/// assert_eq!(error, OptionError::CleanSession);
/// ```
#[cfg(feature = "url")]
pub fn try_set_clean_session(&mut self, clean_session: bool) -> Result<&mut Self, OptionError> {
if self.client_id.is_empty() && !clean_session {
return Err(OptionError::CleanSession);
}
self.clean_session = clean_session;
Ok(self)
}

/// Clean session
pub fn clean_session(&self) -> bool {
self.clean_session
Expand Down Expand Up @@ -918,12 +946,6 @@ impl Debug for MqttOptions {
mod test {
use super::*;

#[test]
#[should_panic]
fn client_id_startswith_space() {
let _mqtt_opts = MqttOptions::new(" client_a", "127.0.0.1", 1883).set_clean_session(true);
}

#[test]
#[cfg(all(feature = "use-rustls", feature = "websocket"))]
fn no_scheme() {
Expand Down Expand Up @@ -1006,10 +1028,4 @@ mod test {
OptionError::Inflight
);
}

#[test]
#[should_panic]
fn no_client_id() {
let _mqtt_opts = MqttOptions::new("", "127.0.0.1", 1883).set_clean_session(true);
}
}

0 comments on commit af14471

Please sign in to comment.