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 "qcoapoption_p.h"
7
8#include <QtCore/qdebug.h>
9#include <QtCore/qloggingcategory.h>
10
11QT_BEGIN_NAMESPACE
12
13Q_STATIC_LOGGING_CATEGORY(lcCoapOption, "qt.coap.option")
14
15/*!
16 \class QCoapOption
17 \inmodule QtCoap
18
19 \brief The QCoapOption class holds data about CoAP options.
20
21 \reentrant
22
23 CoAP defines a number of options that can be included in a message.
24 Both requests and responses may include a list of one or more
25 options. For example, the URI in a request is transported in several
26 options, and metadata that would be carried in an HTTP header in HTTP
27 is supplied as options as well.
28
29 An option contains a name, related to an option ID, and a value.
30 The name is one of the values from the OptionName enumeration.
31*/
32
33/*!
34 \enum QCoapOption::OptionName
35
36 Indicates the name of an option.
37 The value of each ID is as specified by the CoAP standard, with the
38 exception of Invalid. You can refer to
39 \l{https://tools.ietf.org/html/rfc7252#section-5.10}{RFC 7252} and
40 \l{https://tools.ietf.org/html/rfc7959#section-2.1}{RFC 7959} for more details.
41
42 \value Invalid An invalid option.
43 \value IfMatch If-Match option.
44 \value UriHost Uri-Host option.
45 \value Etag Etag option.
46 \value IfNoneMatch If-None-Match option.
47 \value Observe Observe option.
48 \value UriPort Uri-Port option.
49 \value LocationPath Location-path option.
50 \value UriPath Uri-Path option.
51 \value ContentFormat Content-Format option.
52 \value MaxAge Max-Age option.
53 \value UriQuery Uri-Query option.
54 \value Accept Accept option.
55 \value LocationQuery Location-Query option.
56 \value Block2 Block2 option.
57 \value Block1 Block1 option.
58 \value Size2 Size2 option.
59 \value ProxyUri Proxy-Uri option.
60 \value ProxyScheme Proxy-Scheme option.
61 \value Size1 Size1 option.
62*/
63
64/*!
65 Constructs a new CoAP option with the given \a name
66 and QByteArray \a opaqueValue.
67 If no parameters are passed, constructs an Invalid object.
68
69 \sa isValid()
70 */
71QCoapOption::QCoapOption(OptionName name, const QByteArray &opaqueValue) :
72 d_ptr(new QCoapOptionPrivate)
73{
74 Q_D(QCoapOption);
75 d->name = name;
76 d->setValue(opaqueValue);
77}
78
79/*!
80 Constructs a new CoAP option with the given \a name
81 and the QString \a stringValue.
82
83 \sa isValid()
84 */
85QCoapOption::QCoapOption(OptionName name, const QString &stringValue) :
86 d_ptr(new QCoapOptionPrivate)
87{
88 Q_D(QCoapOption);
89 d->name = name;
90 d->setValue(stringValue);
91}
92
93/*!
94 Constructs a new CoAP option with the given \a name
95 and the unsigned integer \a intValue.
96
97 \sa isValid()
98 */
99QCoapOption::QCoapOption(OptionName name, quint32 intValue) :
100 d_ptr(new QCoapOptionPrivate)
101{
102 Q_D(QCoapOption);
103 d->name = name;
104 d->setValue(intValue);
105}
106
107/*!
108 Constructs a new CoAP option as a copy of \a other, making the two
109 options identical.
110
111 \sa isValid()
112 */
113QCoapOption::QCoapOption(const QCoapOption &other) :
114 d_ptr(new QCoapOptionPrivate(*other.d_ptr))
115{
116}
117
118/*!
119 Move-constructs a QCoapOption, making it point to the same object
120 as \a other was pointing to.
121 */
122QCoapOption::QCoapOption(QCoapOption &&other) :
123 d_ptr(other.d_ptr)
124{
125 other.d_ptr = nullptr;
126}
127
128/*!
129 Destroys the QCoapOption object.
130 */
131QCoapOption::~QCoapOption()
132{
133 delete d_ptr;
134}
135
136/*!
137 Copies \a other into this option, making the two options identical.
138 Returns a reference to this QCoapOption.
139 */
140QCoapOption &QCoapOption::operator=(const QCoapOption &other)
141{
142 QCoapOption copy(other);
143 swap(other&: copy);
144 return *this;
145}
146
147/*!
148 Moves \a other into this option and returns a reference to this QCoapOption.
149 */
150QCoapOption &QCoapOption::operator=(QCoapOption &&other) noexcept
151{
152 swap(other);
153 return *this;
154}
155
156/*!
157 Swaps this option with \a other. This operation is very fast and never fails.
158 */
159void QCoapOption::swap(QCoapOption &other) noexcept
160{
161 qSwap(value1&: d_ptr, value2&: other.d_ptr);
162}
163
164/*!
165 Returns the value of the option.
166 */
167QByteArray QCoapOption::opaqueValue() const
168{
169 Q_D(const QCoapOption);
170 return d->value;
171}
172
173/*!
174 Returns the integer value of the option.
175 */
176quint32 QCoapOption::uintValue() const
177{
178 Q_D(const QCoapOption);
179
180 quint32 intValue = 0;
181 for (int i = 0; i < d->value.size(); i++)
182 intValue |= static_cast<quint8>(d->value.at(i)) << (8 * i);
183
184 return intValue;
185}
186
187/*!
188 Returns the QString value of the option.
189*/
190QString QCoapOption::stringValue() const
191{
192 Q_D(const QCoapOption);
193 return QString::fromUtf8(ba: d->value);
194}
195
196/*!
197 Returns the length of the value of the option.
198 */
199int QCoapOption::length() const
200{
201 Q_D(const QCoapOption);
202 return d->value.size();
203}
204
205/*!
206 Returns the name of the option.
207 */
208QCoapOption::OptionName QCoapOption::name() const
209{
210 Q_D(const QCoapOption);
211 return d->name;
212}
213
214/*!
215 Returns \c true if the option is valid.
216 */
217bool QCoapOption::isValid() const
218{
219 Q_D(const QCoapOption);
220 return d->name != QCoapOption::Invalid;
221}
222
223/*!
224 Returns \c true if this QCoapOption and \a other are equals.
225 */
226bool QCoapOption::operator==(const QCoapOption &other) const
227{
228 Q_D(const QCoapOption);
229 return (d->name == other.d_ptr->name
230 && d->value == other.d_ptr->value);
231}
232
233/*!
234 Returns \c true if this QCoapOption and \a other are different.
235 */
236bool QCoapOption::operator!=(const QCoapOption &other) const
237{
238 return !(*this == other);
239}
240
241/*!
242 \internal
243
244 Sets the \a value for the option.
245 */
246void QCoapOptionPrivate::setValue(const QByteArray &opaqueValue)
247{
248 bool oversized = false;
249
250 // Check for value maximum size, according to section 5.10 of RFC 7252
251 // https://tools.ietf.org/html/rfc7252#section-5.10
252 switch (name) {
253 case QCoapOption::IfNoneMatch:
254 if (opaqueValue.size() > 0)
255 oversized = true;
256 break;
257
258 case QCoapOption::UriPort:
259 case QCoapOption::ContentFormat:
260 case QCoapOption::Accept:
261 if (opaqueValue.size() > 2)
262 oversized = true;
263 break;
264
265 case QCoapOption::MaxAge:
266 case QCoapOption::Size1:
267 if (opaqueValue.size() > 4)
268 oversized = true;
269 break;
270
271 case QCoapOption::IfMatch:
272 case QCoapOption::Etag:
273 if (opaqueValue.size() > 8)
274 oversized = true;
275 break;
276
277 case QCoapOption::UriHost:
278 case QCoapOption::LocationPath:
279 case QCoapOption::UriPath:
280 case QCoapOption::UriQuery:
281 case QCoapOption::LocationQuery:
282 case QCoapOption::ProxyScheme:
283 if (opaqueValue.size() > 255)
284 oversized = true;
285 break;
286
287 case QCoapOption::ProxyUri:
288 if (opaqueValue.size() > 1034)
289 oversized = true;
290 break;
291
292 case QCoapOption::Observe:
293 case QCoapOption::Block2:
294 case QCoapOption::Block1:
295 case QCoapOption::Size2:
296 default:
297 break;
298 }
299
300 if (oversized)
301 qCWarning(lcCoapOption) << "Value" << opaqueValue << "is probably too big for option" << name;
302
303 value = opaqueValue;
304}
305
306/*!
307 \internal
308 \overload
309
310 Sets the \a value for the option.
311 */
312void QCoapOptionPrivate::setValue(const QString &value)
313{
314 setValue(value.toUtf8());
315}
316
317/*!
318 \internal
319 \overload
320
321 Sets the \a value for the option.
322 */
323void QCoapOptionPrivate::setValue(quint32 value)
324{
325 QByteArray data;
326 for (; value; value >>= 8)
327 data.append(c: static_cast<qint8>(value & 0xFF));
328
329 setValue(data);
330}
331
332/*!
333 \internal
334
335 For QSharedDataPointer.
336*/
337QCoapOptionPrivate *QCoapOption::d_func()
338{
339 return d_ptr;
340}
341
342QT_END_NAMESPACE
343

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