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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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