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