qudpsocket.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/network/socket/qudpsocket.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Copyright (C) 2016 Intel Corporation.-
5** Contact: https://www.qt.io/licensing/-
6**-
7** This file is part of the QtNetwork module of the Qt Toolkit.-
8**-
9** $QT_BEGIN_LICENSE:LGPL$-
10** Commercial License Usage-
11** Licensees holding valid commercial Qt licenses may use this file in-
12** accordance with the commercial license agreement provided with the-
13** Software or, alternatively, in accordance with the terms contained in-
14** a written agreement between you and The Qt Company. For licensing terms-
15** and conditions see https://www.qt.io/terms-conditions. For further-
16** information use the contact form at https://www.qt.io/contact-us.-
17**-
18** GNU Lesser General Public License Usage-
19** Alternatively, this file may be used under the terms of the GNU Lesser-
20** General Public License version 3 as published by the Free Software-
21** Foundation and appearing in the file LICENSE.LGPL3 included in the-
22** packaging of this file. Please review the following information to-
23** ensure the GNU Lesser General Public License version 3 requirements-
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
25**-
26** GNU General Public License Usage-
27** Alternatively, this file may be used under the terms of the GNU-
28** General Public License version 2.0 or (at your option) the GNU General-
29** Public license version 3 or any later version approved by the KDE Free-
30** Qt Foundation. The licenses are as published by the Free Software-
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
32** included in the packaging of this file. Please review the following-
33** information to ensure the GNU General Public License requirements will-
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
35** https://www.gnu.org/licenses/gpl-3.0.html.-
36**-
37** $QT_END_LICENSE$-
38**-
39****************************************************************************/-
40-
41//#define QUDPSOCKET_DEBUG-
42-
43/*! \class QUdpSocket-
44-
45 \reentrant-
46 \brief The QUdpSocket class provides a UDP socket.-
47-
48 \ingroup network-
49 \inmodule QtNetwork-
50-
51 UDP (User Datagram Protocol) is a lightweight, unreliable,-
52 datagram-oriented, connectionless protocol. It can be used when-
53 reliability isn't important. QUdpSocket is a subclass of-
54 QAbstractSocket that allows you to send and receive UDP-
55 datagrams.-
56-
57 The most common way to use this class is to bind to an address and port-
58 using bind(), then call writeDatagram() and readDatagram() to transfer-
59 data. If you want to use the standard QIODevice functions read(),-
60 readLine(), write(), etc., you must first connect the socket directly to a-
61 peer by calling connectToHost().-
62-
63 The socket emits the bytesWritten() signal every time a datagram-
64 is written to the network. If you just want to send datagrams,-
65 you don't need to call bind().-
66-
67 The readyRead() signal is emitted whenever datagrams arrive. In-
68 that case, hasPendingDatagrams() returns \c true. Call-
69 pendingDatagramSize() to obtain the size of the first pending-
70 datagram, and readDatagram() to read it.-
71-
72 \note An incoming datagram should be read when you receive the readyRead()-
73 signal, otherwise this signal will not be emitted for the next datagram.-
74-
75 Example:-
76-
77 \snippet code/src_network_socket_qudpsocket.cpp 0-
78-
79 QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and-
80 leaveMulticastGroup() to control group membership, and-
81 QAbstractSocket::MulticastTtlOption and-
82 QAbstractSocket::MulticastLoopbackOption to set the TTL and loopback socket-
83 options. Use setMulticastInterface() to control the outgoing interface for-
84 multicast datagrams, and multicastInterface() to query it.-
85-
86 With QUdpSocket, you can also establish a virtual connection to a-
87 UDP server using connectToHost() and then use read() and write()-
88 to exchange datagrams without specifying the receiver for each-
89 datagram.-
90-
91 The \l{broadcastsender}{Broadcast Sender},-
92 \l{broadcastreceiver}{Broadcast Receiver},-
93 \l{multicastsender}{Multicast Sender}, and-
94 \l{multicastreceiver}{Multicast Receiver} examples illustrate how-
95 to use QUdpSocket in applications.-
96-
97 \sa QTcpSocket-
98*/-
99-
100#include "qudpsocket.h"-
101#include "qhostaddress.h"-
102#include "qnetworkinterface.h"-
103#include "qabstractsocket_p.h"-
104-
105QT_BEGIN_NAMESPACE-
106-
107#ifndef QT_NO_UDPSOCKET-
108-
109#define QT_CHECK_BOUND(function, a) do { \-
110 if (!isValid()) { \-
111 qWarning(function" called on a QUdpSocket when not in QUdpSocket::BoundState"); \-
112 return (a); \-
113 } } while (0)-
114-
115class QUdpSocketPrivate : public QAbstractSocketPrivate-
116{-
117 Q_DECLARE_PUBLIC(QUdpSocket)-
118-
119 bool doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,-
120 const QHostAddress &remoteAddress);-
121public:-
122 inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)-
123 { return doEnsureInitialized(bindAddress, bindPort, QHostAddress()); }
never executed: return doEnsureInitialized(bindAddress, bindPort, QHostAddress());
0
124-
125 inline bool ensureInitialized(const QHostAddress &remoteAddress)-
126 { return doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
never executed: return doEnsureInitialized(QHostAddress(), 0, remoteAddress);
0
127};-
128-
129bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,-
130 const QHostAddress &remoteAddress)-
131{-
132 const QHostAddress *address = &bindAddress;-
133 QAbstractSocket::NetworkLayerProtocol proto = address->protocol();-
134 if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
proto == QUdpS...kLayerProtocolDescription
TRUEnever evaluated
FALSEevaluated 635 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
0-635
135 address = &remoteAddress;-
136 proto = address->protocol();-
137 }
never executed: end of block
0
138-
139 // now check if the socket engine is initialized and to the right type-
140 if (!socketEngine || !socketEngine->isValid()) {
!socketEngineDescription
TRUEevaluated 14 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
FALSEevaluated 621 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
!socketEngine->isValid()Description
TRUEnever evaluated
FALSEevaluated 621 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
0-621
141 resolveProxy(remoteAddress.toString(), bindPort);-
142 if (!initSocketLayer(address->protocol()))
!initSocketLay...s->protocol())Description
TRUEnever evaluated
FALSEevaluated 14 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
0-14
143 return false;
never executed: return false;
0
144 }
executed 14 times by 2 tests: end of block
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
14
145-
146 return true;
executed 635 times by 3 tests: return true;
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
635
147}-
148-
149/*!-
150 Creates a QUdpSocket object.-
151-
152 \a parent is passed to the QObject constructor.-
153-
154 \sa socketType()-
155*/-
156QUdpSocket::QUdpSocket(QObject *parent)-
157 : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)-
158{-
159 d_func()->isBuffered = false;-
160}
executed 137 times by 3 tests: end of block
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
137
161-
162/*!-
163 Destroys the socket, closing the connection if necessary.-
164-
165 \sa close()-
166*/-
167QUdpSocket::~QUdpSocket()-
168{-
169}-
170-
171#ifndef QT_NO_NETWORKINTERFACE-
172-
173/*!-
174 \since 4.8-
175-
176 Joins the multicast group specified by \a groupAddress on the default-
177 interface chosen by the operating system. The socket must be in BoundState,-
178 otherwise an error occurs.-
179-
180 Note that if you are attempting to join an IPv4 group, your socket must not-
181 be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use-
182 QHostAddress::AnyIPv4 instead.-
183-
184 This function returns \c true if successful; otherwise it returns \c false-
185 and sets the socket error accordingly.-
186-
187 \sa leaveMulticastGroup()-
188*/-
189bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress)-
190{-
191 return joinMulticastGroup(groupAddress, QNetworkInterface());
executed 13 times by 1 test: return joinMulticastGroup(groupAddress, QNetworkInterface());
Executed by:
  • tst_QUdpSocket
13
192}-
193-
194/*!-
195 \since 4.8-
196 \overload-
197-
198 Joins the multicast group address \a groupAddress on the interface \a-
199 iface.-
200-
201 \sa leaveMulticastGroup()-
202*/-
203bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress,-
204 const QNetworkInterface &iface)-
205{-
206 Q_D(QUdpSocket);-
207 QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false);
executed 4 times by 1 test: return (false);
Executed by:
  • tst_QUdpSocket
!isValid()Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QUdpSocket
FALSEevaluated 9 times by 1 test
Evaluated by:
  • tst_QUdpSocket
4-9
208 return d->socketEngine->joinMulticastGroup(groupAddress, iface);
executed 9 times by 1 test: return d->socketEngine->joinMulticastGroup(groupAddress, iface);
Executed by:
  • tst_QUdpSocket
9
209}-
210-
211/*!-
212 \since 4.8-
213-
214 Leaves the multicast group specified by \a groupAddress on the default-
215 interface chosen by the operating system. The socket must be in BoundState,-
216 otherwise an error occurs.-
217-
218 This function returns \c true if successful; otherwise it returns \c false and-
219 sets the socket error accordingly.-
220-
221 \sa joinMulticastGroup()-
222*/-
223bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress)-
224{-
225 return leaveMulticastGroup(groupAddress, QNetworkInterface());
executed 6 times by 1 test: return leaveMulticastGroup(groupAddress, QNetworkInterface());
Executed by:
  • tst_QUdpSocket
6
226}-
227-
228/*!-
229 \since 4.8-
230 \overload-
231-
232 Leaves the multicast group specified by \a groupAddress on the interface \a-
233 iface.-
234-
235 \sa joinMulticastGroup()-
236*/-
237bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress,-
238 const QNetworkInterface &iface)-
239{-
240 QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
executed 2 times by 1 test: return (false);
Executed by:
  • tst_QUdpSocket
!isValid()Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QUdpSocket
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QUdpSocket
2-4
241 return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
executed 4 times by 1 test: return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
Executed by:
  • tst_QUdpSocket
4
242}-
243-
244/*!-
245 \since 4.8-
246-
247 Returns the interface for the outgoing interface for multicast datagrams.-
248 This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and-
249 the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has-
250 been previously set, this function returns an invalid QNetworkInterface.-
251 The socket must be in BoundState, otherwise an invalid QNetworkInterface is-
252 returned.-
253-
254 \sa setMulticastInterface()-
255*/-
256QNetworkInterface QUdpSocket::multicastInterface() const-
257{-
258 Q_D(const QUdpSocket);-
259 QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
never executed: return (QNetworkInterface());
!isValid()Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • tst_QUdpSocket
0-6
260 return d->socketEngine->multicastInterface();
executed 6 times by 1 test: return d->socketEngine->multicastInterface();
Executed by:
  • tst_QUdpSocket
6
261}-
262-
263/*!-
264 \since 4.8-
265-
266 Sets the outgoing interface for multicast datagrams to the interface \a-
267 iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4-
268 sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The-
269 socket must be in BoundState, otherwise this function does nothing.-
270-
271 \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup()-
272*/-
273void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface)-
274{-
275 Q_D(QUdpSocket);-
276 if (!isValid()) {
!isValid()Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • tst_QUdpSocket
0-6
277 qWarning("QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState");-
278 return;
never executed: return;
0
279 }-
280 d->socketEngine->setMulticastInterface(iface);-
281}
executed 6 times by 1 test: end of block
Executed by:
  • tst_QUdpSocket
6
282-
283#endif // QT_NO_NETWORKINTERFACE-
284-
285/*!-
286 Returns \c true if at least one datagram is waiting to be read;-
287 otherwise returns \c false.-
288-
289 \sa pendingDatagramSize(), readDatagram()-
290*/-
291bool QUdpSocket::hasPendingDatagrams() const-
292{-
293 QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
never executed: return (false);
!isValid()Description
TRUEnever evaluated
FALSEevaluated 629303 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
0-629303
294 return d_func()->socketEngine->hasPendingDatagrams();
executed 629303 times by 2 tests: return d_func()->socketEngine->hasPendingDatagrams();
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
629303
295}-
296-
297/*!-
298 Returns the size of the first pending UDP datagram. If there is-
299 no datagram available, this function returns -1.-
300-
301 \sa hasPendingDatagrams(), readDatagram()-
302*/-
303qint64 QUdpSocket::pendingDatagramSize() const-
304{-
305 QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
never executed: return (-1);
!isValid()Description
TRUEnever evaluated
FALSEevaluated 592 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
0-592
306 return d_func()->socketEngine->pendingDatagramSize();
executed 592 times by 2 tests: return d_func()->socketEngine->pendingDatagramSize();
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
592
307}-
308-
309/*!-
310 Sends the datagram at \a data of size \a size to the host-
311 address \a address at port \a port. Returns the number of-
312 bytes sent on success; otherwise returns -1.-
313-
314 Datagrams are always written as one block. The maximum size of a-
315 datagram is highly platform-dependent, but can be as low as 8192-
316 bytes. If the datagram is too large, this function will return -1-
317 and error() will return DatagramTooLargeError.-
318-
319 Sending datagrams larger than 512 bytes is in general disadvised,-
320 as even if they are sent successfully, they are likely to be-
321 fragmented by the IP layer before arriving at their final-
322 destination.-
323-
324 \warning Calling this function on a connected UDP socket may-
325 result in an error and no packet being sent. If you are using a-
326 connected socket, use write() to send datagrams.-
327-
328 \sa readDatagram(), write()-
329*/-
330qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address,-
331 quint16 port)-
332{-
333 Q_D(QUdpSocket);-
334#if defined QUDPSOCKET_DEBUG-
335 qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,-
336 address.toString().toLatin1().constData(), port);-
337#endif-
338 if (!d->doEnsureInitialized(QHostAddress::Any, 0, address))
!d->doEnsureIn...y, 0, address)Description
TRUEnever evaluated
FALSEevaluated 635 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
0-635
339 return -1;
never executed: return -1;
0
340 if (state() == UnconnectedState)
state() == UnconnectedStateDescription
TRUEevaluated 14 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
FALSEevaluated 621 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
14-621
341 bind();
executed 14 times by 2 tests: bind();
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
14
342-
343 qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));-
344 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();-
345-
346 if (sent >= 0) {
sent >= 0Description
TRUEevaluated 634 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
FALSEevaluated 1 time by 1 test
Evaluated by:
  • tst_QUdpSocket
1-634
347 emit bytesWritten(sent);-
348 } else {
executed 634 times by 3 tests: end of block
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
634
349 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());-
350 }
executed 1 time by 1 test: end of block
Executed by:
  • tst_QUdpSocket
1
351 return sent;
executed 635 times by 3 tests: return sent;
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
635
352}-
353-
354/*!-
355 \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,-
356 const QHostAddress &host, quint16 port)-
357 \overload-
358-
359 Sends the datagram \a datagram to the host address \a host and at-
360 port \a port.-
361*/-
362-
363/*!-
364 Receives a datagram no larger than \a maxSize bytes and stores-
365 it in \a data. The sender's host address and port is stored in-
366 *\a address and *\a port (unless the pointers are 0).-
367-
368 Returns the size of the datagram on success; otherwise returns-
369 -1.-
370-
371 If \a maxSize is too small, the rest of the datagram will be-
372 lost. To avoid loss of data, call pendingDatagramSize() to-
373 determine the size of the pending datagram before attempting to-
374 read it. If \a maxSize is 0, the datagram will be discarded.-
375-
376 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()-
377*/-
378qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address,-
379 quint16 *port)-
380{-
381 Q_D(QUdpSocket);-
382-
383#if defined QUDPSOCKET_DEBUG-
384 qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);-
385#endif-
386 QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
never executed: return (-1);
!isValid()Description
TRUEnever evaluated
FALSEevaluated 629327 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
0-629327
387-
388 qint64 readBytes;-
389 if (address || port) {
addressDescription
TRUEevaluated 507 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
FALSEevaluated 628820 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
portDescription
TRUEnever evaluated
FALSEevaluated 628820 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
0-628820
390 QIpPacketHeader header;-
391 readBytes = d->socketEngine->readDatagram(data, maxSize, &header,-
392 QAbstractSocketEngine::WantDatagramSender);-
393 if (address)
addressDescription
TRUEevaluated 507 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
FALSEnever evaluated
0-507
394 *address = header.senderAddress;
executed 507 times by 2 tests: *address = header.senderAddress;
Executed by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
507
395 if (port)
portDescription
TRUEevaluated 507 times by 2 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
FALSEnever evaluated
0-507
396 *port = header.senderPort;
executed 507 times by 2 tests: *port = header.senderPort;
Executed by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
507
397 } else {
executed 507 times by 2 tests: end of block
Executed by:
  • tst_QUdpSocket
  • tst_qsocks5socketengine - unknown status
507
398 readBytes = d->socketEngine->readDatagram(data, maxSize);-
399 }
executed 628820 times by 2 tests: end of block
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
628820
400-
401 d_func()->socketEngine->setReadNotificationEnabled(true);-
402 if (readBytes < 0)
readBytes < 0Description
TRUEnever evaluated
FALSEevaluated 629327 times by 3 tests
Evaluated by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
0-629327
403 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
never executed: d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
0
404 return readBytes;
executed 629327 times by 3 tests: return readBytes;
Executed by:
  • tst_QUdpSocket
  • tst_qsocketnotifier - unknown status
  • tst_qsocks5socketengine - unknown status
629327
405}-
406#endif // QT_NO_UDPSOCKET-
407-
408QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9