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:critical reason:data-parser
5
6#include "qcoapresourcediscoveryreply_p.h"
7#include "qcoapinternalreply_p.h"
8#include "qcoapnamespace_p.h"
9
10QT_BEGIN_NAMESPACE
11
12QCoapResourceDiscoveryReplyPrivate::QCoapResourceDiscoveryReplyPrivate(const QCoapRequest &request) :
13 QCoapReplyPrivate(request)
14{
15}
16
17/*!
18 \internal
19
20 Updates the QCoapResourceDiscoveryReply object, its message and list of resources
21 with data of the internal reply \a internalReply.
22*/
23void QCoapResourceDiscoveryReplyPrivate::_q_setContent(const QHostAddress &sender,
24 const QCoapMessage &msg,
25 QtCoap::ResponseCode code)
26{
27 Q_Q(QCoapResourceDiscoveryReply);
28
29 if (q->isFinished())
30 return;
31
32 message = msg;
33 responseCode = code;
34
35 if (QtCoap::isError(code: responseCode)) {
36 _q_setError(code: responseCode);
37 } else {
38 auto res = QCoapResourceDiscoveryReplyPrivate::resourcesFromCoreLinkList(sender,
39 data: message.payload());
40 resources.append(l: res);
41 emit q->discovered(reply: q, resources: res);
42 }
43}
44
45/*!
46 \class QCoapResourceDiscoveryReply
47 \inmodule QtCoap
48
49 \brief The QCoapResourceDiscoveryReply class holds the data of a CoAP reply
50 for a resource discovery request.
51
52 \reentrant
53
54 This class is used for discovery requests. It emits the discovered()
55 signal if and when resources are discovered. When using a multicast
56 address for discovery, the discovered() signal will be emitted once
57 for each response received.
58
59 \note A QCoapResourceDiscoveryReply is a QCoapReply that stores also a list
60 of QCoapResources.
61
62 \sa QCoapClient, QCoapRequest, QCoapReply, QCoapResource
63*/
64
65/*!
66 \fn void QCoapResourceDiscoveryReply::discovered(QCoapResourceDiscoveryReply *reply,
67 QList<QCoapResource> resources);
68
69 This signal is emitted whenever a CoAP resource is discovered.
70
71 The \a reply parameter contains a pointer to the reply that has just been
72 received, and \a resources contains a list of resources that were discovered.
73
74 \sa QCoapReply::finished()
75*/
76
77/*!
78 \internal
79
80 Constructs a new CoAP discovery reply from the \a request and sets \a parent
81 as its parent.
82*/
83QCoapResourceDiscoveryReply::QCoapResourceDiscoveryReply(const QCoapRequest &request, QObject *parent) :
84 QCoapReply(*new QCoapResourceDiscoveryReplyPrivate(request), parent)
85{
86}
87
88/*!
89 Returns the list of resources.
90*/
91QList<QCoapResource> QCoapResourceDiscoveryReply::resources() const
92{
93 Q_D(const QCoapResourceDiscoveryReply);
94 return d->resources;
95}
96
97/*!
98 \internal
99
100 Decodes the \a data received from the \a sender to a list of QCoapResource
101 objects. The \a data byte array contains the frame returned by the
102 discovery request.
103*/
104QList<QCoapResource>
105QCoapResourceDiscoveryReplyPrivate::resourcesFromCoreLinkList(const QHostAddress &sender,
106 const QByteArray &data)
107{
108 QList<QCoapResource> resourceList;
109
110 QLatin1String quote = QLatin1String("\"");
111 const QList<QByteArray> links = data.split(sep: ',');
112 for (const QByteArray &link : links) {
113 QCoapResource resource;
114 resource.setHost(sender);
115
116 const QList<QByteArray> parameterList = link.split(sep: ';');
117 for (const QByteArray &parameter : parameterList) {
118 QString parameterString = QString::fromUtf8(ba: parameter);
119 const qsizetype length = parameterString.size();
120 if (parameter.startsWith(c: '<'))
121 resource.setPath(parameterString.mid(position: 1, n: length - 2));
122 else if (parameter.startsWith(bv: "title="))
123 resource.setTitle(parameterString.mid(position: 6).remove(s: quote));
124 else if (parameter.startsWith(bv: "rt="))
125 resource.setResourceType(parameterString.mid(position: 3).remove(s: quote));
126 else if (parameter.startsWith(bv: "if="))
127 resource.setInterface(parameterString.mid(position: 3).remove(s: quote));
128 else if (parameter.startsWith(bv: "sz="))
129 resource.setMaximumSize(parameterString.mid(position: 3).remove(s: quote).toInt());
130 else if (parameter.startsWith(bv: "ct="))
131 resource.setContentFormat(parameterString.mid(position: 3).remove(s: quote).toUInt());
132 else if (parameter == "obs")
133 resource.setObservable(true);
134 }
135
136 if (!resource.path().isEmpty())
137 resourceList.push_back(t: resource);
138 }
139
140 return resourceList;
141}
142
143QT_END_NAMESPACE
144

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