1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qmqttclient.h"
5#include "qmqttclient_p.h"
6
7#include <QtCore/QLoggingCategory>
8#include <QtCore/QUuid>
9#include <QtCore/QtEndian>
10
11QT_BEGIN_NAMESPACE
12
13Q_LOGGING_CATEGORY(lcMqttClient, "qt.mqtt.client")
14
15/*!
16 \class QMqttClient
17
18 \inmodule QtMqtt
19 \brief The QMqttClient class represents the central access communicating
20 with an MQTT broker.
21
22 An MQTT client is a program or device that uses MQTT to create a network
23 connection to an MQTT server, also called a \e broker. The connection
24 request must contain a unique client identifier. Optionally, it can contain
25 a Will Topic, Will Message, user name, and password.
26
27 Once a connection is created, a client can send messages that other clients
28 might be interested in receiving, subscribe to request notifications on
29 topics, unsubscribe to remove a request for notifications, and disconnect
30 from the broker.
31*/
32
33/*!
34 \property QMqttClient::clientId
35 \brief This property holds the client's identifier value.
36
37 Each client needs to have a unique ID to be able to connect to an MQTT
38 broker. If no client ID is specified by the user, one will be generated
39 automatically when a connection is established.
40*/
41
42/*!
43 \property QMqttClient::hostname
44 \brief This property holds the hostname of the MQTT broker to connect to.
45
46 If no transport is specified via setTransport(), the client will instantiate
47 a socket connection to the specified hostname itself.
48*/
49
50/*!
51 \property QMqttClient::port
52 \brief This property holds the port to connect to the MQTT broker.
53
54 If no transport is specified via setTransport(), the client will instantiate
55 a socket connection to a host with this port number.
56*/
57
58/*!
59 \property QMqttClient::keepAlive
60 \brief This property holds the interval at which regular ping messages are
61 sent to the broker.
62
63 Once a connection to a broker is established, the client needs to send
64 frequent updates to propagate it can still be reached. The interval between
65 those updates is specified by this property.
66
67 The interval is specified in seconds.
68
69 If the broker does not respond within a grace period the connection will be
70 closed.
71
72 \sa autoKeepAlive(), requestPing(), pingResponseReceived()
73*/
74
75/*!
76 \property QMqttClient::protocolVersion
77 \brief This property holds the MQTT standard version to use for connections.
78
79 Specifies the version of the standard the client uses for connecting to a
80 broker. Valid values are:
81
82 \list
83 \li 3: MQTT standard version 3.1.
84 \li 4: MQTT standard version 3.1.1, often referred to MQTT 4.
85 \endlist
86*/
87
88/*!
89 \property QMqttClient::state
90 \brief This property holds the current state of the client.
91*/
92
93/*!
94 \property QMqttClient::error
95 \brief Specifies the current error of the client.
96*/
97
98/*!
99 \property QMqttClient::username
100 \brief This property holds the user name for connecting to a broker.
101*/
102
103/*!
104 \property QMqttClient::password
105 \brief This property holds the password for connecting to a broker.
106*/
107
108/*!
109 \property QMqttClient::cleanSession
110 \brief This property holds the state after connecting to a broker.
111*/
112
113/*!
114 \property QMqttClient::willTopic
115 \brief This property holds the Will Topic.
116*/
117
118/*!
119 \property QMqttClient::willMessage
120 \brief This property holds the payload of a Will Message.
121*/
122
123/*!
124 \property QMqttClient::willQoS
125 \brief This property holds the level of QoS for sending and storing the
126 Will Message.
127*/
128
129/*!
130 \property QMqttClient::willRetain
131 \brief This property holds whether the Will Message should be retained on
132 the broker for future subscribers to receive.
133*/
134
135/*!
136 \property QMqttClient::autoKeepAlive
137 \since 5.14
138 \brief This property holds whether the client will automatically manage
139 keep alive messages to the server.
140
141 If this property is \c true, then the client will automatically send a
142 ping message to the server at the keepAlive interval.
143
144 Otherwise, a user will have to manually invoke requestPing
145 within the specified interval of the connection. If no ping has been
146 sent within the interval, the server will disconnect.
147
148 The default of this property is \c true.
149
150 \sa keepAlive(), requestPing(), serverConnectionProperties(), pingResponseReceived()
151*/
152
153/*!
154 \enum QMqttClient::TransportType
155
156 This enum type specifies the connection method to be used to instantiate a
157 connection to a broker.
158
159 \value IODevice
160 The transport uses a class based on a QIODevice.
161 \value AbstractSocket
162 The transport uses a class based on a QAbstractSocket.
163 \value SecureSocket
164 The transport uses a class based on a QSslSocket.
165*/
166
167/*!
168 \enum QMqttClient::ClientState
169
170 This enum type specifies the states a client can enter.
171
172 \value Disconnected
173 The client is disconnected from the broker.
174 \value Connecting
175 A connection request has been made, but the broker has not approved
176 the connection yet.
177 \value Connected
178 The client is connected to the broker.
179*/
180
181/*!
182 \enum QMqttClient::ClientError
183
184 This enum type specifies the error state of a client.
185
186 \value NoError
187 No error occurred.
188 \value InvalidProtocolVersion
189 The broker does not accept a connection using the specified protocol
190 version.
191 \value IdRejected
192 The client ID is malformed. This might be related to its length.
193 \value ServerUnavailable
194 The network connection has been established, but the service is
195 unavailable on the broker side.
196 \value BadUsernameOrPassword
197 The data in the username or password is malformed.
198 \value NotAuthorized
199 The client is not authorized to connect.
200 \value TransportInvalid
201 The underlying transport caused an error. For example, the connection
202 might have been interrupted unexpectedly.
203 \value ProtocolViolation
204 The client encountered a protocol violation, and therefore closed the
205 connection.
206 \value UnknownError
207 An unknown error occurred.
208 \value Mqtt5SpecificError
209 The error is related to MQTT protocol level 5. A reason code might
210 provide more details.
211*/
212
213/*!
214 \enum QMqttClient::ProtocolVersion
215
216 This enum specifies the protocol version of the MQTT standard to use during
217 communication with a broker.
218
219 \value MQTT_3_1
220 MQTT Standard 3.1
221 \value MQTT_3_1_1
222 MQTT Standard 3.1.1, publicly referred to as version 4
223 \value MQTT_5_0
224 MQTT Standard 5.0
225*/
226
227/*!
228 \fn QMqttClient::connected()
229
230 This signal is emitted when a connection has been established.
231*/
232
233/*!
234 \fn QMqttClient::disconnected()
235
236 This signal is emitted when a connection has been closed. A connection may
237 be closed when disconnectFromHost() is called or when the broker
238 disconnects.
239*/
240
241/*!
242 \fn QMqttClient::messageReceived(const QByteArray &message, const QMqttTopicName &topic)
243
244 This signal is emitted when a new message has been received. The category of
245 the message is specified by \a topic with the content being \a message.
246*/
247
248/*!
249 \fn QMqttClient::messageStatusChanged(qint32 id, QMqtt::MessageStatus s, const QMqttMessageStatusProperties &properties);
250 \since 5.12
251
252 This signal is emitted when the status for the message identified by \a id
253 changes. \a s specifies the new status of the message, and
254 \a properties specify additional properties provided by the server.
255*/
256
257/*!
258 \fn QMqttClient::messageSent(qint32 id)
259
260 Indicates that a message that was sent via the publish() function has been
261 received by the broker. The \a id is the same as returned by \c publish() to
262 help tracking the status of the message.
263*/
264
265/*!
266 \fn QMqttClient::pingResponseReceived()
267
268 This signal is emitted after the broker responds to a requestPing() call or
269 a keepAlive() ping message, and the connection is still valid.
270*/
271
272/*!
273 \fn QMqttClient::brokerSessionRestored()
274
275 This signal is emitted after a client has successfully connected to a broker
276 with the cleanSession property set to \c false, and the broker has restored
277 the session.
278
279 Sessions can be restored if a client has connected previously using the same
280 clientId.
281*/
282
283/*!
284 \since 5.12
285 \fn QMqttClient::authenticationRequested(const QMqttAuthenticationProperties &p)
286
287 This signal is emitted after a client invoked QMqttClient::connectToHost or
288 QMqttClient::connectToHostEncrypted and before the connection is
289 established. In extended authentication, a broker might request additional
290 details which need to be provided by invoking QMqttClient::authenticate.
291 \a p specifies properties provided by the broker.
292
293 \note Extended authentication is part of the MQTT 5.0 standard and can
294 only be used when the client specifies MQTT_5_0 as ProtocolVersion.
295
296 \sa authenticationFinished(), authenticate()
297*/
298
299/*!
300 \since 5.12
301 \fn QMqttClient::authenticationFinished(const QMqttAuthenticationProperties &p)
302
303 This signal is emitted after extended authentication has finished. \a p
304 specifies available details on the authentication process.
305
306 After successful authentication QMqttClient::connected is emitted.
307
308 \note Extended authentication is part of the MQTT 5.0 standard and can
309 only be used when the client specifies MQTT_5_0 as ProtocolVersion.
310
311 \sa authenticationRequested(), authenticate()
312*/
313
314/*!
315 Creates a new MQTT client instance with the specified \a parent.
316 */
317QMqttClient::QMqttClient(QObject *parent) : QObject(*(new QMqttClientPrivate(this)), parent)
318{
319 Q_D(QMqttClient);
320 d->m_connection.setClientPrivate(d);
321}
322
323/*!
324 Deletes a MQTT client. If the MQTT client was not already disconnected from the MQTT broker,
325 it will be disconnected from automatically.
326*/
327QMqttClient::~QMqttClient()
328{
329 Q_D(QMqttClient);
330 if (d->m_connection.internalState() == QMqttConnection::BrokerConnected) {
331 d->m_connection.setClientDestruction();
332 disconnectFromHost();
333 }
334}
335
336/*!
337 Sets the transport to \a device. A transport can be either a socket type
338 or derived from QIODevice and is specified by \a transport.
339
340 \note The transport can only be exchanged if the MQTT client is in the
341 \l Disconnected state.
342
343 \note Setting a custom transport for a client does not pass over responsibility
344 on connection management. The transport has to be opened for QIODevice based
345 transports or connected for socket type transports before calling QMqttClient::connectToHost().
346 */
347void QMqttClient::setTransport(QIODevice *device, QMqttClient::TransportType transport)
348{
349 Q_D(QMqttClient);
350
351 if (d->m_state != Disconnected) {
352 qCDebug(lcMqttClient) << "Changing transport layer while connected is not possible.";
353 return;
354 }
355 d->m_connection.setTransport(device, transport);
356}
357
358/*!
359 Returns the transport used for communication with the broker.
360 */
361QIODevice *QMqttClient::transport() const
362{
363 Q_D(const QMqttClient);
364 return d->m_connection.transport();
365}
366
367/*!
368 Adds a new subscription to receive notifications on \a topic. The parameter
369 \a qos specifies the level at which security messages are received. For more
370 information about the available QoS levels, see \l {Quality of Service}.
371
372 This function returns a pointer to a \l QMqttSubscription. If the same topic
373 is subscribed twice, the return value points to the same subscription
374 instance. The MQTT client is the owner of the subscription.
375 */
376QMqttSubscription *QMqttClient::subscribe(const QMqttTopicFilter &topic, quint8 qos)
377{
378 return subscribe(topic, properties: QMqttSubscriptionProperties(), qos);
379}
380
381/*!
382 \since 5.12
383
384 Adds a new subscription to receive notifications on \a topic. The parameter
385 \a properties specifies additional subscription properties to be validated
386 by the broker. The parameter \a qos specifies the level at which security
387 messages are received. For more information about the available QoS levels,
388 see \l {Quality of Service}.
389
390 This function returns a pointer to a \l QMqttSubscription. If the same topic
391 is subscribed twice, the return value points to the same subscription
392 instance. The MQTT client is the owner of the subscription.
393
394 \note \a properties will only be passed to the broker when the client
395 specifies MQTT_5_0 as ProtocolVersion.
396*/
397QMqttSubscription *QMqttClient::subscribe(const QMqttTopicFilter &topic, const QMqttSubscriptionProperties &properties, quint8 qos)
398{
399 Q_D(QMqttClient);
400
401 if (d->m_state != QMqttClient::Connected)
402 return nullptr;
403
404 return d->m_connection.sendControlSubscribe(topic, qos, properties);
405}
406
407/*!
408 Unsubscribes from \a topic. No notifications will be sent to any of the
409 subscriptions made by calling subscribe().
410
411 \note If a client disconnects from a broker without unsubscribing, the
412 broker will store all messages and publish them on the next reconnect.
413 */
414void QMqttClient::unsubscribe(const QMqttTopicFilter &topic)
415{
416 unsubscribe(topic, properties: QMqttUnsubscriptionProperties());
417}
418
419/*!
420 \since 5.12
421
422 Unsubscribes from \a topic. No notifications will be sent to any of the
423 subscriptions made by calling subscribe(). \a properties specifies
424 additional user properties to be passed to the broker.
425
426 \note If a client disconnects from a broker without unsubscribing, the
427 broker will store all messages and publish them on the next reconnect.
428
429 \note \a properties will only be passed to the broker when the client
430 specifies MQTT_5_0 as ProtocolVersion.
431*/
432void QMqttClient::unsubscribe(const QMqttTopicFilter &topic, const QMqttUnsubscriptionProperties &properties)
433{
434 Q_D(QMqttClient);
435 d->m_connection.sendControlUnsubscribe(topic, properties);
436}
437
438/*!
439 Publishes a \a message to the broker with the specified \a topic. \a qos
440 specifies the QoS level required for transferring the message.
441
442 If \a retain is set to \c true, the message will stay on the broker for
443 other clients to connect and receive the message.
444
445 Returns an ID that is used internally to identify the message.
446*/
447qint32 QMqttClient::publish(const QMqttTopicName &topic, const QByteArray &message, quint8 qos, bool retain)
448{
449 return publish(topic, properties: QMqttPublishProperties(), message, qos, retain);
450}
451
452/*!
453 \since 5.12
454
455 Publishes a \a message to the broker with the specified \a properties and
456 \a topic. \a qos specifies the QoS level required for transferring
457 the message.
458
459 If \a retain is set to \c true, the message will stay on the broker for
460 other clients to connect and receive the message.
461
462 Returns an ID that is used internally to identify the message.
463
464 \note \a properties will only be passed to the broker when the client
465 specifies MQTT_5_0 as ProtocolVersion.
466*/
467qint32 QMqttClient::publish(const QMqttTopicName &topic, const QMqttPublishProperties &properties,
468 const QByteArray &message, quint8 qos, bool retain)
469{
470 Q_D(QMqttClient);
471 if (qos > 2)
472 return -1;
473
474 if (d->m_state != QMqttClient::Connected)
475 return -1;
476
477 return d->m_connection.sendControlPublish(topic, message, qos, retain, properties);
478}
479
480/*!
481 Sends a ping message to the broker and expects a reply.
482
483 If the connection is active and \l autoKeepAlive is \c true, then calling this
484 function will fail as the client is responsible for managing this process.
485
486 Using \c requestPing() manually requires a call every time within the \l keepAlive
487 interval as long as the connection is active.
488
489 To check whether the ping is successful, connect to the
490 \l pingResponseReceived() signal.
491
492 Returns \c true if the ping request could be sent.
493
494 \sa pingResponseReceived(), autoKeepAlive(), keepAlive()
495 */
496bool QMqttClient::requestPing()
497{
498 Q_D(QMqttClient);
499 return d->m_connection.sendControlPingRequest(isAuto: false);
500}
501
502QString QMqttClient::hostname() const
503{
504 Q_D(const QMqttClient);
505 return d->m_hostname;
506}
507
508quint16 QMqttClient::port() const
509{
510 Q_D(const QMqttClient);
511 return d->m_port;
512}
513
514/*!
515 Initiates a connection to the MQTT broker.
516 */
517void QMqttClient::connectToHost()
518{
519 connectToHost(encrypted: false, sslPeerName: QString());
520}
521
522#ifndef QT_NO_SSL
523/*!
524 \since 5.14
525 Initiates an encrypted connection to the MQTT broker.
526
527 \a conf specifies the SSL configuration to be used for the connection
528 */
529void QMqttClient::connectToHostEncrypted(const QSslConfiguration &conf)
530{
531 Q_D(QMqttClient);
532 d->m_connection.m_sslConfiguration = conf;
533 connectToHost(encrypted: true, sslPeerName: QString());
534}
535#endif
536
537void QMqttClient::connectToHost(bool encrypted, const QString &sslPeerName)
538{
539 Q_D(QMqttClient);
540
541 if (state() == QMqttClient::Connecting) {
542 qCDebug(lcMqttClient) << "Connection request currently ongoing.";
543 return;
544 }
545
546 if (state() == QMqttClient::Connected) {
547 qCDebug(lcMqttClient) << "Already connected to a broker. Rejecting connection request.";
548 return;
549 }
550
551 if (!d->m_connection.ensureTransport(createSecureIfNeeded: encrypted)) {
552 qCDebug(lcMqttClient) << "Could not ensure connection.";
553 d->setStateAndError(s: Disconnected, e: TransportInvalid);
554 return;
555 }
556 d->m_error = QMqttClient::NoError; // Fresh reconnect, unset error
557 d->setStateAndError(s: Connecting);
558
559 if (d->m_cleanSession)
560 d->m_connection.cleanSubscriptions();
561
562 if (!d->m_connection.ensureTransportOpen(sslPeerName)) {
563 qCDebug(lcMqttClient) << "Could not ensure that connection is open.";
564 d->setStateAndError(s: Disconnected, e: TransportInvalid);
565 return;
566 }
567
568 // Once transport has connected, it will invoke
569 // QMqttConnection::sendControlConnect to
570 // handshake with the broker
571}
572
573/*!
574 Disconnects from the MQTT broker.
575 */
576void QMqttClient::disconnectFromHost()
577{
578 Q_D(QMqttClient);
579
580 switch (d->m_connection.internalState()) {
581 case QMqttConnection::BrokerConnected:
582 case QMqttConnection::ClientDestruction:
583 d->m_connection.sendControlDisconnect();
584 break;
585 case QMqttConnection::BrokerDisconnected:
586 break;
587 case QMqttConnection::BrokerConnecting:
588 case QMqttConnection::BrokerWaitForConnectAck:
589 d->m_connection.m_transport->close();
590 break;
591 }
592}
593
594QMqttClient::ClientState QMqttClient::state() const
595{
596 Q_D(const QMqttClient);
597 return d->m_state;
598}
599
600QString QMqttClient::username() const
601{
602 Q_D(const QMqttClient);
603 return d->m_username;
604}
605
606QString QMqttClient::password() const
607{
608 Q_D(const QMqttClient);
609 return d->m_password;
610}
611
612bool QMqttClient::cleanSession() const
613{
614 Q_D(const QMqttClient);
615 return d->m_cleanSession;
616}
617
618QString QMqttClient::willTopic() const
619{
620 Q_D(const QMqttClient);
621 return d->m_willTopic;
622}
623
624quint8 QMqttClient::willQoS() const
625{
626 Q_D(const QMqttClient);
627 return d->m_willQoS;
628}
629
630QByteArray QMqttClient::willMessage() const
631{
632 Q_D(const QMqttClient);
633 return d->m_willMessage;
634}
635
636bool QMqttClient::willRetain() const
637{
638 Q_D(const QMqttClient);
639 return d->m_willRetain;
640}
641
642bool QMqttClient::autoKeepAlive() const
643{
644 Q_D(const QMqttClient);
645 return d->m_autoKeepAlive;
646}
647
648/*!
649 \since 5.12
650
651 Sets the connection properties to \a prop. \l QMqttConnectionProperties
652 can be used to ask the server to use a specific feature set. After a
653 connection request the server response can be obtained by calling
654 \l QMqttClient::serverConnectionProperties.
655
656 \note The connection properties can only be set if the MQTT client is in the
657 \l Disconnected state.
658
659 \note QMqttConnectionProperties can only be used when the client specifies
660 MQTT_5_0 as ProtocolVersion.
661*/
662void QMqttClient::setConnectionProperties(const QMqttConnectionProperties &prop)
663{
664 Q_D(QMqttClient);
665 d->m_connectionProperties = prop;
666}
667
668/*!
669 \since 5.12
670
671 Returns the connection properties the client requests to the broker.
672
673 \note QMqttConnectionProperties can only be used when the client specifies
674 MQTT_5_0 as ProtocolVersion.
675*/
676QMqttConnectionProperties QMqttClient::connectionProperties() const
677{
678 Q_D(const QMqttClient);
679 return d->m_connectionProperties;
680}
681
682/*!
683 \since 5.12
684
685 Sets the last will properties to \a prop. QMqttLastWillProperties allows
686 to set additional features for the last will message stored at the broker.
687
688 \note The connection properties can only be set if the MQTT client is in the
689 \l Disconnected state.
690
691 \note QMqttLastWillProperties can only be used when the client specifies
692 MQTT_5_0 as ProtocolVersion.
693*/
694void QMqttClient::setLastWillProperties(const QMqttLastWillProperties &prop)
695{
696 Q_D(QMqttClient);
697 d->m_lastWillProperties = prop;
698}
699
700/*!
701 \since 5.12
702
703 Returns the last will properties.
704
705 \note QMqttLastWillProperties can only be used when the client specifies
706 MQTT_5_0 as ProtocolVersion.
707*/
708QMqttLastWillProperties QMqttClient::lastWillProperties() const
709{
710 Q_D(const QMqttClient);
711 return d->m_lastWillProperties;
712}
713
714/*!
715 \since 5.12
716
717 Returns the QMqttServerConnectionProperties the broker returned after a
718 connection attempt.
719
720 This can be used to verify that client side connection properties set by
721 QMqttClient::setConnectionProperties have been accepted by the broker. Also,
722 in case of a failed connection attempt, it can be used for connection
723 diagnostics.
724
725 \note QMqttServerConnectionProperties can only be used when the client
726 specifies MQTT_5_0 as ProtocolVersion.
727
728 \sa connectionProperties()
729*/
730QMqttServerConnectionProperties QMqttClient::serverConnectionProperties() const
731{
732 Q_D(const QMqttClient);
733 return d->m_serverConnectionProperties;
734}
735
736/*!
737 \since 5.12
738
739 Sends an authentication request to the broker. \a prop specifies
740 the required information to fulfill the authentication request.
741
742 This function should only be called after a
743 QMqttClient::authenticationRequested signal has been emitted.
744
745 \note Extended authentication is part of the MQTT 5.0 standard and can
746 only be used when the client specifies MQTT_5_0 as ProtocolVersion.
747
748 \sa authenticationRequested(), authenticationFinished()
749*/
750void QMqttClient::authenticate(const QMqttAuthenticationProperties &prop)
751{
752 Q_D(QMqttClient);
753 if (protocolVersion() != QMqttClient::MQTT_5_0) {
754 qCDebug(lcMqttClient) << "Authentication is only supported on protocol level 5.";
755 return;
756 }
757 if (state() == QMqttClient::Disconnected) {
758 qCDebug(lcMqttClient) << "Cannot send authentication request while disconnected.";
759 return;
760 }
761 d->m_connection.sendControlAuthenticate(properties: prop);
762}
763
764QMqttClient::ClientError QMqttClient::error() const
765{
766 Q_D(const QMqttClient);
767 return d->m_error;
768}
769
770QMqttClient::ProtocolVersion QMqttClient::protocolVersion() const
771{
772 Q_D(const QMqttClient);
773 return d->m_protocolVersion;
774}
775
776QString QMqttClient::clientId() const
777{
778 Q_D(const QMqttClient);
779 return d->m_clientId;
780}
781
782quint16 QMqttClient::keepAlive() const
783{
784 Q_D(const QMqttClient);
785 return d->m_keepAlive;
786}
787
788void QMqttClient::setHostname(const QString &hostname)
789{
790 Q_D(QMqttClient);
791
792 if (state() != QMqttClient::Disconnected) {
793 qCDebug(lcMqttClient) << "Changing hostname while connected is not possible.";
794 return;
795 }
796
797 if (d->m_hostname == hostname)
798 return;
799
800 d->m_hostname = hostname;
801 emit hostnameChanged(hostname);
802}
803
804void QMqttClient::setPort(quint16 port)
805{
806 Q_D(QMqttClient);
807
808 if (state() != QMqttClient::Disconnected) {
809 qCDebug(lcMqttClient) << "Changing port while connected is not possible.";
810 return;
811 }
812
813 if (d->m_port == port)
814 return;
815
816 d->m_port = port;
817 emit portChanged(port);
818}
819
820void QMqttClient::setClientId(const QString &clientId)
821{
822 Q_D(QMqttClient);
823
824 if (state() != QMqttClient::Disconnected) {
825 qCDebug(lcMqttClient) << "Changing client ID while connected is not possible.";
826 return;
827 }
828 d->setClientId(clientId);
829}
830
831void QMqttClient::setKeepAlive(quint16 keepAlive)
832{
833 Q_D(QMqttClient);
834 if (d->m_keepAlive == keepAlive)
835 return;
836
837 if (state() != QMqttClient::Disconnected) {
838 qCDebug(lcMqttClient) << "Changing keepAlive while connected is not possible.";
839 return;
840 }
841
842 d->m_keepAlive = keepAlive;
843 emit keepAliveChanged(keepAlive);
844}
845
846void QMqttClient::setProtocolVersion(ProtocolVersion protocolVersion)
847{
848 Q_D(QMqttClient);
849
850 if (state() != QMqttClient::Disconnected) {
851 qCDebug(lcMqttClient) << "Changing protocol version while connected is not possible.";
852 return;
853 }
854
855 if (d->m_protocolVersion == protocolVersion)
856 return;
857
858 if (protocolVersion < 3 || protocolVersion > 5)
859 return;
860
861 d->m_protocolVersion = protocolVersion;
862 emit protocolVersionChanged(protocolVersion);
863}
864
865void QMqttClient::setState(ClientState state)
866{
867 Q_D(QMqttClient);
868 if (d->m_state == state)
869 return;
870
871 d->m_state = state;
872 emit stateChanged(state);
873 if (d->m_state == QMqttClient::Disconnected)
874 emit disconnected();
875 else if (d->m_state == QMqttClient::Connected)
876 emit connected();
877}
878
879void QMqttClient::setUsername(const QString &username)
880{
881 Q_D(QMqttClient);
882
883 if (state() != QMqttClient::Disconnected) {
884 qCDebug(lcMqttClient) << "Changing username while connected is not possible.";
885 return;
886 }
887
888 if (d->m_username == username)
889 return;
890
891 d->m_username = username;
892 emit usernameChanged(username);
893}
894
895void QMqttClient::setPassword(const QString &password)
896{
897 Q_D(QMqttClient);
898
899 if (state() != QMqttClient::Disconnected) {
900 qCDebug(lcMqttClient) << "Changing password while connected is not possible.";
901 return;
902 }
903
904 if (d->m_password == password)
905 return;
906
907 d->m_password = password;
908 emit passwordChanged(password);
909}
910
911void QMqttClient::setCleanSession(bool cleanSession)
912{
913 Q_D(QMqttClient);
914
915 if (state() != QMqttClient::Disconnected) {
916 qCDebug(lcMqttClient) << "Changing clean session while connected is not possible.";
917 return;
918 }
919
920 if (d->m_cleanSession == cleanSession)
921 return;
922
923 d->m_cleanSession = cleanSession;
924 emit cleanSessionChanged(cleanSession);
925}
926
927void QMqttClient::setWillTopic(const QString &willTopic)
928{
929 Q_D(QMqttClient);
930
931 if (state() != QMqttClient::Disconnected) {
932 qCDebug(lcMqttClient) << "Changing will topic while connected is not possible.";
933 return;
934 }
935
936 if (d->m_willTopic == willTopic)
937 return;
938
939 d->m_willTopic = willTopic;
940 emit willTopicChanged(willTopic);
941}
942
943void QMqttClient::setWillQoS(quint8 willQoS)
944{
945 Q_D(QMqttClient);
946
947 if (state() != QMqttClient::Disconnected) {
948 qCDebug(lcMqttClient) << "Changing will qos while connected is not possible.";
949 return;
950 }
951
952 if (d->m_willQoS == willQoS)
953 return;
954
955 d->m_willQoS = willQoS;
956 emit willQoSChanged(willQoS);
957}
958
959void QMqttClient::setWillMessage(const QByteArray &willMessage)
960{
961 Q_D(QMqttClient);
962
963 if (state() != QMqttClient::Disconnected) {
964 qCDebug(lcMqttClient) << "Changing will message while connected is not possible.";
965 return;
966 }
967
968 if (d->m_willMessage == willMessage)
969 return;
970
971 d->m_willMessage = willMessage;
972 emit willMessageChanged(willMessage);
973}
974
975void QMqttClient::setWillRetain(bool willRetain)
976{
977 Q_D(QMqttClient);
978
979 if (state() != QMqttClient::Disconnected) {
980 qCDebug(lcMqttClient) << "Changing will retain while connected is not possible.";
981 return;
982 }
983
984 if (d->m_willRetain == willRetain)
985 return;
986
987 d->m_willRetain = willRetain;
988 emit willRetainChanged(willRetain);
989}
990
991void QMqttClient::setAutoKeepAlive(bool autoKeepAlive)
992{
993 Q_D(QMqttClient);
994
995 if (state() != QMqttClient::Disconnected) {
996 qCDebug(lcMqttClient) << "Changing autoKeepAlive while connected is not possible.";
997 return;
998 }
999
1000 if (d->m_autoKeepAlive == autoKeepAlive)
1001 return;
1002
1003 d->m_autoKeepAlive = autoKeepAlive;
1004 emit autoKeepAliveChanged(autoKeepAlive: d->m_autoKeepAlive);
1005}
1006
1007void QMqttClient::setError(ClientError e)
1008{
1009 Q_D(QMqttClient);
1010 if (d->m_error == e)
1011 return;
1012
1013 d->m_error = e;
1014 emit errorChanged(error: d->m_error);
1015}
1016
1017QMqttClientPrivate::QMqttClientPrivate(QMqttClient *c)
1018 : QObjectPrivate()
1019{
1020 m_client = c;
1021 m_clientId = QUuid::createUuid().toString();
1022 m_clientId.remove(c: QLatin1Char('{'));
1023 m_clientId.remove(c: QLatin1Char('}'));
1024 m_clientId.remove(c: QLatin1Char('-'));
1025 m_clientId.resize(size: 23);
1026#ifdef QT_BUILD_INTERNAL
1027 // Some test servers require a username token
1028 if (qEnvironmentVariableIsSet(varName: "QT_MQTT_TEST_USERNAME"))
1029 m_username = qEnvironmentVariable(varName: "QT_MQTT_TEST_USERNAME");
1030 if (qEnvironmentVariableIsSet(varName: "QT_MQTT_TEST_PASSWORD"))
1031 m_password = qEnvironmentVariable(varName: "QT_MQTT_TEST_PASSWORD");
1032 if (qEnvironmentVariableIsSet(varName: "QT_MQTT_TEST_CLIENTID"))
1033 m_clientId = qEnvironmentVariable(varName: "QT_MQTT_TEST_CLIENTID");
1034#endif
1035}
1036
1037QMqttClientPrivate::~QMqttClientPrivate()
1038{
1039}
1040
1041void QMqttClientPrivate::setStateAndError(QMqttClient::ClientState s, QMqttClient::ClientError e)
1042{
1043 Q_Q(QMqttClient);
1044
1045 if (e != QMqttClient::NoError)
1046 q->setError(e);
1047 q->setState(s);
1048}
1049
1050void QMqttClientPrivate::setClientId(const QString &id)
1051{
1052 Q_Q(QMqttClient);
1053
1054 if (m_clientId == id)
1055 return;
1056
1057 m_clientId = id;
1058 emit q->clientIdChanged(clientId: id);
1059}
1060
1061QT_END_NAMESPACE
1062

source code of qtmqtt/src/mqtt/qmqttclient.cpp