PreVerify/mqtt/paho.mqtt.cpp/connect_options.cpp
2024-09-09 19:18:28 +08:00

441 lines
11 KiB
C++

// connect_options.cpp
/*******************************************************************************
* Copyright (c) 2017-2023 Frank Pagliughi <fpagliughi@mindspring.com>
* Copyright (c) 2016 Guilherme M. Ferreira <guilherme.maciel.ferreira@gmail.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Guilherme M. Ferreira - initial implementation and documentation
* Frank Pagliughi - Copy and move operations. Bug fixes.
*******************************************************************************/
#include "mqtt/connect_options.h"
#include <cstring>
namespace mqtt {
/////////////////////////////////////////////////////////////////////////////
PAHO_MQTTPP_EXPORT const MQTTAsync_connectOptions connect_options::DFLT_C_STRUCT =
MQTTAsync_connectOptions_initializer;
PAHO_MQTTPP_EXPORT const MQTTAsync_connectOptions connect_options::DFLT_C_STRUCT5 =
MQTTAsync_connectOptions_initializer5;
PAHO_MQTTPP_EXPORT const MQTTAsync_connectOptions connect_options::DFLT_C_STRUCT_WS =
MQTTAsync_connectOptions_initializer_ws;
PAHO_MQTTPP_EXPORT const MQTTAsync_connectOptions connect_options::DFLT_C_STRUCT5_WS =
MQTTAsync_connectOptions_initializer5_ws;
// --------------------------------------------------------------------------
connect_options::connect_options(int ver /*=MQTTVERSION_DEFAULT*/)
{
opts_ = (ver < MQTTVERSION_5) ? DFLT_C_STRUCT : DFLT_C_STRUCT5;
}
connect_options::connect_options(
string_ref userName, binary_ref password,
int ver /*=MQTTVERSION_DEFAULT*/
)
: connect_options(ver)
{
set_user_name(userName);
set_password(password);
}
connect_options::connect_options(const connect_options& opt) : opts_(opt.opts_),
userName_(opt.userName_),
password_(opt.password_),
tok_(opt.tok_),
serverURIs_(opt.serverURIs_),
props_(opt.props_),
httpHeaders_(opt.httpHeaders_),
httpProxy_(opt.httpProxy_),
httpsProxy_(opt.httpsProxy_)
{
if (opts_.will)
set_will(opt.will_);
if (opts_.ssl)
set_ssl(opt.ssl_);
update_c_struct();
}
connect_options::connect_options(connect_options&& opt) : opts_(opt.opts_),
will_(std::move(opt.will_)),
ssl_(std::move(opt.ssl_)),
userName_(std::move(opt.userName_)),
password_(std::move(opt.password_)),
tok_(std::move(opt.tok_)),
serverURIs_(std::move(opt.serverURIs_)),
props_(std::move(opt.props_)),
httpHeaders_(std::move(opt.httpHeaders_)),
httpProxy_(std::move(opt.httpProxy_)),
httpsProxy_(std::move(opt.httpsProxy_))
{
if (opts_.will)
opts_.will = &will_.opts_;
if (opts_.willProperties)
opts_.willProperties = const_cast<MQTTProperties*>(&will_.props_.c_struct());
if (opts_.ssl)
opts_.ssl = &ssl_.opts_;
update_c_struct();
}
connect_options connect_options::v3()
{
return connect_options(DFLT_C_STRUCT);
}
connect_options connect_options::v5()
{
return connect_options(DFLT_C_STRUCT5);
}
// Unfortunately, with the existing implementation, there's no way to know
// if the (connect) properties, will and ssl options were set by looking at the C++ structs.
// In a major update, we can consider using a pointer or optional<> to
// indicate that they were set.
// But, for now, the copy and assignment operations must handle it manually
// by looking to see if the source C options pointer was set.
void connect_options::update_c_struct()
{
opts_.username = c_str(userName_);
// Password
if (password_.empty()) {
opts_.binarypwd.len = 0;
opts_.binarypwd.data = nullptr;
}
else {
opts_.binarypwd.len = (int) password_.size();
opts_.binarypwd.data = password_.data();
}
// Token
opts_.onSuccess = nullptr;
opts_.onFailure = nullptr;
opts_.onSuccess5 = nullptr;
opts_.onFailure5 = nullptr;
if (tok_) {
if (opts_.MQTTVersion < MQTTVERSION_5) {
opts_.onSuccess = &token::on_success;
opts_.onFailure = &token::on_failure;
}
else {
opts_.onSuccess5 = &token::on_success5;
opts_.onFailure5 = &token::on_failure5;
}
}
// Server URIs
if (!serverURIs_ || serverURIs_->empty()) {
opts_.serverURIcount = 0;
opts_.serverURIs = nullptr;
}
else {
opts_. serverURIcount = (int) serverURIs_->size();
opts_.serverURIs = serverURIs_->c_arr();
}
// Connect Properties
if (opts_.MQTTVersion >= MQTTVERSION_5)
opts_.connectProperties = const_cast<MQTTProperties*>(&props_.c_struct());
// HTTP & Proxy
opts_.httpProxy = c_str(httpProxy_);
opts_.httpsProxy = c_str(httpsProxy_);
}
connect_options& connect_options::operator=(const connect_options& opt)
{
if (&opt == this)
return *this;
opts_ = opt.opts_;
if (opts_.will)
set_will(opt.will_);
if (opts_.ssl)
set_ssl(opt.ssl_);
userName_ = opt.userName_;
password_ = opt.password_;
tok_ = opt.tok_;
serverURIs_ = opt.serverURIs_;
props_ = opt.props_;
httpHeaders_ = opt.httpHeaders_;
httpProxy_ = opt.httpProxy_;
httpsProxy_ = opt.httpsProxy_;
update_c_struct();
return *this;
}
connect_options& connect_options::operator=(connect_options&& opt)
{
if (&opt == this)
return *this;
opts_ = opt.opts_;
if (opts_.will)
set_will(std::move(opt.will_));
if (opts_.ssl)
set_ssl(std::move(opt.ssl_));
userName_ = std::move(opt.userName_);
password_ = std::move(opt.password_);
tok_ = std::move(opt.tok_);
serverURIs_ = std::move(opt.serverURIs_);
props_ = std::move(opt.props_);
httpHeaders_ = std::move(opt.httpHeaders_);
httpProxy_ = std::move(opt.httpProxy_);
httpsProxy_ = std::move(opt.httpsProxy_);
update_c_struct();
return *this;
}
void connect_options::set_will(const will_options& will)
{
will_ = will;
opts_.will = &will_.opts_;
opts_.willProperties = will_.get_properties().empty()
? nullptr : const_cast<MQTTProperties*>(&will_.props_.c_struct());
}
void connect_options::set_will(will_options&& will)
{
will_ = will;
opts_.will = &will_.opts_;
opts_.willProperties = will_.get_properties().empty()
? nullptr : const_cast<MQTTProperties*>(&will_.props_.c_struct());
}
void connect_options::set_user_name(string_ref userName)
{
userName_ = std::move(userName);
opts_.username = c_str(userName_);
}
void connect_options::set_password(binary_ref password)
{
password_ = std::move(password);
if (password_.empty()) {
opts_.binarypwd.len = 0;
opts_.binarypwd.data = nullptr;
}
else {
opts_.binarypwd.len = (int) password_.size();
opts_.binarypwd.data = password_.data();
}
}
void connect_options::set_ssl(const ssl_options& ssl)
{
ssl_ = ssl;
opts_.ssl = &ssl_.opts_;
}
void connect_options::set_ssl(ssl_options&& ssl)
{
ssl_ = ssl;
opts_.ssl = &ssl_.opts_;
}
// Clean sessions only apply to MQTT v3, so force it there if set.
void connect_options::set_clean_session(bool clean)
{
if (opts_.MQTTVersion < MQTTVERSION_5)
opts_.cleansession = to_int(clean);
}
// Clean start only apply to MQTT v5, so force it there if set.
void connect_options::set_clean_start(bool cleanStart)
{
if (opts_.MQTTVersion >= MQTTVERSION_5)
opts_.cleanstart = to_int(cleanStart);
}
void connect_options::set_token(const token_ptr& tok)
{
tok_ = tok;
opts_.context = tok_.get();
opts_.onSuccess = nullptr;
opts_.onFailure = nullptr;
opts_.onSuccess5 = nullptr;
opts_.onFailure5 = nullptr;
if (tok) {
if (opts_.MQTTVersion < MQTTVERSION_5) {
opts_.onSuccess = &token::on_success;
opts_.onFailure = &token::on_failure;
}
else {
opts_.onSuccess5 = &token::on_success5;
opts_.onFailure5 = &token::on_failure5;
}
}
}
void connect_options::set_servers(const_string_collection_ptr serverURIs)
{
if (serverURIs) {
serverURIs_ = std::move(serverURIs);
opts_. serverURIcount = (int) serverURIs_->size();
opts_.serverURIs = serverURIs_->c_arr();
}
else {
serverURIs_.reset();
opts_.serverURIcount = 0;
opts_.serverURIs = nullptr;
}
}
void connect_options::set_mqtt_version(int mqttVersion) {
opts_.MQTTVersion = mqttVersion;
if (mqttVersion < MQTTVERSION_5)
opts_.cleanstart = 0;
else
opts_.cleansession = 0;
}
void connect_options::set_automatic_reconnect(int minRetryInterval,
int maxRetryInterval)
{
opts_.automaticReconnect = to_int(true);
opts_.minRetryInterval = minRetryInterval;
opts_.maxRetryInterval = maxRetryInterval;
}
void connect_options::set_properties(const properties& props)
{
props_ = props;
opts_.connectProperties = const_cast<MQTTProperties*>(&props_.c_struct());
opts_.MQTTVersion = MQTTVERSION_5;
}
void connect_options::set_properties(properties&& props)
{
props_ = std::move(props);
opts_.connectProperties = const_cast<MQTTProperties*>(&props_.c_struct());
opts_.MQTTVersion = MQTTVERSION_5;
}
void connect_options::set_http_proxy(const string& httpProxy)
{
httpProxy_ = httpProxy;
opts_.httpProxy = c_str(httpProxy_);
}
void connect_options::set_https_proxy(const string& httpsProxy)
{
httpsProxy_ = httpsProxy;
opts_.httpsProxy = c_str(httpsProxy_);
}
/////////////////////////////////////////////////////////////////////////////
// connect_data
PAHO_MQTTPP_EXPORT const MQTTAsync_connectData connect_data::DFLT_C_STRUCT
= MQTTAsync_connectData_initializer;
connect_data::connect_data() : data_(DFLT_C_STRUCT)
{
}
connect_data::connect_data(string_ref userName)
: data_(DFLT_C_STRUCT), userName_(userName)
{
update_c_struct();
}
connect_data::connect_data(string_ref userName, binary_ref password)
: data_(DFLT_C_STRUCT), userName_(userName), password_(password)
{
update_c_struct();
}
connect_data::connect_data(const MQTTAsync_connectData& cdata)
: data_(DFLT_C_STRUCT),
password_((char*)cdata.binarypwd.data, size_t(cdata.binarypwd.len))
{
if (cdata.username)
userName_ = string_ref(cdata.username, strlen(cdata.username));
update_c_struct();
}
void connect_data::update_c_struct()
{
data_.username = userName_.empty() ? nullptr : userName_.c_str();
if (password_.empty()) {
data_.binarypwd.len = 0;
data_.binarypwd.data = nullptr;
}
else {
data_.binarypwd.len = (int) password_.size();
data_.binarypwd.data = password_.data();
}
}
connect_data& connect_data::operator=(const connect_data& rhs)
{
if (&rhs != this) {
userName_ = rhs.userName_;
password_ = rhs.password_;
update_c_struct();
}
return *this;
}
void connect_data::set_user_name(string_ref userName)
{
userName_ = std::move(userName);
update_c_struct();
}
void connect_data::set_password(binary_ref password)
{
password_ = std::move(password);
update_c_struct();
}
/////////////////////////////////////////////////////////////////////////////
} // end namespace mqtt