1
0
mirror of https://github.com/qt/qtmqtt.git synced 2026-10-25 16:16:26 +00:00
qtmqtt/examples/mqtt/consolepubsub/configuration.h
Lucie Gérard edd6855344 Use SPDX license identifiers
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
License files are organized under LICENSES directory.

Pick-to: 6.4
Task-number: QTBUG-67283
Change-Id: Ie4309963c8e17d4e7dad602f61a660246d5e23cb
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-06-16 10:22:20 +02:00

265 lines
10 KiB
C

// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QByteArray>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QLoggingCategory>
#include <QString>
#include <QMqttClient>
#include <QSslConfiguration>
#include <QSslSocket>
struct Configuration
{
QString topic;
QByteArray content;
quint8 qos;
bool retain{false};
bool useEncryption{false};
#ifndef QT_NO_SSL
QSslConfiguration sslConfiguration;
#endif
};
QMqttClient *createClientWithConfiguration(QCoreApplication *app,
Configuration *msg,
bool publish)
{
QCommandLineParser parser;
if (publish)
parser.setApplicationDescription("Qt MQTT publish tool");
else
parser.setApplicationDescription("Qt MQTT subscription tool");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption optionDebug("d",
QLatin1String("Enable debug messages / logging categories"));
parser.addOption(optionDebug);
QCommandLineOption optionFile("f",
QLatin1String("Specify the content of a file as message."),
QLatin1String("filename"));
if (publish)
parser.addOption(optionFile);
QCommandLineOption optionClientId("i",
QLatin1String("Specify a client ID. Defaults to random value."),
QLatin1String("clientid"));
parser.addOption(optionClientId);
QCommandLineOption optionKeepAlive("k",
QLatin1String("Specify the keep-alive value in seconds."),
QLatin1String("keepAlive"));
parser.addOption(optionKeepAlive);
QCommandLineOption optionMessageContent("m",
QLatin1String("Specify the message content. Defaults to"
" a null message."),
QLatin1String("messageContent"));
if (publish)
parser.addOption(optionMessageContent);
QCommandLineOption optionPassword("P",
QLatin1String("Provide a password."),
QLatin1String("password"));
parser.addOption(optionPassword);
QCommandLineOption optionPort("p",
QLatin1String("Network port to connect to. Defaults to 1883."),
QLatin1String("hostPort"),
QLatin1String("1883"));
parser.addOption(optionPort);
QCommandLineOption optionQos("q",
QLatin1String("Quality of service level to use for all messages."
"Defaults to 0."),
QLatin1String("qos"),
QLatin1String("0"));
parser.addOption(optionQos);
QCommandLineOption optionRetain("r",
QLatin1String("Specify the retain flag for a message."));
if (publish)
parser.addOption(optionRetain);
QCommandLineOption optionHost("s",
QLatin1String("MQTT server to connect to. Defaults to localhost."),
QLatin1String("hostName"),
QLatin1String("localhost"));
parser.addOption(optionHost);
QCommandLineOption optionMessageTopic("t",
QLatin1String("Specify the message topic."),
QLatin1String("messageTopic"));
parser.addOption(optionMessageTopic);
QCommandLineOption optionUser("u",
QLatin1String("Provide a username."),
QLatin1String("username"));
parser.addOption(optionUser);
QCommandLineOption optionVersion("V",
QLatin1String("Specify the protocol version. Options are "
"mqtt31, mqtt311, mqtt5. Defaults to mqtt311."),
QLatin1String("protocolVersion"),
QLatin1String("mqtt311"));
parser.addOption(optionVersion);
QCommandLineOption optionCaFile("cafile",
QLatin1String("Specify a file containing trusted CA "
"certificates to enable encrypted communication."),
QLatin1String("cafile"));
parser.addOption(optionCaFile);
QCommandLineOption optionCaPath("capath",
QLatin1String("Specify a directory containing trusted CA "
"certificates to enable encrypted communication."),
QLatin1String("capath"));
parser.addOption(optionCaPath);
parser.process(*app);
auto *client = new QMqttClient(app);
client->setHostname(parser.value(optionHost));
bool ok = true;
quint16 port = static_cast<quint16>(parser.value(optionPort).toInt(&ok));
if (!ok) {
qWarning() << "Invalid port specified:" << parser.value(optionPort);
return nullptr;
}
client->setPort(port);
if (parser.isSet(optionUser))
client->setUsername(parser.value(optionUser));
if (parser.isSet(optionPassword))
client->setPassword(parser.value(optionPassword));
if (parser.isSet(optionClientId))
client->setClientId(parser.value(optionClientId));
if (parser.isSet(optionVersion)) {
const QString version = parser.value(optionVersion);
if (version == QLatin1String("mqtt31"))
client->setProtocolVersion(QMqttClient::MQTT_3_1);
else if (version == QLatin1String("mqtt311"))
client->setProtocolVersion(QMqttClient::MQTT_3_1_1);
else if (version == QLatin1String("mqtt5"))
client->setProtocolVersion(QMqttClient::MQTT_5_0);
else {
qWarning() << "Invalid protocol version specified:" << version;
return nullptr;
}
}
if (parser.isSet(optionCaFile) || parser.isSet(optionCaPath)) {
#ifdef QT_NO_SSL
qWarning() << "Qt has not been compiled with SSL support.";
return nullptr;
#else
QList<QString> fileNames;
if (parser.isSet(optionCaFile))
fileNames.append(parser.value(optionCaFile));
if (parser.isSet(optionCaPath)) {
QFileInfo path(parser.value(optionCaPath));
if (!path.isDir()) {
qWarning() << "Specified capath is not a directory";
return nullptr;
}
auto entries = QDir(parser.value(optionCaPath)).entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
for (auto entry : entries)
fileNames.append(entry.absoluteFilePath());
}
if (fileNames.isEmpty()) {
qWarning() << "No certificate file found.";
return nullptr;
}
QList<QSslCertificate> defaultCerts;
for (auto it : fileNames) {
auto certificates = QSslCertificate::fromPath(it);
if (certificates.isEmpty() && parser.isSet(optionDebug))
qWarning() << "File " << it << " does not contain any certificates";
defaultCerts.append(certificates);
}
if (defaultCerts.isEmpty()) {
qWarning() << "No certificate could be loaded.";
return nullptr;
}
msg->sslConfiguration.setCaCertificates(defaultCerts);
msg->useEncryption = true;
#endif
}
if (parser.isSet(optionDebug))
QLoggingCategory::setFilterRules(QLatin1String("qt.mqtt.*=true"));
msg->qos = static_cast<quint8>(parser.value(optionQos).toInt(&ok));
if (!ok || msg->qos > 2) {
qWarning() << "Invalid quality of service for message specified:" << msg->qos;
return nullptr;
}
if (parser.isSet(optionKeepAlive)) {
const quint16 keep = static_cast<quint16>(parser.value(optionKeepAlive).toUInt(&ok));
if (!ok) {
qWarning() << "Invalid keep alive value specified";
return nullptr;
}
client->setKeepAlive(keep);
}
if (publish) {
if (parser.isSet(optionFile) && parser.isSet(optionMessageContent)) {
qWarning() << "You cannot specify a file and a text as message.";
return nullptr;
}
if (parser.isSet(optionFile)) {
QFile file(parser.value(optionFile));
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Could not open specified file for reading.";
return nullptr;
}
msg->content = file.readAll();
file.close();
}
if (parser.isSet(optionMessageContent))
msg->content = parser.value(optionMessageContent).toUtf8();
}
if (!parser.isSet(optionMessageTopic)) {
qWarning() << "You must specify a topic to publish a message.";
return nullptr;
}
msg->topic = parser.value(optionMessageTopic);
if (publish && !QMqttTopicName(msg->topic).isValid()) {
qWarning() << "The specified message topic is invalid.";
return nullptr;
}
if (!publish && !QMqttTopicFilter(msg->topic).isValid()) {
qWarning() << "The specified subscription topic is invalid.";
return nullptr;
}
if (publish && parser.isSet(optionRetain))
msg->retain = true;
// Output:
qInfo() << "Client configuration:";
qInfo() << " Host:" << client->hostname() << " Port:" << client->port()
<< " Protocol:" << client->protocolVersion();
qInfo() << " Username:" << client->username() << " Password:" << !client->password().isEmpty();
qInfo() << " Client ID:" << client->clientId() << "Keep Alive:" << client->keepAlive();
return client;
}