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// Qt-Security score:significant reason:default
5
6#include "qcoapmessage_p.h"
7
8QT_BEGIN_NAMESPACE
9
10QCoapMessagePrivate::QCoapMessagePrivate(QCoapMessage::Type _type) :
11 type(_type)
12{
13}
14
15QCoapMessagePrivate::QCoapMessagePrivate(const QCoapMessagePrivate &other) :
16 QSharedData(other),
17 version(other.version), type(other.type), messageId(other.messageId),
18 token(other.token), options(other.options), payload(other.payload)
19{
20}
21
22QCoapMessagePrivate::~QCoapMessagePrivate()
23{
24}
25
26QCoapMessagePrivate *QCoapMessagePrivate::clone() const
27{
28 return new QCoapMessagePrivate(*this);
29}
30
31/*!
32 \class QCoapMessage
33 \inmodule QtCoap
34
35 \brief The QCoapMessage class holds information about a CoAP message that
36 can be a request or a reply.
37
38 \reentrant
39
40 It holds information such as the message type, message id, token and other
41 ancillary data.
42
43 \sa QCoapOption, QCoapReply, QCoapRequest
44*/
45
46/*!
47 \enum QCoapMessage::Type
48
49 Indicates the type of the message.
50
51 \value Confirmable A Confirmable message. The destination
52 endpoint needs to acknowledge the
53 message.
54 \value NonConfirmable A Non-Confirmable message. The
55 destination endpoint does not need to
56 acknowledge the message.
57 \value Acknowledgment An Acknowledgment message. A message
58 sent or received in reply to a
59 Confirmable message.
60 \value Reset A Reset message. This message type is used
61 in case of errors or to stop the ongoing
62 transmission. (For example, it is used
63 to cancel an observation).
64*/
65
66/*!
67 \fn void QCoapMessage::swap(QCoapMessage &other)
68
69 Swaps this message with \a other. This operation is very fast and never fails.
70*/
71
72/*!
73 Constructs a new QCoapMessage.
74*/
75QCoapMessage::QCoapMessage() :
76 d_ptr(new QCoapMessagePrivate)
77{
78}
79
80/*!
81 Destroys the QCoapMessage.
82*/
83QCoapMessage::~QCoapMessage()
84{
85}
86
87/*!
88 Constructs a shallow copy of \a other.
89*/
90QCoapMessage::QCoapMessage(const QCoapMessage &other) :
91 d_ptr(other.d_ptr)
92{
93}
94
95/*!
96 \internal
97 Constructs a new QCoapMessage with \a dd as the d_ptr.
98 This constructor must be used internally when subclassing
99 the QCoapMessage class.
100*/
101QCoapMessage::QCoapMessage(QCoapMessagePrivate &dd) :
102 d_ptr(&dd)
103{
104}
105
106/*!
107 \overload
108
109 Adds the CoAP option with the given \a name and \a value.
110*/
111void QCoapMessage::addOption(QCoapOption::OptionName name, const QByteArray &value)
112{
113 QCoapOption option(name, value);
114 addOption(option);
115}
116
117/*!
118 Adds the given CoAP \a option.
119*/
120void QCoapMessage::addOption(const QCoapOption &option)
121{
122 Q_D(QCoapMessage);
123
124 const auto it = std::upper_bound(first: d->options.begin(), last: d->options.end(), val: option,
125 comp: [](const QCoapOption &a, const QCoapOption &b) -> bool {
126 return a.name() < b.name();
127 });
128 const auto idx = std::distance(first: d->options.begin(), last: it);
129
130 // Sort options by ascending order while inserting
131 d->options.insert(i: idx, t: option);
132}
133
134/*!
135 Removes the given \a option.
136*/
137void QCoapMessage::removeOption(const QCoapOption &option)
138{
139 Q_D(QCoapMessage);
140 d->options.removeOne(t: option);
141}
142
143/*!
144 Removes all options with the given \a name.
145 The CoAP protocol allows for the same option to repeat.
146*/
147void QCoapMessage::removeOption(QCoapOption::OptionName name)
148{
149 Q_D(QCoapMessage);
150 auto namesMatch = [name](const QCoapOption &option) {
151 return option.name() == name;
152 };
153
154 auto &options = d->options;
155 options.erase(abegin: std::remove_if(first: options.begin(), last: options.end(), pred: namesMatch),
156 aend: options.end());
157}
158
159/*!
160 Removes all options.
161*/
162void QCoapMessage::clearOptions()
163{
164 Q_D(QCoapMessage);
165 d->options.clear();
166}
167
168/*!
169 Returns the CoAP version.
170
171 \sa setVersion()
172*/
173quint8 QCoapMessage::version() const
174{
175 Q_D(const QCoapMessage);
176 return d->version;
177}
178
179/*!
180 Returns the message type.
181
182 \sa setType()
183*/
184QCoapMessage::Type QCoapMessage::type() const
185{
186 Q_D(const QCoapMessage);
187 return d->type;
188}
189
190/*!
191 Returns the message token.
192
193 \sa setToken()
194*/
195QByteArray QCoapMessage::token() const
196{
197 Q_D(const QCoapMessage);
198 return d->token;
199}
200
201/*!
202 Returns the token length.
203*/
204quint8 QCoapMessage::tokenLength() const
205{
206 Q_D(const QCoapMessage);
207 return static_cast<quint8>(d->token.size());
208}
209
210/*!
211 Returns the message id.
212
213 \sa setMessageId()
214*/
215quint16 QCoapMessage::messageId() const
216{
217 Q_D(const QCoapMessage);
218 return d->messageId;
219}
220
221/*!
222 Returns the payload.
223
224 \sa setPayload()
225*/
226QByteArray QCoapMessage::payload() const
227{
228 Q_D(const QCoapMessage);
229 return d->payload;
230}
231
232/*!
233 Returns the option at \a index position.
234*/
235QCoapOption QCoapMessage::optionAt(int index) const
236{
237 Q_D(const QCoapMessage);
238 return d->options.at(i: index);
239}
240
241/*!
242 Finds and returns the first option with the given \a name.
243 If there is no such option, returns an invalid QCoapOption with an empty value.
244*/
245QCoapOption QCoapMessage::option(QCoapOption::OptionName name) const
246{
247 Q_D(const QCoapMessage);
248
249 auto it = d->findOption(name);
250 return it != d->options.end() ? *it : QCoapOption();
251}
252
253/*!
254 \internal
255
256 Finds and returns a constant iterator to the first option
257 with the given \a name.
258 If there is no such option, returns \c d->options.end().
259*/
260QList<QCoapOption>::const_iterator
261QCoapMessagePrivate::findOption(QCoapOption::OptionName name) const
262{
263 return std::find_if(first: options.begin(), last: options.end(), pred: [name](const QCoapOption &option) {
264 return option.name() == name;
265 });
266}
267
268/*!
269 Returns \c true if the message contains at last one option
270 with \a name.
271*/
272bool QCoapMessage::hasOption(QCoapOption::OptionName name) const
273{
274 Q_D(const QCoapMessage);
275 return d->findOption(name) != d->options.end();
276}
277
278/*!
279 Returns the list of options.
280*/
281const QList<QCoapOption> &QCoapMessage::options() const
282{
283 Q_D(const QCoapMessage);
284 return d->options;
285}
286
287/*!
288 Finds and returns the list of options with the given \a name.
289*/
290QList<QCoapOption> QCoapMessage::options(QCoapOption::OptionName name) const
291{
292 Q_D(const QCoapMessage);
293
294 QList<QCoapOption> result;
295 std::copy_if(first: d->options.cbegin(), last: d->options.cend(), result: std::back_inserter(x&: result),
296 pred: [name](const QCoapOption &option) {
297 return option.name() == name;
298 });
299 return result;
300}
301
302/*!
303 Returns the number of options.
304*/
305int QCoapMessage::optionCount() const
306{
307 Q_D(const QCoapMessage);
308 return d->options.size();
309}
310
311/*!
312 Sets the CoAP version to \a version.
313
314 \sa version()
315*/
316void QCoapMessage::setVersion(quint8 version)
317{
318 Q_D(QCoapMessage);
319 d->version = version;
320}
321
322/*!
323 Sets the message type to \a type.
324
325 \sa type()
326*/
327void QCoapMessage::setType(const Type &type)
328{
329 Q_D(QCoapMessage);
330 d->type = type;
331}
332
333/*!
334 Sets the message token to \a token.
335
336 \sa token()
337*/
338void QCoapMessage::setToken(const QByteArray &token)
339{
340 Q_D(QCoapMessage);
341 d->token = token;
342}
343
344/*!
345 Sets the message ID to \a id.
346
347 \sa messageId()
348*/
349void QCoapMessage::setMessageId(quint16 id)
350{
351 Q_D(QCoapMessage);
352 d->messageId = id;
353}
354
355/*!
356 Sets the message payload to \a payload. The payload can be represented in
357 one of the content formats defined in \l {CoAP Content-Formats Registry}.
358
359 \note CoAP supports common content formats such as XML, JSON, and so on, but
360 these are text based and consequently heavy both in payload and in processing.
361 One of the recommended content formats to use with CoAP is CBOR, which is
362 designed to be used in such contexts.
363
364 \sa payload(), QCborStreamWriter, QCborStreamReader
365*/
366void QCoapMessage::setPayload(const QByteArray &payload)
367{
368 Q_D(QCoapMessage);
369 d->payload = payload;
370}
371
372/*!
373 Sets the message options to \a options.
374*/
375void QCoapMessage::setOptions(const QList<QCoapOption> &options)
376{
377 Q_D(QCoapMessage);
378 d->options = options;
379}
380
381void QCoapMessage::swap(QCoapMessage &other) noexcept
382{
383 qSwap(value1&: d_ptr, value2&: other.d_ptr);
384}
385
386/*!
387 Moves \a other into this message and returns a reference to this QCoapMessage.
388 */
389QCoapMessage &QCoapMessage::operator=(QCoapMessage &&other) noexcept
390{
391 swap(other);
392 return *this;
393}
394
395/*!
396 Copies the contents of \a other into this message.
397 Returns a reference to this QCoapMessage.
398 */
399QCoapMessage &QCoapMessage::operator=(const QCoapMessage &other)
400{
401 d_ptr = other.d_ptr;
402 return *this;
403}
404
405/*!
406 \internal
407
408 For QSharedDataPointer.
409*/
410QCoapMessagePrivate* QCoapMessage::d_func()
411{
412 return d_ptr.data();
413}
414
415/*!
416 \variable QCoapMessage::d_ptr
417 \internal
418
419 Pointer to private data structure.
420*/
421
422QT_END_NAMESPACE
423

source code of qtcoap/src/coap/qcoapmessage.cpp