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

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