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() /
59 receiveDatagram() to transfer data. If you want to use the standard
60 QIODevice functions read(), readLine(), write(), etc., you must first
61 connect the socket directly to a 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() or receiveDatagram() 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, QNetworkDatagram
98*/
99
100#include "qudpsocket.h"
101#include "qhostaddress.h"
102#include "qnetworkdatagram.h"
103#include "qnetworkinterface.h"
104#include "qabstractsocket_p.h"
105
106QT_BEGIN_NAMESPACE
107
108#ifndef QT_NO_UDPSOCKET
109
110#define QT_CHECK_BOUND(function, a) do { \
111 if (!isValid()) { \
112 qWarning(function" called on a QUdpSocket when not in QUdpSocket::BoundState"); \
113 return (a); \
114 } } while (0)
115
116class QUdpSocketPrivate : public QAbstractSocketPrivate
117{
118 Q_DECLARE_PUBLIC(QUdpSocket)
119
120 bool doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
121 const QHostAddress &remoteAddress);
122public:
123 inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
124 { return doEnsureInitialized(bindAddress, bindPort, remoteAddress: QHostAddress()); }
125
126 inline bool ensureInitialized(const QHostAddress &remoteAddress)
127 { return doEnsureInitialized(bindAddress: QHostAddress(), bindPort: 0, remoteAddress); }
128};
129
130bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
131 const QHostAddress &remoteAddress)
132{
133 const QHostAddress *address = &bindAddress;
134 QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
135 if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
136 address = &remoteAddress;
137 proto = address->protocol();
138 }
139
140 // now check if the socket engine is initialized and to the right type
141 if (!socketEngine || !socketEngine->isValid()) {
142 resolveProxy(hostName: remoteAddress.toString(), port: bindPort);
143 if (!initSocketLayer(protocol: address->protocol()))
144 return false;
145 }
146
147 return true;
148}
149
150/*!
151 Creates a QUdpSocket object.
152
153 \a parent is passed to the QObject constructor.
154
155 \sa socketType()
156*/
157QUdpSocket::QUdpSocket(QObject *parent)
158 : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
159{
160 d_func()->isBuffered = false;
161}
162
163/*!
164 Destroys the socket, closing the connection if necessary.
165
166 \sa close()
167*/
168QUdpSocket::~QUdpSocket()
169{
170}
171
172#ifndef QT_NO_NETWORKINTERFACE
173
174/*!
175 \since 4.8
176
177 Joins the multicast group specified by \a groupAddress on the default
178 interface chosen by the operating system. The socket must be in BoundState,
179 otherwise an error occurs.
180
181 Note that if you are attempting to join an IPv4 group, your socket must not
182 be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use
183 QHostAddress::AnyIPv4 instead.
184
185 This function returns \c true if successful; otherwise it returns \c false
186 and sets the socket error accordingly.
187
188 \note Joining IPv6 multicast groups without an interface selection is not
189 supported in all operating systems. Consider using the overload where the
190 interface is specified.
191
192 \sa leaveMulticastGroup()
193*/
194bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress)
195{
196 return joinMulticastGroup(groupAddress, iface: QNetworkInterface());
197}
198
199/*!
200 \since 4.8
201 \overload
202
203 Joins the multicast group address \a groupAddress on the interface \a
204 iface.
205
206 \sa leaveMulticastGroup()
207*/
208bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress,
209 const QNetworkInterface &iface)
210{
211 Q_D(QUdpSocket);
212 QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false);
213 return d->socketEngine->joinMulticastGroup(groupAddress, iface);
214}
215
216/*!
217 \since 4.8
218
219 Leaves the multicast group specified by \a groupAddress on the default
220 interface chosen by the operating system. The socket must be in BoundState,
221 otherwise an error occurs.
222
223 This function returns \c true if successful; otherwise it returns \c false and
224 sets the socket error accordingly.
225
226 \note This function should be called with the same arguments as were passed
227 to joinMulticastGroup().
228
229 \sa joinMulticastGroup()
230*/
231bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress)
232{
233 return leaveMulticastGroup(groupAddress, iface: QNetworkInterface());
234}
235
236/*!
237 \since 4.8
238 \overload
239
240 Leaves the multicast group specified by \a groupAddress on the interface \a
241 iface.
242
243 \note This function should be called with the same arguments as were passed
244 to joinMulticastGroup().
245
246 \sa joinMulticastGroup()
247*/
248bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress,
249 const QNetworkInterface &iface)
250{
251 QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
252 return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
253}
254
255/*!
256 \since 4.8
257
258 Returns the interface for the outgoing interface for multicast datagrams.
259 This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and
260 the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has
261 been previously set, this function returns an invalid QNetworkInterface.
262 The socket must be in BoundState, otherwise an invalid QNetworkInterface is
263 returned.
264
265 \sa setMulticastInterface()
266*/
267QNetworkInterface QUdpSocket::multicastInterface() const
268{
269 Q_D(const QUdpSocket);
270 QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
271 return d->socketEngine->multicastInterface();
272}
273
274/*!
275 \since 4.8
276
277 Sets the outgoing interface for multicast datagrams to the interface \a
278 iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4
279 sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The
280 socket must be in BoundState, otherwise this function does nothing.
281
282 \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup()
283*/
284void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface)
285{
286 Q_D(QUdpSocket);
287 if (!isValid()) {
288 qWarning(msg: "QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState");
289 return;
290 }
291 d->socketEngine->setMulticastInterface(iface);
292}
293
294#endif // QT_NO_NETWORKINTERFACE
295
296/*!
297 Returns \c true if at least one datagram is waiting to be read;
298 otherwise returns \c false.
299
300 \sa pendingDatagramSize(), readDatagram()
301*/
302bool QUdpSocket::hasPendingDatagrams() const
303{
304 QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
305 return d_func()->socketEngine->hasPendingDatagrams();
306}
307
308/*!
309 Returns the size of the first pending UDP datagram. If there is
310 no datagram available, this function returns -1.
311
312 \sa hasPendingDatagrams(), readDatagram()
313*/
314qint64 QUdpSocket::pendingDatagramSize() const
315{
316 QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
317 return d_func()->socketEngine->pendingDatagramSize();
318}
319
320/*!
321 Sends the datagram at \a data of size \a size to the host
322 address \a address at port \a port. Returns the number of
323 bytes sent on success; otherwise returns -1.
324
325 Datagrams are always written as one block. The maximum size of a
326 datagram is highly platform-dependent, but can be as low as 8192
327 bytes. If the datagram is too large, this function will return -1
328 and error() will return DatagramTooLargeError.
329
330 Sending datagrams larger than 512 bytes is in general disadvised,
331 as even if they are sent successfully, they are likely to be
332 fragmented by the IP layer before arriving at their final
333 destination.
334
335 \warning Calling this function on a connected UDP socket may
336 result in an error and no packet being sent. If you are using a
337 connected socket, use write() to send datagrams.
338
339 \sa readDatagram(), write()
340*/
341qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address,
342 quint16 port)
343{
344 Q_D(QUdpSocket);
345#if defined QUDPSOCKET_DEBUG
346 qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,
347 address.toString().toLatin1().constData(), port);
348#endif
349 if (!d->doEnsureInitialized(bindAddress: QHostAddress::Any, bindPort: 0, remoteAddress: address))
350 return -1;
351 if (state() == UnconnectedState)
352 bind();
353
354 qint64 sent = d->socketEngine->writeDatagram(data, len: size, header: QIpPacketHeader(address, port));
355 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
356
357 if (sent >= 0) {
358 emit bytesWritten(bytes: sent);
359 } else {
360 if (sent == -2) {
361 // Socket engine reports EAGAIN. Treat as a temporary error.
362 d->setErrorAndEmit(errorCode: QAbstractSocket::TemporaryError,
363 errorString: tr(s: "Unable to send a datagram"));
364 return -1;
365 }
366 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
367 }
368 return sent;
369}
370
371/*!
372 \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
373 const QHostAddress &host, quint16 port)
374 \overload
375
376 Sends the datagram \a datagram to the host address \a host and at
377 port \a port.
378
379 The function returns the number of bytes sent if it succeeded or -1 if it
380 encountered an error.
381*/
382
383/*!
384 \since 5.8
385 \overload
386
387 Sends the datagram \a datagram to the host address and port numbers
388 contained in \a datagram, using the network interface and hop count limits
389 also set there. If the destination address and port numbers are unset, this
390 function will send to the address that was passed to connectToHost().
391
392 If the destination address is IPv6 with a non-empty
393 \l{QHostAddress::scopeId()}{scope id} but differs from the interface index
394 in \a datagram, it is undefined which interface the operating system will
395 choose to send on.
396
397 The function returns the number of bytes sent if it succeeded or -1 if it
398 encountered an error.
399
400 \warning Calling this function on a connected UDP socket may
401 result in an error and no packet being sent. If you are using a
402 connected socket, use write() to send datagrams.
403
404 \sa QNetworkDatagram::setDestination(), QNetworkDatagram::setHopLimit(), QNetworkDatagram::setInterfaceIndex()
405*/
406qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
407{
408 Q_D(QUdpSocket);
409#if defined QUDPSOCKET_DEBUG
410 qDebug("QUdpSocket::writeDatagram(%p, %i, \"%s\", %i)",
411 datagram.d->data.constData(),
412 datagram.d->data.size(),
413 datagram.destinationAddress().toString().toLatin1().constData(),
414 datagram.destinationPort());
415#endif
416 if (!d->doEnsureInitialized(bindAddress: QHostAddress::Any, bindPort: 0, remoteAddress: datagram.destinationAddress()))
417 return -1;
418 if (state() == UnconnectedState)
419 bind();
420
421 qint64 sent = d->socketEngine->writeDatagram(data: datagram.d->data,
422 len: datagram.d->data.size(),
423 header: datagram.d->header);
424 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
425
426 if (sent >= 0) {
427 emit bytesWritten(bytes: sent);
428 } else {
429 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
430 }
431 return sent;
432}
433
434/*!
435 \since 5.8
436
437 Receives a datagram no larger than \a maxSize bytes and returns it in the
438 QNetworkDatagram object, along with the sender's host address and port. If
439 possible, this function will also try to determine the datagram's
440 destination address, port, and the number of hop counts at reception time.
441
442 On failure, returns a QNetworkDatagram that reports \l
443 {QNetworkDatagram::isValid()}{not valid}.
444
445 If \a maxSize is too small, the rest of the datagram will be lost. If \a
446 maxSize is 0, the datagram will be discarded. If \a maxSize is -1 (the
447 default), this function will attempt to read the entire datagram.
448
449 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
450*/
451QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize)
452{
453 Q_D(QUdpSocket);
454
455#if defined QUDPSOCKET_DEBUG
456 qDebug("QUdpSocket::receiveDatagram(%lld)", maxSize);
457#endif
458 QT_CHECK_BOUND("QUdpSocket::receiveDatagram()", QNetworkDatagram());
459
460 if (maxSize < 0)
461 maxSize = d->socketEngine->pendingDatagramSize();
462 if (maxSize < 0)
463 return QNetworkDatagram();
464
465 QNetworkDatagram result(QByteArray(maxSize, Qt::Uninitialized));
466 qint64 readBytes = d->socketEngine->readDatagram(data: result.d->data.data(), maxlen: maxSize, header: &result.d->header,
467 QAbstractSocketEngine::WantAll);
468 d->hasPendingData = false;
469 d->socketEngine->setReadNotificationEnabled(true);
470 if (readBytes < 0) {
471 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
472 readBytes = 0;
473 }
474
475 result.d->data.truncate(pos: readBytes);
476 return result;
477}
478
479/*!
480 Receives a datagram no larger than \a maxSize bytes and stores
481 it in \a data. The sender's host address and port is stored in
482 *\a address and *\a port (unless the pointers are \nullptr).
483
484 Returns the size of the datagram on success; otherwise returns
485 -1.
486
487 If \a maxSize is too small, the rest of the datagram will be
488 lost. To avoid loss of data, call pendingDatagramSize() to
489 determine the size of the pending datagram before attempting to
490 read it. If \a maxSize is 0, the datagram will be discarded.
491
492 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
493*/
494qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
495 quint16 *port)
496{
497 Q_D(QUdpSocket);
498
499#if defined QUDPSOCKET_DEBUG
500 qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
501#endif
502 QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
503
504 qint64 readBytes;
505 if (address || port) {
506 QIpPacketHeader header;
507 readBytes = d->socketEngine->readDatagram(data, maxlen: maxSize, header: &header,
508 QAbstractSocketEngine::WantDatagramSender);
509 if (address)
510 *address = header.senderAddress;
511 if (port)
512 *port = header.senderPort;
513 } else {
514 readBytes = d->socketEngine->readDatagram(data, maxlen: maxSize);
515 }
516
517 d->hasPendingData = false;
518 d->socketEngine->setReadNotificationEnabled(true);
519 if (readBytes < 0) {
520 if (readBytes == -2) {
521 // No pending datagram. Treat as a temporary error.
522 d->setErrorAndEmit(errorCode: QAbstractSocket::TemporaryError,
523 errorString: tr(s: "No datagram available for reading"));
524 return -1;
525 }
526 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
527 }
528 return readBytes;
529}
530
531#endif // QT_NO_UDPSOCKET
532
533QT_END_NAMESPACE
534

source code of qtbase/src/network/socket/qudpsocket.cpp