code
This commit is contained in:
334
Plugins/MqttClient/Source/DTMqtt/MqttCPP/ssl_options.cpp
Normal file
334
Plugins/MqttClient/Source/DTMqtt/MqttCPP/ssl_options.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
// Copyright 2023 Dexter.Wan. All Rights Reserved.
|
||||
// EMail: 45141961@qq.com
|
||||
|
||||
#include "ssl_options.h"
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
|
||||
namespace mqtt {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const MQTTAsync_SSLOptions ssl_options::DFLT_C_STRUCT = MQTTAsync_SSLOptions_initializer;
|
||||
|
||||
ssl_options::ssl_options() : opts_(DFLT_C_STRUCT)
|
||||
{
|
||||
}
|
||||
|
||||
ssl_options::ssl_options(const string& trustStore, const string& keyStore,
|
||||
const string& privateKey, const string& privateKeyPassword,
|
||||
const string& enabledCipherSuites, bool enableServerCertAuth,
|
||||
const std::vector<string> alpnProtos /*=std::vector<string>()*/)
|
||||
: opts_(DFLT_C_STRUCT),
|
||||
trustStore_(trustStore),
|
||||
keyStore_(keyStore),
|
||||
privateKey_(privateKey),
|
||||
privateKeyPassword_(privateKeyPassword),
|
||||
enabledCipherSuites_(enabledCipherSuites)
|
||||
{
|
||||
set_alpn_protos(alpnProtos);
|
||||
update_c_struct();
|
||||
opts_.enableServerCertAuth = enableServerCertAuth;
|
||||
}
|
||||
|
||||
ssl_options::ssl_options(const string& trustStore, const string& keyStore,
|
||||
const string& privateKey, const string& privateKeyPassword,
|
||||
const string& caPath,
|
||||
const string& enabledCipherSuites, bool enableServerCertAuth,
|
||||
const std::vector<string> alpnProtos /*=std::vector<string>()*/)
|
||||
: opts_(DFLT_C_STRUCT),
|
||||
trustStore_(trustStore),
|
||||
keyStore_(keyStore),
|
||||
privateKey_(privateKey),
|
||||
privateKeyPassword_(privateKeyPassword),
|
||||
caPath_(caPath),
|
||||
enabledCipherSuites_(enabledCipherSuites)
|
||||
{
|
||||
set_alpn_protos(alpnProtos);
|
||||
update_c_struct();
|
||||
opts_.enableServerCertAuth = enableServerCertAuth;
|
||||
}
|
||||
|
||||
ssl_options::ssl_options(const ssl_options& other)
|
||||
: opts_(other.opts_),
|
||||
trustStore_(other.trustStore_),
|
||||
keyStore_(other.keyStore_),
|
||||
privateKey_(other.privateKey_),
|
||||
privateKeyPassword_(other.privateKeyPassword_),
|
||||
caPath_(other.caPath_),
|
||||
enabledCipherSuites_(other.enabledCipherSuites_),
|
||||
errHandler_(other.errHandler_),
|
||||
pskHandler_(other.pskHandler_),
|
||||
protos_(other.protos_)
|
||||
{
|
||||
update_c_struct();
|
||||
}
|
||||
|
||||
ssl_options::ssl_options(ssl_options&& other)
|
||||
: opts_(other.opts_),
|
||||
trustStore_(std::move(other.trustStore_)),
|
||||
keyStore_(std::move(other.keyStore_)),
|
||||
privateKey_(std::move(other.privateKey_)),
|
||||
privateKeyPassword_(std::move(other.privateKeyPassword_)),
|
||||
caPath_(std::move(other.caPath_)),
|
||||
enabledCipherSuites_(std::move(other.enabledCipherSuites_)),
|
||||
errHandler_(std::move(other.errHandler_)),
|
||||
pskHandler_(std::move(other.pskHandler_)),
|
||||
protos_(std::move(other.protos_))
|
||||
{
|
||||
update_c_struct();
|
||||
}
|
||||
|
||||
void ssl_options::update_c_struct()
|
||||
{
|
||||
opts_.trustStore = c_str(trustStore_);
|
||||
opts_.keyStore = c_str(keyStore_);
|
||||
opts_.privateKey = c_str(privateKey_);
|
||||
opts_.privateKeyPassword = c_str(privateKeyPassword_);
|
||||
opts_.CApath = c_str(caPath_);
|
||||
opts_.enabledCipherSuites = c_str(enabledCipherSuites_);
|
||||
|
||||
if (errHandler_) {
|
||||
opts_.ssl_error_cb = &ssl_options::on_error;
|
||||
opts_.ssl_error_context = this;
|
||||
}
|
||||
else {
|
||||
opts_.ssl_error_cb = nullptr;
|
||||
opts_.ssl_error_context = nullptr;
|
||||
}
|
||||
|
||||
if (pskHandler_) {
|
||||
opts_.ssl_psk_cb = &ssl_options::on_psk;
|
||||
opts_.ssl_psk_context = this;
|
||||
}
|
||||
else {
|
||||
opts_.ssl_psk_cb = nullptr;
|
||||
opts_.ssl_psk_context = nullptr;
|
||||
}
|
||||
|
||||
if (!protos_.empty()) {
|
||||
opts_.protos = protos_.data();
|
||||
opts_.protos_len = unsigned(protos_.length());
|
||||
}
|
||||
else {
|
||||
opts_.protos = nullptr;
|
||||
opts_.protos_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
int ssl_options::on_error(const char *str, size_t len, void *context)
|
||||
{
|
||||
try {
|
||||
if (context && str && len > 0) {
|
||||
string errMsg { str, len };
|
||||
|
||||
ssl_options* opts = static_cast<ssl_options*>(context);
|
||||
auto& errHandler = opts->errHandler_;
|
||||
|
||||
if (errHandler)
|
||||
errHandler(errMsg);
|
||||
|
||||
return MQTTASYNC_SUCCESS;
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
return MQTTASYNC_FAILURE;
|
||||
}
|
||||
|
||||
unsigned ssl_options::on_psk(const char *hint, char *identity, unsigned max_identity_len,
|
||||
unsigned char *psk, unsigned max_psk_len, void *context)
|
||||
{
|
||||
unsigned ret = 0;
|
||||
|
||||
try {
|
||||
if (context) {
|
||||
auto hintStr = (hint) ? string(hint) : string();
|
||||
|
||||
ssl_options* opts = static_cast<ssl_options*>(context);
|
||||
auto& pskHandler = opts->pskHandler_;
|
||||
|
||||
if (pskHandler) {
|
||||
ret = pskHandler(hintStr, identity, size_t(max_identity_len),
|
||||
psk, size_t(max_psk_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ssl_options& ssl_options::operator=(const ssl_options& rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
opts_ = rhs.opts_;
|
||||
|
||||
trustStore_ = rhs.trustStore_;
|
||||
keyStore_ = rhs.keyStore_;
|
||||
privateKey_ = rhs.privateKey_;
|
||||
privateKeyPassword_ = rhs.privateKeyPassword_;
|
||||
caPath_ = rhs.caPath_;
|
||||
enabledCipherSuites_ = rhs.enabledCipherSuites_;
|
||||
|
||||
errHandler_ = rhs.errHandler_;
|
||||
pskHandler_ = rhs.pskHandler_;
|
||||
|
||||
protos_ = rhs.protos_;
|
||||
|
||||
update_c_struct();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ssl_options& ssl_options::operator=(ssl_options&& rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
opts_ = rhs.opts_;
|
||||
|
||||
trustStore_ = std::move(rhs.trustStore_);
|
||||
keyStore_ = std::move(rhs.keyStore_);
|
||||
privateKey_ = std::move(rhs.privateKey_);
|
||||
privateKeyPassword_ = std::move(rhs.privateKeyPassword_);
|
||||
caPath_ = std::move(rhs.caPath_);
|
||||
enabledCipherSuites_ = std::move(rhs.enabledCipherSuites_);
|
||||
|
||||
errHandler_ = std::move(rhs.errHandler_);
|
||||
pskHandler_ = std::move(rhs.pskHandler_);
|
||||
|
||||
protos_ = std::move(rhs.protos_);
|
||||
|
||||
update_c_struct();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void ssl_options::set_trust_store(const string& trustStore)
|
||||
{
|
||||
trustStore_ = trustStore;
|
||||
opts_.trustStore = c_str(trustStore_);
|
||||
}
|
||||
|
||||
void ssl_options::set_key_store(const string& keyStore)
|
||||
{
|
||||
keyStore_ = keyStore;
|
||||
opts_.keyStore = c_str(keyStore_);
|
||||
}
|
||||
|
||||
void ssl_options::set_private_key(const string& privateKey)
|
||||
{
|
||||
privateKey_ = privateKey;
|
||||
opts_.privateKey = c_str(privateKey_);
|
||||
}
|
||||
|
||||
void ssl_options::set_private_key_password(const string& privateKeyPassword)
|
||||
{
|
||||
privateKeyPassword_ = privateKeyPassword;
|
||||
opts_.privateKeyPassword = c_str(privateKeyPassword_);
|
||||
}
|
||||
|
||||
void ssl_options::set_enabled_cipher_suites(const string& enabledCipherSuites)
|
||||
{
|
||||
enabledCipherSuites_ = enabledCipherSuites;
|
||||
opts_.enabledCipherSuites = c_str(enabledCipherSuites_);
|
||||
}
|
||||
|
||||
void ssl_options::set_enable_server_cert_auth(bool enableServerCertAuth)
|
||||
{
|
||||
opts_.enableServerCertAuth = to_int(enableServerCertAuth);
|
||||
}
|
||||
|
||||
void ssl_options::set_ca_path(const string& path)
|
||||
{
|
||||
caPath_ = path;
|
||||
opts_.CApath = c_str(caPath_);
|
||||
}
|
||||
|
||||
void ssl_options::set_error_handler(error_handler cb)
|
||||
{
|
||||
errHandler_ = cb;
|
||||
|
||||
if (errHandler_) {
|
||||
opts_.ssl_error_cb = &ssl_options::on_error;
|
||||
opts_.ssl_error_context = this;
|
||||
}
|
||||
else {
|
||||
opts_.ssl_error_cb = nullptr;
|
||||
opts_.ssl_error_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ssl_options::set_psk_handler(psk_handler cb)
|
||||
{
|
||||
pskHandler_ = cb;
|
||||
|
||||
if (pskHandler_) {
|
||||
opts_.ssl_psk_cb = &ssl_options::on_psk;
|
||||
opts_.ssl_psk_context = this;
|
||||
}
|
||||
else {
|
||||
opts_.ssl_psk_cb = nullptr;
|
||||
opts_.ssl_psk_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the list of ALPN protocols.
|
||||
// To do so, it must recover the strings from the wire format.
|
||||
std::vector<string> ssl_options::get_alpn_protos() const
|
||||
{
|
||||
std::vector<string> protos;
|
||||
size_t i = 0, n = protos_.length();
|
||||
|
||||
while (i < n) {
|
||||
size_t sn = protos_[i++];
|
||||
if (i+sn > n) break;
|
||||
|
||||
string s;
|
||||
s.reserve(sn);
|
||||
|
||||
sn += i;
|
||||
while (i < sn)
|
||||
s.push_back(char(protos_[i++]));
|
||||
protos.push_back(std::move(s));
|
||||
}
|
||||
return protos;
|
||||
}
|
||||
|
||||
// Converts the vector of names into the binary string in wire format.
|
||||
// This is a single string uf unsigned characters with each protocol
|
||||
// prepended by a byte of its length.
|
||||
void ssl_options::set_alpn_protos(const std::vector<string>& protos)
|
||||
{
|
||||
using uchar = unsigned char;
|
||||
|
||||
if (!protos.empty()) {
|
||||
std::basic_string<uchar> protoBin;
|
||||
for (const auto& proto : protos) {
|
||||
protoBin.push_back(uchar(proto.length()));
|
||||
for (const char c : proto)
|
||||
protoBin.push_back(uchar(c));
|
||||
}
|
||||
protos_ = std::move(protoBin);
|
||||
|
||||
opts_.protos = protos_.data();
|
||||
opts_.protos_len = unsigned(protos_.length());
|
||||
}
|
||||
else {
|
||||
protos_ = std::basic_string<uchar>();
|
||||
opts_.protos = nullptr;
|
||||
opts_.protos_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// end namespace mqtt
|
||||
}
|
||||
|
Reference in New Issue
Block a user