1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qcoapconnection_p.h"
6
7#include <QtCore/qloggingcategory.h>
8
9QT_BEGIN_NAMESPACE
10
11Q_LOGGING_CATEGORY(lcCoapConnection, "qt.coap.connection")
12
13/*!
14 \internal
15
16 \class QCoapConnection
17 \inmodule QtCoap
18
19 \brief The QCoapConnection class defines an interface for
20 handling transfers of frames to a server.
21
22 It isolates CoAP clients from the transport in use, so that any
23 client can be used with any supported transport.
24*/
25
26/*!
27 \internal
28
29 \enum QCoapConnection::ConnectionState
30
31 This enum specifies the state of the underlying transport.
32
33 \value Unconnected The underlying transport is not yet ready for data transmission.
34
35 \value Bound The underlying transport is ready for data transmission. For example,
36 if QUdpSocket is used for the transport, this corresponds to
37 QAbstractSocket::BoundState.
38 \sa state(), bound()
39*/
40
41/*!
42 \internal
43
44 \fn void QCoapConnection::error(QAbstractSocket::SocketError error)
45
46 This signal is emitted when a connection error occurs. The \a error
47 parameter describes the type of error that occurred.
48*/
49
50/*!
51 \internal
52
53 \fn void QCoapConnection::readyRead(const QByteArray &data, const QHostAddress &sender)
54
55 This signal is emitted when a network reply is available. The \a data
56 parameter supplies the received data, and the \a sender parameter supplies
57 the sender address.
58*/
59
60/*!
61 \internal
62
63 \fn void QCoapConnection::bound()
64
65 This signal is emitted when the underlying transport is ready for data transmission.
66 Derived implementations must emit this signal whenever they are ready to start
67 transferring data frames to and from the server.
68
69 \sa bind()
70*/
71
72/*!
73 \fn void QCoapConnection::securityConfigurationChanged()
74
75 This signal is emitted when the security configuration is changed.
76*/
77
78/*!
79 \internal
80
81 \fn void QCoapConnection::bind(const QString &host, quint16 port)
82
83 Prepares the underlying transport for data transmission to to the given \a host
84 address on \a port. Emits the bound() signal when the transport is ready.
85
86 This is a pure virtual method.
87
88 \sa bound(), close()
89*/
90
91/*!
92 \internal
93
94 \fn void QCoapConnection::close()
95
96 Closes the open sockets and connections to free the underlying transport.
97 This is a pure virtual method.
98
99 \sa bind()
100*/
101
102/*!
103 \internal
104
105 \fn void QCoapConnection::writeData(const QByteArray &data, const QString &host, quint16 port)
106
107 Sends the given \a data frame to the host address \a host at port \a port.
108
109 This is a pure virtual method.
110*/
111
112QCoapConnectionPrivate::QCoapConnectionPrivate(QtCoap::SecurityMode security)
113 : securityMode(security)
114 , state(QCoapConnection::ConnectionState::Unconnected)
115{}
116
117/*!
118 Constructs a new CoAP connection for the given \a securityMode and
119 sets \a parent as its parent.
120*/
121QCoapConnection::QCoapConnection(QtCoap::SecurityMode securityMode, QObject *parent)
122 : QCoapConnection(*new QCoapConnectionPrivate(securityMode), parent)
123{
124}
125
126/*!
127 \internal
128
129 Constructs a new new CoAP connection as a child of \a parent, with \a dd
130 as its \c d_ptr. This constructor must be used when internally subclassing
131 the QCoapConnection class.
132*/
133QCoapConnection::QCoapConnection(QObjectPrivate &dd, QObject *parent)
134 : QObject(dd, parent)
135{
136 connect(sender: this, signal: &QCoapConnection::bound, context: this,
137 slot: [this]() {
138 Q_D(QCoapConnection);
139 d->state = ConnectionState::Bound;
140 startToSendRequest();
141 });
142}
143
144/*!
145 \internal
146
147 Releases any resources held by QCoapConnection.
148*/
149QCoapConnection::~QCoapConnection()
150{
151}
152
153/*!
154 \internal
155
156 Prepares the underlying transport for data transmission and sends the given
157 \a request frame to the given \a host at the given \a port when the transport
158 is ready.
159
160 The preparation of the transport is done by calling the pure virtual bind() method,
161 which needs to be implemented by derived classes.
162*/
163void
164QCoapConnectionPrivate::sendRequest(const QByteArray &request, const QString &host, quint16 port)
165{
166 Q_Q(QCoapConnection);
167
168 CoapFrame frame(request, host, port);
169 framesToSend.enqueue(t: frame);
170
171 if (state == QCoapConnection::ConnectionState::Unconnected)
172 q->bind(host, port);
173 else
174 q->startToSendRequest();
175}
176
177/*!
178 \internal
179
180 Returns \c true if security is used, returns \c false otherwise.
181*/
182bool QCoapConnection::isSecure() const
183{
184 Q_D(const QCoapConnection);
185 return d->securityMode != QtCoap::SecurityMode::NoSecurity;
186}
187
188/*!
189 \internal
190
191 Returns the security mode.
192*/
193QtCoap::SecurityMode QCoapConnection::securityMode() const
194{
195 Q_D(const QCoapConnection);
196 return d->securityMode;
197}
198
199/*!
200 \internal
201
202 Returns the connection state.
203*/
204QCoapConnection::ConnectionState QCoapConnection::state() const
205{
206 Q_D(const QCoapConnection);
207 return d->state;
208}
209
210/*!
211 \internal
212
213 Sends the last stored frame to the server by calling the pure virtual
214 writeData() method.
215*/
216void QCoapConnection::startToSendRequest()
217{
218 Q_D(QCoapConnection);
219
220 Q_ASSERT(!d->framesToSend.isEmpty());
221 while (!d->framesToSend.isEmpty()) {
222 const CoapFrame frame = d->framesToSend.dequeue();
223 writeData(data: frame.currentPdu, host: frame.host, port: frame.port);
224 }
225}
226
227/*!
228 Sets the security configuration parameters from the \a configuration.
229 The security configuration will be ignored if the QtCoap::NoSecurity mode is
230 used for connection.
231
232 \note This method must be called before the handshake starts.
233*/
234void QCoapConnection::setSecurityConfiguration(const QCoapSecurityConfiguration &configuration)
235{
236 Q_D(QCoapConnection);
237
238 if (isSecure()) {
239 d->securityConfiguration = configuration;
240 emit securityConfigurationChanged();
241 } else {
242 qCWarning(lcCoapConnection, "Security is disabled, security configuration will be ignored.");
243 }
244}
245
246/*!
247 \internal
248
249 Returns the security configuration.
250*/
251QCoapSecurityConfiguration QCoapConnection::securityConfiguration() const
252{
253 Q_D(const QCoapConnection);
254 return d->securityConfiguration;
255}
256
257/*!
258 \internal
259
260 Closes the open sockets and connections to free the transport and clears
261 the connection state.
262*/
263void QCoapConnection::disconnect()
264{
265 Q_D(QCoapConnection);
266
267 close();
268
269 d->framesToSend.clear();
270 d->state = ConnectionState::Unconnected;
271}
272
273QT_END_NAMESPACE
274

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