1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5//#define QUDPSOCKET_DEBUG
6
7/*! \class QUdpSocket
8
9 \reentrant
10 \brief The QUdpSocket class provides a UDP socket.
11
12 \ingroup network
13 \inmodule QtNetwork
14
15 UDP (User Datagram Protocol) is a lightweight, unreliable,
16 datagram-oriented, connectionless protocol. It can be used when
17 reliability isn't important. QUdpSocket is a subclass of
18 QAbstractSocket that allows you to send and receive UDP
19 datagrams.
20
21 The most common way to use this class is to bind to an address and port
22 using bind(), then call writeDatagram() and readDatagram() /
23 receiveDatagram() to transfer data. If you want to use the standard
24 QIODevice functions read(), readLine(), write(), etc., you must first
25 connect the socket directly to a peer by calling connectToHost().
26
27 The socket emits the bytesWritten() signal every time a datagram
28 is written to the network. If you just want to send datagrams,
29 you don't need to call bind().
30
31 The readyRead() signal is emitted whenever datagrams arrive. In
32 that case, hasPendingDatagrams() returns \c true. Call
33 pendingDatagramSize() to obtain the size of the first pending
34 datagram, and readDatagram() or receiveDatagram() to read it.
35
36 \note An incoming datagram should be read when you receive the readyRead()
37 signal, otherwise this signal will not be emitted for the next datagram.
38
39 Example:
40
41 \snippet code/src_network_socket_qudpsocket.cpp 0
42
43 QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and
44 leaveMulticastGroup() to control group membership, and
45 QAbstractSocket::MulticastTtlOption and
46 QAbstractSocket::MulticastLoopbackOption to set the TTL and loopback socket
47 options. Use setMulticastInterface() to control the outgoing interface for
48 multicast datagrams, and multicastInterface() to query it.
49
50 With QUdpSocket, you can also establish a virtual connection to a
51 UDP server using connectToHost() and then use read() and write()
52 to exchange datagrams without specifying the receiver for each
53 datagram.
54
55 The \l{broadcastsender}{Broadcast Sender},
56 \l{broadcastreceiver}{Broadcast Receiver},
57 \l{multicastsender}{Multicast Sender}, and
58 \l{multicastreceiver}{Multicast Receiver} examples illustrate how
59 to use QUdpSocket in applications.
60
61 \sa QTcpSocket, QNetworkDatagram
62*/
63
64#include "qudpsocket.h"
65#include "qhostaddress.h"
66#include "qnetworkdatagram.h"
67#include "qnetworkinterface.h"
68#include "qabstractsocket_p.h"
69
70QT_BEGIN_NAMESPACE
71
72#ifndef QT_NO_UDPSOCKET
73
74#define QT_CHECK_BOUND(function, a) do { \
75 if (!isValid()) { \
76 qWarning(function" called on a QUdpSocket when not in QUdpSocket::BoundState"); \
77 return (a); \
78 } } while (0)
79
80class QUdpSocketPrivate : public QAbstractSocketPrivate
81{
82 Q_DECLARE_PUBLIC(QUdpSocket)
83
84 bool doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
85 const QHostAddress &remoteAddress);
86public:
87 inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
88 { return doEnsureInitialized(bindAddress, bindPort, remoteAddress: QHostAddress()); }
89
90 inline bool ensureInitialized(const QHostAddress &remoteAddress)
91 { return doEnsureInitialized(bindAddress: QHostAddress(), bindPort: 0, remoteAddress); }
92};
93
94bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
95 const QHostAddress &remoteAddress)
96{
97 const QHostAddress *address = &bindAddress;
98 QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
99 if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
100 address = &remoteAddress;
101 proto = address->protocol();
102 }
103
104 // now check if the socket engine is initialized and to the right type
105 if (!socketEngine || !socketEngine->isValid()) {
106 resolveProxy(hostName: remoteAddress.toString(), port: bindPort);
107 if (!initSocketLayer(protocol: address->protocol()))
108 return false;
109 }
110
111 return true;
112}
113
114/*!
115 Creates a QUdpSocket object.
116
117 \a parent is passed to the QObject constructor.
118
119 \sa socketType()
120*/
121QUdpSocket::QUdpSocket(QObject *parent)
122 : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
123{
124 d_func()->isBuffered = false;
125}
126
127/*!
128 Destroys the socket, closing the connection if necessary.
129
130 \sa close()
131*/
132QUdpSocket::~QUdpSocket()
133{
134}
135
136#ifndef QT_NO_NETWORKINTERFACE
137
138/*!
139 \since 4.8
140
141 Joins the multicast group specified by \a groupAddress on the default
142 interface chosen by the operating system. The socket must be in BoundState,
143 otherwise an error occurs.
144
145 Note that if you are attempting to join an IPv4 group, your socket must not
146 be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use
147 QHostAddress::AnyIPv4 instead.
148
149 This function returns \c true if successful; otherwise it returns \c false
150 and sets the socket error accordingly.
151
152 \note Joining IPv6 multicast groups without an interface selection is not
153 supported in all operating systems. Consider using the overload where the
154 interface is specified.
155
156 \sa leaveMulticastGroup()
157*/
158bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress)
159{
160 return joinMulticastGroup(groupAddress, iface: QNetworkInterface());
161}
162
163/*!
164 \since 4.8
165 \overload
166
167 Joins the multicast group address \a groupAddress on the interface \a
168 iface.
169
170 \sa leaveMulticastGroup()
171*/
172bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress,
173 const QNetworkInterface &iface)
174{
175 Q_D(QUdpSocket);
176 QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false);
177 return d->socketEngine->joinMulticastGroup(groupAddress, iface);
178}
179
180/*!
181 \since 4.8
182
183 Leaves the multicast group specified by \a groupAddress on the default
184 interface chosen by the operating system. The socket must be in BoundState,
185 otherwise an error occurs.
186
187 This function returns \c true if successful; otherwise it returns \c false and
188 sets the socket error accordingly.
189
190 \note This function should be called with the same arguments as were passed
191 to joinMulticastGroup().
192
193 \sa joinMulticastGroup()
194*/
195bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress)
196{
197 return leaveMulticastGroup(groupAddress, iface: QNetworkInterface());
198}
199
200/*!
201 \since 4.8
202 \overload
203
204 Leaves the multicast group specified by \a groupAddress on the interface \a
205 iface.
206
207 \note This function should be called with the same arguments as were passed
208 to joinMulticastGroup().
209
210 \sa joinMulticastGroup()
211*/
212bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress,
213 const QNetworkInterface &iface)
214{
215 QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
216 return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
217}
218
219/*!
220 \since 4.8
221
222 Returns the interface for the outgoing interface for multicast datagrams.
223 This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and
224 the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has
225 been previously set, this function returns an invalid QNetworkInterface.
226 The socket must be in BoundState, otherwise an invalid QNetworkInterface is
227 returned.
228
229 \sa setMulticastInterface()
230*/
231QNetworkInterface QUdpSocket::multicastInterface() const
232{
233 Q_D(const QUdpSocket);
234 QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
235 return d->socketEngine->multicastInterface();
236}
237
238/*!
239 \since 4.8
240
241 Sets the outgoing interface for multicast datagrams to the interface \a
242 iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4
243 sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The
244 socket must be in BoundState, otherwise this function does nothing.
245
246 \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup()
247*/
248void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface)
249{
250 Q_D(QUdpSocket);
251 if (!isValid()) {
252 qWarning(msg: "QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState");
253 return;
254 }
255 d->socketEngine->setMulticastInterface(iface);
256}
257
258#endif // QT_NO_NETWORKINTERFACE
259
260/*!
261 Returns \c true if at least one datagram is waiting to be read;
262 otherwise returns \c false.
263
264 \sa pendingDatagramSize(), readDatagram()
265*/
266bool QUdpSocket::hasPendingDatagrams() const
267{
268 QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
269 return d_func()->socketEngine->hasPendingDatagrams();
270}
271
272/*!
273 Returns the size of the first pending UDP datagram. If there is
274 no datagram available, this function returns -1.
275
276 \sa hasPendingDatagrams(), readDatagram()
277*/
278qint64 QUdpSocket::pendingDatagramSize() const
279{
280 QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
281 return d_func()->socketEngine->pendingDatagramSize();
282}
283
284/*!
285 Sends the datagram at \a data of size \a size to the host
286 address \a address at port \a port. Returns the number of
287 bytes sent on success; otherwise returns -1.
288
289 Datagrams are always written as one block. The maximum size of a
290 datagram is highly platform-dependent, but can be as low as 8192
291 bytes. If the datagram is too large, this function will return -1
292 and error() will return DatagramTooLargeError.
293
294 Sending datagrams larger than 512 bytes is in general disadvised,
295 as even if they are sent successfully, they are likely to be
296 fragmented by the IP layer before arriving at their final
297 destination.
298
299 \warning Calling this function on a connected UDP socket may
300 result in an error and no packet being sent. If you are using a
301 connected socket, use write() to send datagrams.
302
303 \sa readDatagram(), write()
304*/
305qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address,
306 quint16 port)
307{
308 Q_D(QUdpSocket);
309#if defined QUDPSOCKET_DEBUG
310 qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,
311 address.toString().toLatin1().constData(), port);
312#endif
313 if (!d->doEnsureInitialized(bindAddress: QHostAddress::Any, bindPort: 0, remoteAddress: address))
314 return -1;
315 if (state() == UnconnectedState)
316 bind();
317
318 qint64 sent = d->socketEngine->writeDatagram(data, len: size, header: QIpPacketHeader(address, port));
319 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
320
321 if (sent >= 0) {
322 emit bytesWritten(bytes: sent);
323 } else {
324 if (sent == -2) {
325 // Socket engine reports EAGAIN. Treat as a temporary error.
326 d->setErrorAndEmit(errorCode: QAbstractSocket::TemporaryError,
327 errorString: tr(s: "Unable to send a datagram"));
328 return -1;
329 }
330 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
331 }
332 return sent;
333}
334
335/*!
336 \fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
337 const QHostAddress &host, quint16 port)
338 \overload
339
340 Sends the datagram \a datagram to the host address \a host and at
341 port \a port.
342
343 The function returns the number of bytes sent if it succeeded or -1 if it
344 encountered an error.
345*/
346
347/*!
348 \since 5.8
349 \overload
350
351 Sends the datagram \a datagram to the host address and port numbers
352 contained in \a datagram, using the network interface and hop count limits
353 also set there. If the destination address and port numbers are unset, this
354 function will send to the address that was passed to connectToHost().
355
356 If the destination address is IPv6 with a non-empty
357 \l{QHostAddress::scopeId()}{scope id} but differs from the interface index
358 in \a datagram, it is undefined which interface the operating system will
359 choose to send on.
360
361 The function returns the number of bytes sent if it succeeded or -1 if it
362 encountered an error.
363
364 \warning Calling this function on a connected UDP socket may
365 result in an error and no packet being sent. If you are using a
366 connected socket, use write() to send datagrams.
367
368 \sa QNetworkDatagram::setDestination(), QNetworkDatagram::setHopLimit(), QNetworkDatagram::setInterfaceIndex()
369*/
370qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
371{
372 Q_D(QUdpSocket);
373#if defined QUDPSOCKET_DEBUG
374 qDebug("QUdpSocket::writeDatagram(%p, %i, \"%s\", %i)",
375 datagram.d->data.constData(),
376 datagram.d->data.size(),
377 datagram.destinationAddress().toString().toLatin1().constData(),
378 datagram.destinationPort());
379#endif
380 if (!d->doEnsureInitialized(bindAddress: QHostAddress::Any, bindPort: 0, remoteAddress: datagram.destinationAddress()))
381 return -1;
382 if (state() == UnconnectedState)
383 bind();
384
385 qint64 sent = d->socketEngine->writeDatagram(data: datagram.d->data,
386 len: datagram.d->data.size(),
387 header: datagram.d->header);
388 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
389
390 if (sent >= 0) {
391 emit bytesWritten(bytes: sent);
392 } else {
393 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
394 }
395 return sent;
396}
397
398/*!
399 \since 5.8
400
401 Receives a datagram no larger than \a maxSize bytes and returns it in the
402 QNetworkDatagram object, along with the sender's host address and port. If
403 possible, this function will also try to determine the datagram's
404 destination address, port, and the number of hop counts at reception time.
405
406 On failure, returns a QNetworkDatagram that reports \l
407 {QNetworkDatagram::isValid()}{not valid}.
408
409 If \a maxSize is too small, the rest of the datagram will be lost. If \a
410 maxSize is 0, the datagram will be discarded. If \a maxSize is -1 (the
411 default), this function will attempt to read the entire datagram.
412
413 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
414*/
415QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize)
416{
417 Q_D(QUdpSocket);
418
419#if defined QUDPSOCKET_DEBUG
420 qDebug("QUdpSocket::receiveDatagram(%lld)", maxSize);
421#endif
422 QT_CHECK_BOUND("QUdpSocket::receiveDatagram()", QNetworkDatagram());
423
424 if (maxSize < 0)
425 maxSize = d->socketEngine->pendingDatagramSize();
426 if (maxSize < 0)
427 return QNetworkDatagram();
428
429 QNetworkDatagram result(QByteArray(maxSize, Qt::Uninitialized));
430 qint64 readBytes = d->socketEngine->readDatagram(data: result.d->data.data(), maxlen: maxSize, header: &result.d->header,
431 QAbstractSocketEngine::WantAll);
432 d->hasPendingData = false;
433 d->socketEngine->setReadNotificationEnabled(true);
434 if (readBytes < 0) {
435 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
436 readBytes = 0;
437 }
438
439 result.d->data.truncate(pos: readBytes);
440 return result;
441}
442
443/*!
444 Receives a datagram no larger than \a maxSize bytes and stores
445 it in \a data. The sender's host address and port is stored in
446 *\a address and *\a port (unless the pointers are \nullptr).
447
448 Returns the size of the datagram on success; otherwise returns
449 -1.
450
451 If \a maxSize is too small, the rest of the datagram will be
452 lost. To avoid loss of data, call pendingDatagramSize() to
453 determine the size of the pending datagram before attempting to
454 read it. If \a maxSize is 0, the datagram will be discarded.
455
456 \sa writeDatagram(), hasPendingDatagrams(), pendingDatagramSize()
457*/
458qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
459 quint16 *port)
460{
461 Q_D(QUdpSocket);
462
463#if defined QUDPSOCKET_DEBUG
464 qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
465#endif
466 QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
467
468 qint64 readBytes;
469 if (address || port) {
470 QIpPacketHeader header;
471 readBytes = d->socketEngine->readDatagram(data, maxlen: maxSize, header: &header,
472 QAbstractSocketEngine::WantDatagramSender);
473 if (address)
474 *address = header.senderAddress;
475 if (port)
476 *port = header.senderPort;
477 } else {
478 readBytes = d->socketEngine->readDatagram(data, maxlen: maxSize);
479 }
480
481 d->hasPendingData = false;
482 d->socketEngine->setReadNotificationEnabled(true);
483 if (readBytes < 0) {
484 if (readBytes == -2) {
485 // No pending datagram. Treat as a temporary error.
486 d->setErrorAndEmit(errorCode: QAbstractSocket::TemporaryError,
487 errorString: tr(s: "No datagram available for reading"));
488 return -1;
489 }
490 d->setErrorAndEmit(errorCode: d->socketEngine->error(), errorString: d->socketEngine->errorString());
491 }
492 return readBytes;
493}
494
495#endif // QT_NO_UDPSOCKET
496
497QT_END_NAMESPACE
498
499#include "moc_qudpsocket.cpp"
500

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