Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qudpsocket.cpp
Go to the documentation of this file.
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
64#include "qudpsocket.h"
65#include "qhostaddress.h"
66#include "qnetworkdatagram.h"
67#include "qnetworkinterface.h"
68#include "qabstractsocket_p.h"
69
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
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, QHostAddress()); }
89
90 inline bool ensureInitialized(const QHostAddress &remoteAddress)
91 { return doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
92};
93
94bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
95 const QHostAddress &remoteAddress)
96{
97 const QHostAddress *address = &bindAddress;
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(remoteAddress.toString(), bindPort);
107 if (!initSocketLayer(address->protocol()))
108 return false;
109 }
110
111 return true;
112}
113
122 : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
123{
124 d_func()->isBuffered = false;
125}
126
133{
134}
135
136#ifndef QT_NO_NETWORKINTERFACE
137
159{
160 return joinMulticastGroup(groupAddress, QNetworkInterface());
161}
162
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
196{
197 return leaveMulticastGroup(groupAddress, QNetworkInterface());
198}
199
213 const QNetworkInterface &iface)
214{
215 QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
216 return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
217}
218
232{
233 Q_D(const QUdpSocket);
234 QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
235 return d->socketEngine->multicastInterface();
236}
237
249{
250 Q_D(QUdpSocket);
251 if (!isValid()) {
252 qWarning("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
267{
268 QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
269 return d_func()->socketEngine->hasPendingDatagrams();
270}
271
279{
280 QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
281 return d_func()->socketEngine->pendingDatagramSize();
282}
283
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(QHostAddress::Any, 0, address))
314 return -1;
315 if (state() == UnconnectedState)
316 bind();
317
318 qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
319 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
320
321 if (sent >= 0) {
322 emit bytesWritten(sent);
323 } else {
324 if (sent == -2) {
325 // Socket engine reports EAGAIN. Treat as a temporary error.
326 d->setErrorAndEmit(QAbstractSocket::TemporaryError,
327 tr("Unable to send a datagram"));
328 return -1;
329 }
330 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
331 }
332 return sent;
333}
334
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(),
378 datagram.destinationPort());
379#endif
380 if (!d->doEnsureInitialized(QHostAddress::Any, 0, datagram.destinationAddress()))
381 return -1;
382 if (state() == UnconnectedState)
383 bind();
384
385 qint64 sent = d->socketEngine->writeDatagram(datagram.d->data,
386 datagram.d->data.size(),
387 datagram.d->header);
388 d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
389
390 if (sent >= 0) {
391 emit bytesWritten(sent);
392 } else {
393 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
394 }
395 return sent;
396}
397
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
430 qint64 readBytes = d->socketEngine->readDatagram(result.d->data.data(), maxSize, &result.d->header,
432 d->hasPendingData = false;
433 d->socketEngine->setReadNotificationEnabled(true);
434 if (readBytes < 0) {
435 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
436 readBytes = 0;
437 }
438
439 result.d->data.truncate(readBytes);
440 return result;
441}
442
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) {
471 readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
473 if (address)
474 *address = header.senderAddress;
475 if (port)
476 *port = header.senderPort;
477 } else {
478 readBytes = d->socketEngine->readDatagram(data, 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(QAbstractSocket::TemporaryError,
487 tr("No datagram available for reading"));
488 return -1;
489 }
490 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
491 }
492 return readBytes;
493}
494
495#endif // QT_NO_UDPSOCKET
496
498
499#include "moc_qudpsocket.cpp"
virtual bool isValid() const =0
QAbstractSocketEngine * socketEngine
void resolveProxy(const QString &hostName, quint16 port)
bool initSocketLayer(QAbstractSocket::NetworkLayerProtocol protocol)
The QAbstractSocket class provides the base functionality common to all socket types.
virtual bool bind(const QHostAddress &address, quint16 port=0, BindMode mode=DefaultForPlatform)
static constexpr auto UnknownNetworkLayerProtocol
bool isValid() const
Returns true if the socket is valid and ready for use; otherwise returns false.
SocketState state() const
Returns the state of the socket.
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
The QHostAddress class provides an IP address.
QString toString() const
Returns the address as a string.
NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
void bytesWritten(qint64 bytes)
This signal is emitted every time a payload of data has been written to the device's current write ch...
The QNetworkDatagram class provides the data and metadata of a UDP datagram.
QHostAddress destinationAddress() const
Returns the destination address associated with this datagram.
int destinationPort() const
Returns the port number of the destination associated with this datagram.
The QNetworkInterface class provides a listing of the host's IP addresses and network interfaces.
\inmodule QtCore
Definition qobject.h:90
QByteArray toLatin1() const &
Definition qstring.h:559
bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
bool ensureInitialized(const QHostAddress &remoteAddress)
\reentrant
Definition qudpsocket.h:21
bool leaveMulticastGroup(const QHostAddress &groupAddress)
bool joinMulticastGroup(const QHostAddress &groupAddress)
QNetworkDatagram receiveDatagram(qint64 maxSize=-1)
QNetworkInterface multicastInterface() const
bool hasPendingDatagrams() const
Returns true if at least one datagram is waiting to be read; otherwise returns false.
virtual ~QUdpSocket()
Destroys the socket, closing the connection if necessary.
qint64 writeDatagram(const QNetworkDatagram &datagram)
void setMulticastInterface(const QNetworkInterface &iface)
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host=nullptr, quint16 *port=nullptr)
Receives a datagram no larger than maxSize bytes and stores it in data.
qint64 pendingDatagramSize() const
Returns the size of the first pending UDP datagram.
QUdpSocket(QObject *parent=nullptr)
Creates a QUdpSocket object.
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
static QString header(const QString &name)
EGLOutputPortEXT port
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint64EXT address
GLuint64EXT * result
[6]
#define tr(X)
#define emit
unsigned short quint16
Definition qtypes.h:43
long long qint64
Definition qtypes.h:55
#define QT_CHECK_BOUND(function, a)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent