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

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