1 | // Copyright (C) 2017 Witekio. |
2 | // Copyright (C) 2018 The Qt Company Ltd. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
4 | |
5 | #include "qcoapclient_p.h" |
6 | #include "qcoapprotocol_p.h" |
7 | #include "qcoapreply.h" |
8 | #include "qcoapresourcediscoveryreply.h" |
9 | #include "qcoapnamespace.h" |
10 | #include "qcoapsecurityconfiguration.h" |
11 | #include "qcoapqudpconnection_p.h" |
12 | #include "qcoaprequest_p.h" |
13 | #include "qcoapreply_p.h" |
14 | #include <QtCore/qiodevice.h> |
15 | #include <QtCore/qurl.h> |
16 | #include <QtCore/qloggingcategory.h> |
17 | #include <QtNetwork/qudpsocket.h> |
18 | |
19 | QT_BEGIN_NAMESPACE |
20 | |
21 | Q_LOGGING_CATEGORY(lcCoapClient, "qt.coap.client" ) |
22 | |
23 | QCoapClientPrivate::QCoapClientPrivate(QCoapProtocol *protocol, QCoapConnection *connection) |
24 | : protocol(protocol) |
25 | , connection(connection) |
26 | , workerThread(new QThread) |
27 | { |
28 | protocol->moveToThread(thread: workerThread); |
29 | connection->moveToThread(thread: workerThread); |
30 | workerThread->start(); |
31 | } |
32 | |
33 | QCoapClientPrivate::~QCoapClientPrivate() |
34 | { |
35 | workerThread->quit(); |
36 | workerThread->wait(); |
37 | delete workerThread; |
38 | delete protocol; |
39 | delete connection; |
40 | } |
41 | |
42 | /*! |
43 | \class QCoapClient |
44 | \inmodule QtCoap |
45 | |
46 | \brief The QCoapClient class allows the application to |
47 | send CoAP requests and receive replies. |
48 | |
49 | \reentrant |
50 | |
51 | The QCoapClient class contains signals that get triggered when the |
52 | reply of a sent request has arrived. |
53 | |
54 | The application can use a QCoapClient to send requests over a CoAP |
55 | network. It provides functions for standard requests: each returns a QCoapReply object, |
56 | to which the response data shall be delivered; this can be read when the finished() |
57 | signal arrives. |
58 | |
59 | A simple request can be sent with: |
60 | \code |
61 | QCoapClient *client = new QCoapClient(this); |
62 | connect(client, &QCoapClient::finished, this, &TestClass::slotFinished); |
63 | client->get(QCoapRequest(Qurl("coap://coap.me/test"))); |
64 | \endcode |
65 | |
66 | \note After processing of the request has finished, it is the responsibility |
67 | of the user to delete the QCoapReply object at an appropriate time. Do not |
68 | directly delete it inside the slot connected to finished(). You can use the |
69 | deleteLater() function. |
70 | |
71 | You can also use an \e observe request. This can be used as above, or more |
72 | conveniently with the QCoapReply::notified() signal: |
73 | \code |
74 | QCoapRequest request = QCoapRequest(Qurl("coap://coap.me/obs")); |
75 | QCoapReply *reply = client->observe(request); |
76 | connect(reply, &QCoapReply::notified, this, &TestClass::slotNotified); |
77 | \endcode |
78 | |
79 | And the observation can be cancelled with: |
80 | \code |
81 | client->cancelObserve(reply); |
82 | \endcode |
83 | |
84 | When a reply arrives, the QCoapClient emits a finished() signal. |
85 | |
86 | \note For a discovery request, the returned object is a QCoapResourceDiscoveryReply. |
87 | It can be used the same way as a QCoapReply but contains also a list of |
88 | resources. |
89 | |
90 | \sa QCoapRequest, QCoapReply, QCoapResourceDiscoveryReply |
91 | */ |
92 | |
93 | /*! |
94 | \fn void QCoapClient::finished(QCoapReply *reply) |
95 | |
96 | This signal is emitted along with the \l QCoapReply::finished() signal |
97 | whenever a CoAP reply is received, after either a success or an error. |
98 | The \a reply parameter will contain a pointer to the reply that has just |
99 | been received. |
100 | |
101 | \sa error(), QCoapReply::finished(), QCoapReply::error() |
102 | */ |
103 | |
104 | /*! |
105 | \fn void QCoapClient::responseToMulticastReceived(QCoapReply *reply, |
106 | const QCoapMessage &message, |
107 | const QHostAddress &sender) |
108 | |
109 | This signal is emitted when a unicast response to a multicast request |
110 | arrives. The \a reply parameter contains a pointer to the reply that has just |
111 | been received, \a message contains the payload and the message details, |
112 | and \a sender contains the sender address. |
113 | |
114 | \sa error(), QCoapReply::finished(), QCoapReply::error() |
115 | */ |
116 | |
117 | /*! |
118 | \fn void QCoapClient::error(QCoapReply *reply, QtCoap::Error error) |
119 | |
120 | This signal is emitted whenever an error occurs. The \a reply parameter |
121 | can be \nullptr if the error is not related to a specific QCoapReply. The |
122 | \a error parameter contains the error code. |
123 | |
124 | \sa finished(), QCoapReply::error(), QCoapReply::finished() |
125 | */ |
126 | |
127 | /*! |
128 | Constructs a QCoapClient object for the given \a securityMode and |
129 | sets \a parent as the parent object. |
130 | |
131 | The default for \a securityMode is QtCoap::NoSecurity, which |
132 | disables security. |
133 | |
134 | This connects using a QCoapQUdpConnection; to use a custom transport, |
135 | sub-class QCoapConnection and pass an instance to one of the other |
136 | constructors. |
137 | */ |
138 | QCoapClient::QCoapClient(QtCoap::SecurityMode securityMode, QObject *parent) : |
139 | QObject(*new QCoapClientPrivate(new QCoapProtocol, new QCoapQUdpConnection(securityMode)), |
140 | parent) |
141 | { |
142 | Q_D(QCoapClient); |
143 | |
144 | qRegisterMetaType<QCoapReply *>(); |
145 | qRegisterMetaType<QCoapMessage>(); |
146 | qRegisterMetaType<QPointer<QCoapReply>>(); |
147 | qRegisterMetaType<QPointer<QCoapResourceDiscoveryReply>>(); |
148 | qRegisterMetaType<QCoapConnection *>(); |
149 | qRegisterMetaType<QtCoap::Error>(); |
150 | qRegisterMetaType<QtCoap::ResponseCode>(); |
151 | qRegisterMetaType<QtCoap::Method>(); |
152 | qRegisterMetaType<QtCoap::SecurityMode>(); |
153 | qRegisterMetaType<QtCoap::MulticastGroup>(); |
154 | // Requires a name, as this is a typedef |
155 | qRegisterMetaType<QCoapToken>(typeName: "QCoapToken" ); |
156 | qRegisterMetaType<QCoapMessageId>(typeName: "QCoapMessageId" ); |
157 | qRegisterMetaType<QAbstractSocket::SocketOption>(); |
158 | |
159 | connect(sender: d->connection, signal: &QCoapConnection::readyRead, context: d->protocol, |
160 | slot: [this](const QByteArray &data, const QHostAddress &sender) { |
161 | Q_D(QCoapClient); |
162 | d->protocol->d_func()->onFrameReceived(data, sender); |
163 | }); |
164 | connect(sender: d->connection, signal: &QCoapConnection::error, context: d->protocol, |
165 | slot: [this](QAbstractSocket::SocketError socketError) { |
166 | Q_D(QCoapClient); |
167 | d->protocol->d_func()->onConnectionError(error: socketError); |
168 | }); |
169 | |
170 | connect(sender: d->protocol, signal: &QCoapProtocol::finished, |
171 | context: this, slot: &QCoapClient::finished); |
172 | connect(sender: d->protocol, signal: &QCoapProtocol::responseToMulticastReceived, |
173 | context: this, slot: &QCoapClient::responseToMulticastReceived); |
174 | connect(sender: d->protocol, signal: &QCoapProtocol::error, |
175 | context: this, slot: &QCoapClient::error); |
176 | } |
177 | |
178 | /*! |
179 | \internal |
180 | |
181 | Sets the client's connection to \a customConnection. |
182 | */ |
183 | void QCoapClientPrivate::setConnection(QCoapConnection *customConnection) |
184 | { |
185 | Q_Q(QCoapClient); |
186 | |
187 | delete connection; |
188 | connection = customConnection; |
189 | |
190 | q->connect(sender: connection, signal: &QCoapConnection::readyRead, context: protocol, |
191 | slot: [this](const QByteArray &data, const QHostAddress &sender) { |
192 | protocol->d_func()->onFrameReceived(data, sender); |
193 | }); |
194 | q->connect(sender: connection, signal: &QCoapConnection::error, context: protocol, |
195 | slot: [this](QAbstractSocket::SocketError socketError) { |
196 | protocol->d_func()->onConnectionError(error: socketError); |
197 | }); |
198 | } |
199 | |
200 | /*! |
201 | Destroys the QCoapClient object and frees up any |
202 | resources. Note that QCoapReply objects that are returned from |
203 | this class have the QCoapClient set as their parents, which means that |
204 | they will be deleted along with it. |
205 | */ |
206 | QCoapClient::~QCoapClient() |
207 | { |
208 | qDeleteAll(c: findChildren<QCoapReply *>(aName: QString(), options: Qt::FindDirectChildrenOnly)); |
209 | } |
210 | |
211 | /*! |
212 | Sends the \a request using the GET method and returns a new QCoapReply object. |
213 | |
214 | \sa post(), put(), deleteResource(), observe(), discover() |
215 | */ |
216 | QCoapReply *QCoapClient::get(const QCoapRequest &request) |
217 | { |
218 | Q_D(QCoapClient); |
219 | |
220 | QCoapRequest copyRequest = QCoapRequestPrivate::createRequest(other: request, method: QtCoap::Method::Get, |
221 | isSecure: d->connection->isSecure()); |
222 | return d->sendRequest(request: copyRequest); |
223 | } |
224 | |
225 | /*! |
226 | \overload |
227 | |
228 | Sends a GET request to \a url and returns a new QCoapReply object. |
229 | |
230 | \sa post(), put(), deleteResource(), observe(), discover() |
231 | */ |
232 | QCoapReply *QCoapClient::get(const QUrl &url) |
233 | { |
234 | QCoapRequest request(url); |
235 | return get(request); |
236 | } |
237 | |
238 | /*! |
239 | Sends the \a request using the PUT method and returns a new QCoapReply |
240 | object. Uses \a data as the payload for this request. If \a data is empty, |
241 | the payload of the \a request will be used. |
242 | |
243 | \sa get(), post(), deleteResource(), observe(), discover() |
244 | */ |
245 | QCoapReply *QCoapClient::put(const QCoapRequest &request, const QByteArray &data) |
246 | { |
247 | Q_D(QCoapClient); |
248 | |
249 | QCoapRequest copyRequest = QCoapRequestPrivate::createRequest(other: request, method: QtCoap::Method::Put, |
250 | isSecure: d->connection->isSecure()); |
251 | if (!data.isEmpty()) |
252 | copyRequest.setPayload(data); |
253 | return d->sendRequest(request: copyRequest); |
254 | } |
255 | |
256 | /*! |
257 | \overload |
258 | |
259 | Sends the \a request using the PUT method and returns a new QCoapReply |
260 | object. Uses \a device content as the payload for this request. |
261 | A null device is treated as empty content. |
262 | |
263 | \note The device has to be open and readable before calling this function. |
264 | |
265 | \sa get(), post(), deleteResource(), observe(), discover() |
266 | */ |
267 | QCoapReply *QCoapClient::put(const QCoapRequest &request, QIODevice *device) |
268 | { |
269 | return put(request, data: device ? device->readAll() : QByteArray()); |
270 | } |
271 | |
272 | /*! |
273 | \overload |
274 | |
275 | Sends a PUT request to \a url and returns a new QCoapReply object. |
276 | Uses \a data as the payload for this request. |
277 | |
278 | \sa get(), post(), deleteResource(), observe(), discover() |
279 | */ |
280 | QCoapReply *QCoapClient::put(const QUrl &url, const QByteArray &data) |
281 | { |
282 | return put(request: QCoapRequest(url), data); |
283 | } |
284 | |
285 | /*! |
286 | Sends the \a request using the POST method and returns a new QCoapReply |
287 | object. Uses \a data as the payload for this request. If \a data is empty, |
288 | the payload of the \a request will be used. |
289 | |
290 | \sa get(), put(), deleteResource(), observe(), discover() |
291 | */ |
292 | QCoapReply *QCoapClient::post(const QCoapRequest &request, const QByteArray &data) |
293 | { |
294 | Q_D(QCoapClient); |
295 | |
296 | QCoapRequest copyRequest = QCoapRequestPrivate::createRequest(other: request, method: QtCoap::Method::Post, |
297 | isSecure: d->connection->isSecure()); |
298 | if (!data.isEmpty()) |
299 | copyRequest.setPayload(data); |
300 | return d->sendRequest(request: copyRequest); |
301 | } |
302 | |
303 | /*! |
304 | \overload |
305 | |
306 | Sends the \a request using the POST method and returns a new QCoapReply |
307 | object. Uses \a device content as the payload for this request. |
308 | A null device is treated as empty content. |
309 | |
310 | \note The device has to be open and readable before calling this function. |
311 | |
312 | \sa get(), put(), deleteResource(), observe(), discover() |
313 | */ |
314 | QCoapReply *QCoapClient::post(const QCoapRequest &request, QIODevice *device) |
315 | { |
316 | if (!device) |
317 | return nullptr; |
318 | |
319 | return post(request, data: device->readAll()); |
320 | } |
321 | |
322 | /*! |
323 | \overload |
324 | |
325 | Sends a POST request to \a url and returns a new QCoapReply object. |
326 | Uses \a data as the payload for this request. |
327 | |
328 | \sa get(), put(), deleteResource(), observe(), discover() |
329 | */ |
330 | QCoapReply *QCoapClient::post(const QUrl &url, const QByteArray &data) |
331 | { |
332 | return post(request: QCoapRequest(url), data); |
333 | } |
334 | |
335 | /*! |
336 | Sends the \a request using the DELETE method and returns a new QCoapReply |
337 | object. |
338 | |
339 | \sa get(), put(), post(), observe(), discover() |
340 | */ |
341 | QCoapReply *QCoapClient::deleteResource(const QCoapRequest &request) |
342 | { |
343 | Q_D(QCoapClient); |
344 | |
345 | QCoapRequest copyRequest = QCoapRequestPrivate::createRequest(other: request, method: QtCoap::Method::Delete, |
346 | isSecure: d->connection->isSecure()); |
347 | return d->sendRequest(request: copyRequest); |
348 | } |
349 | |
350 | /*! |
351 | \overload |
352 | |
353 | Sends a DELETE request to the target \a url. |
354 | |
355 | \sa get(), put(), post(), observe(), discover() |
356 | */ |
357 | QCoapReply *QCoapClient::deleteResource(const QUrl &url) |
358 | { |
359 | return deleteResource(request: QCoapRequest(url)); |
360 | } |
361 | |
362 | /*! |
363 | \overload |
364 | |
365 | Discovers the resources available at the endpoints which have joined |
366 | the \a group at the given \a port. Returns a new QCoapResourceDiscoveryReply |
367 | object which emits the \l QCoapResourceDiscoveryReply::discovered() signal whenever |
368 | a response arrives. The \a group is one of the CoAP multicast group addresses |
369 | and defaults to QtCoap::AllCoapNodesIPv4. |
370 | |
371 | Discovery path defaults to "/.well-known/core", but can be changed |
372 | by passing a different path to \a discoveryPath. Discovery is described in |
373 | \l{https://tools.ietf.org/html/rfc6690#section-1.2.1}{RFC 6690}. |
374 | |
375 | \sa get(), post(), put(), deleteResource(), observe() |
376 | */ |
377 | QCoapResourceDiscoveryReply *QCoapClient::discover(QtCoap::MulticastGroup group, int port, |
378 | const QString &discoveryPath) |
379 | { |
380 | Q_D(QCoapClient); |
381 | |
382 | QString base; |
383 | switch (group) { |
384 | case QtCoap::MulticastGroup::AllCoapNodesIPv4: |
385 | base = QStringLiteral("224.0.1.187" ); |
386 | break; |
387 | case QtCoap::MulticastGroup::AllCoapNodesIPv6LinkLocal: |
388 | base = QStringLiteral("ff02::fd" ); |
389 | break; |
390 | case QtCoap::MulticastGroup::AllCoapNodesIPv6SiteLocal: |
391 | base = QStringLiteral("ff05::fd" ); |
392 | break; |
393 | } |
394 | |
395 | QUrl discoveryUrl; |
396 | discoveryUrl.setHost(host: base); |
397 | discoveryUrl.setPath(path: discoveryPath); |
398 | discoveryUrl.setPort(port); |
399 | |
400 | QCoapRequest request = QCoapRequestPrivate::createRequest(other: QCoapRequest(discoveryUrl), |
401 | method: QtCoap::Method::Get, |
402 | isSecure: d->connection->isSecure()); |
403 | |
404 | return d->sendDiscovery(request); |
405 | } |
406 | |
407 | /*! |
408 | Discovers the resources available at the given \a url and returns |
409 | a new QCoapResourceDiscoveryReply object which emits the |
410 | \l QCoapResourceDiscoveryReply::discovered() signal whenever the response |
411 | arrives. |
412 | |
413 | Discovery path defaults to "/.well-known/core", but can be changed |
414 | by passing a different path to \a discoveryPath. Discovery is described in |
415 | \l{https://tools.ietf.org/html/rfc6690#section-1.2.1}{RFC 6690}. |
416 | |
417 | \sa get(), post(), put(), deleteResource(), observe() |
418 | */ |
419 | QCoapResourceDiscoveryReply *QCoapClient::discover(const QUrl &url, const QString &discoveryPath) |
420 | { |
421 | Q_D(QCoapClient); |
422 | |
423 | QUrl discoveryUrl(url); |
424 | discoveryUrl.setPath(path: url.path() + discoveryPath); |
425 | |
426 | QCoapRequest request = QCoapRequestPrivate::createRequest(other: QCoapRequest(discoveryUrl), |
427 | method: QtCoap::Method::Get, |
428 | isSecure: d->connection->isSecure()); |
429 | return d->sendDiscovery(request); |
430 | } |
431 | |
432 | /*! |
433 | Sends a request to observe the target \a request and returns |
434 | a new QCoapReply object which emits the \l QCoapReply::notified() |
435 | signal whenever a new notification arrives. |
436 | |
437 | \sa cancelObserve(), get(), post(), put(), deleteResource(), discover() |
438 | */ |
439 | QCoapReply *QCoapClient::observe(const QCoapRequest &request) |
440 | { |
441 | Q_D(QCoapClient); |
442 | |
443 | QCoapRequest copyRequest = QCoapRequestPrivate::createRequest(other: request, method: QtCoap::Method::Get, |
444 | isSecure: d->connection->isSecure()); |
445 | copyRequest.enableObserve(); |
446 | |
447 | return get(request: copyRequest); |
448 | } |
449 | |
450 | /*! |
451 | \overload |
452 | |
453 | Sends a request to observe the target \a url and returns |
454 | a new QCoapReply object which emits the \l QCoapReply::notified() |
455 | signal whenever a new notification arrives. |
456 | |
457 | \sa cancelObserve(), get(), post(), put(), deleteResource(), discover() |
458 | */ |
459 | QCoapReply *QCoapClient::observe(const QUrl &url) |
460 | { |
461 | return observe(request: QCoapRequest(url)); |
462 | } |
463 | |
464 | /*! |
465 | \overload |
466 | |
467 | Cancels the observation of a resource using the reply \a notifiedReply returned by |
468 | the observe() method. |
469 | |
470 | \sa observe() |
471 | */ |
472 | void QCoapClient::cancelObserve(QCoapReply *notifiedReply) |
473 | { |
474 | Q_D(QCoapClient); |
475 | QMetaObject::invokeMethod(obj: d->protocol, member: "cancelObserve" , |
476 | Q_ARG(QPointer<QCoapReply>, QPointer<QCoapReply>(notifiedReply))); |
477 | } |
478 | |
479 | /*! |
480 | \overload |
481 | |
482 | Cancels the observation of a resource identified by the \a url. |
483 | |
484 | \sa observe() |
485 | */ |
486 | void QCoapClient::cancelObserve(const QUrl &url) |
487 | { |
488 | Q_D(QCoapClient); |
489 | const auto adjustedUrl = QCoapRequestPrivate::adjustedUrl(url, secure: d->connection->isSecure()); |
490 | QMetaObject::invokeMethod(obj: d->protocol, member: "cancelObserve" , Q_ARG(QUrl, adjustedUrl)); |
491 | } |
492 | |
493 | /*! |
494 | Closes the open sockets and connections to free the transport. |
495 | |
496 | \note In the secure mode this needs to be called before changing |
497 | the security configuration or connecting to another server. |
498 | |
499 | \sa setSecurityConfiguration() |
500 | */ |
501 | void QCoapClient::disconnect() |
502 | { |
503 | Q_D(QCoapClient); |
504 | QMetaObject::invokeMethod(obj: d->connection, member: "disconnect" , c: Qt::QueuedConnection); |
505 | } |
506 | |
507 | /*! |
508 | \internal |
509 | |
510 | Sends the CoAP \a request to its own URL and returns a new QCoapReply |
511 | object. |
512 | */ |
513 | QCoapReply *QCoapClientPrivate::sendRequest(const QCoapRequest &request) |
514 | { |
515 | Q_Q(QCoapClient); |
516 | |
517 | // Prepare the reply |
518 | QCoapReply *reply = QCoapReplyPrivate::createCoapReply(request, parent: q); |
519 | |
520 | if (!send(reply)) { |
521 | delete reply; |
522 | return nullptr; |
523 | } |
524 | |
525 | return reply; |
526 | } |
527 | |
528 | /*! |
529 | \internal |
530 | |
531 | Sends the CoAP \a request to its own URL and returns a |
532 | new QCoapResourceDiscoveryReply object. |
533 | */ |
534 | QCoapResourceDiscoveryReply *QCoapClientPrivate::sendDiscovery(const QCoapRequest &request) |
535 | { |
536 | Q_Q(QCoapClient); |
537 | |
538 | // Prepare the reply |
539 | QCoapResourceDiscoveryReply *reply = new QCoapResourceDiscoveryReply(request, q); |
540 | |
541 | if (!send(reply)) { |
542 | delete reply; |
543 | return nullptr; |
544 | } |
545 | |
546 | return reply; |
547 | } |
548 | |
549 | /*! |
550 | \internal |
551 | |
552 | Connect to the reply and use the protocol to send it. |
553 | */ |
554 | bool QCoapClientPrivate::send(QCoapReply *reply) |
555 | { |
556 | const auto scheme = connection->isSecure() ? QLatin1String("coaps" ) : QLatin1String("coap" ); |
557 | if (reply->request().url().scheme() != scheme) { |
558 | qCWarning(lcCoapClient, "Failed to send request, URL has an incorrect scheme." ); |
559 | return false; |
560 | } |
561 | |
562 | if (!QCoapRequestPrivate::isUrlValid(url: reply->request().url())) { |
563 | qCWarning(lcCoapClient, "Failed to send request for an invalid URL." ); |
564 | return false; |
565 | } |
566 | |
567 | // According to https://tools.ietf.org/html/rfc7252#section-8.1, |
568 | // multicast requests MUST be Non-confirmable. |
569 | if (QHostAddress(reply->url().host()).isMulticast() |
570 | && reply->request().type() == QCoapMessage::Type::Confirmable) { |
571 | qCWarning(lcCoapClient, "Failed to send request, " |
572 | "multicast requests must be non-confirmable." ); |
573 | return false; |
574 | } |
575 | |
576 | QMetaObject::invokeMethod(obj: protocol, member: "sendRequest" , c: Qt::QueuedConnection, |
577 | Q_ARG(QPointer<QCoapReply>, QPointer<QCoapReply>(reply)), |
578 | Q_ARG(QCoapConnection *, connection)); |
579 | |
580 | return true; |
581 | } |
582 | |
583 | /*! |
584 | Sets the security configuration parameters from \a configuration. |
585 | Configuration will be ignored if the QtCoap::NoSecurity mode is used. |
586 | |
587 | \note This method must be called before the handshake starts. If you need |
588 | to change the security configuration after establishing a secure connection |
589 | with the server, the client needs to be disconnected first. |
590 | |
591 | \sa disconnect() |
592 | */ |
593 | void QCoapClient::setSecurityConfiguration(const QCoapSecurityConfiguration &configuration) |
594 | { |
595 | Q_D(QCoapClient); |
596 | |
597 | QMetaObject::invokeMethod(obj: d->connection, member: "setSecurityConfiguration" , c: Qt::QueuedConnection, |
598 | Q_ARG(QCoapSecurityConfiguration, configuration)); |
599 | } |
600 | |
601 | /*! |
602 | Sets the maximum block size used by the protocol to \a blockSize |
603 | when sending requests and receiving replies. The block size must be |
604 | a power of two. |
605 | */ |
606 | void QCoapClient::setBlockSize(quint16 blockSize) |
607 | { |
608 | Q_D(QCoapClient); |
609 | |
610 | QMetaObject::invokeMethod(obj: d->protocol, member: "setBlockSize" , c: Qt::QueuedConnection, |
611 | Q_ARG(quint16, blockSize)); |
612 | } |
613 | |
614 | /*! |
615 | Sets the QUdpSocket socket \a option to \a value. |
616 | */ |
617 | void QCoapClient::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value) |
618 | { |
619 | Q_D(QCoapClient); |
620 | |
621 | QMetaObject::invokeMethod(obj: d->connection, member: "setSocketOption" , c: Qt::QueuedConnection, |
622 | Q_ARG(QAbstractSocket::SocketOption, option), |
623 | Q_ARG(QVariant, value)); |
624 | } |
625 | |
626 | /*! |
627 | Sets the \c MAX_SERVER_RESPONSE_DELAY value to \a responseDelay in milliseconds. |
628 | The default is 250 seconds. |
629 | |
630 | As defined in \l {RFC 7390 - Section 2.5}, \c MAX_SERVER_RESPONSE_DELAY is the expected |
631 | maximum response delay over all servers that the client can send a multicast request to. |
632 | */ |
633 | void QCoapClient::setMaximumServerResponseDelay(uint responseDelay) |
634 | { |
635 | Q_D(QCoapClient); |
636 | QMetaObject::invokeMethod(obj: d->protocol, member: "setMaximumServerResponseDelay" , c: Qt::QueuedConnection, |
637 | Q_ARG(uint, responseDelay)); |
638 | } |
639 | |
640 | /*! |
641 | Sets the \c ACK_TIMEOUT value defined in \l {RFC 7252 - Section 4.2} to |
642 | \a ackTimeout in milliseconds. The default is 2000 ms. |
643 | |
644 | This timeout only applies to confirmable messages. The actual timeout for |
645 | reliable transmissions is a random value between \c ACK_TIMEOUT and |
646 | \c {ACK_TIMEOUT * ACK_RANDOM_FACTOR}. |
647 | |
648 | \sa setAckRandomFactor() |
649 | */ |
650 | void QCoapClient::setAckTimeout(uint ackTimeout) |
651 | { |
652 | Q_D(QCoapClient); |
653 | QMetaObject::invokeMethod(obj: d->protocol, member: "setAckTimeout" , c: Qt::QueuedConnection, |
654 | Q_ARG(uint, ackTimeout)); |
655 | } |
656 | |
657 | /*! |
658 | Sets the \c ACK_RANDOM_FACTOR value defined in \l {RFC 7252 - Section 4.2}, |
659 | to \a ackRandomFactor. This value should be greater than or equal to 1. |
660 | The default is 1.5. |
661 | |
662 | \sa setAckTimeout() |
663 | */ |
664 | void QCoapClient::setAckRandomFactor(double ackRandomFactor) |
665 | { |
666 | Q_D(QCoapClient); |
667 | QMetaObject::invokeMethod(obj: d->protocol, member: "setAckRandomFactor" , c: Qt::QueuedConnection, |
668 | Q_ARG(double, ackRandomFactor)); |
669 | } |
670 | |
671 | /*! |
672 | Sets the \c MAX_RETRANSMIT value defined in \l {RFC 7252 - Section 4.2} |
673 | to \a maximumRetransmitCount. This value should be less than or equal to 25. |
674 | The default is 4. |
675 | */ |
676 | void QCoapClient::setMaximumRetransmitCount(uint maximumRetransmitCount) |
677 | { |
678 | Q_D(QCoapClient); |
679 | QMetaObject::invokeMethod(obj: d->protocol, member: "setMaximumRetransmitCount" , c: Qt::QueuedConnection, |
680 | Q_ARG(uint, maximumRetransmitCount)); |
681 | } |
682 | |
683 | /*! |
684 | Sets the minimum token size to \a tokenSize in bytes. For security reasons it is |
685 | recommended to use tokens with a length of at least 4 bytes. The default value for |
686 | this parameter is 4 bytes. |
687 | */ |
688 | void QCoapClient::setMinimumTokenSize(int tokenSize) |
689 | { |
690 | Q_D(QCoapClient); |
691 | QMetaObject::invokeMethod(obj: d->protocol, member: "setMinimumTokenSize" , c: Qt::QueuedConnection, |
692 | Q_ARG(int, tokenSize)); |
693 | } |
694 | |
695 | QT_END_NAMESPACE |
696 | |