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 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QCoapResourceDiscoveryReplyPrivate::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 | */ |
22 | void 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 | */ |
82 | QCoapResourceDiscoveryReply::QCoapResourceDiscoveryReply(const QCoapRequest &request, QObject *parent) : |
83 | QCoapReply(*new QCoapResourceDiscoveryReplyPrivate(request), parent) |
84 | { |
85 | } |
86 | |
87 | /*! |
88 | Returns the list of resources. |
89 | */ |
90 | QList<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 | */ |
103 | QList<QCoapResource> |
104 | QCoapResourceDiscoveryReplyPrivate::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 | |
142 | QT_END_NAMESPACE |
143 | |