Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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
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(),
377 datagram.destinationAddress().toString().toLatin1().constData(),
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.constData(),
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->hasPendingDatagram = false;
434 d->socketEngine->setReadNotificationEnabled(true);
435 if (readBytes < 0) {
436 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
437 readBytes = 0;
438 }
439
440 result.d->data.truncate(readBytes);
441 return result;
442}
443
460 quint16 *port)
461{
462 Q_D(QUdpSocket);
463
464#if defined QUDPSOCKET_DEBUG
465 qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
466#endif
467 QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
468
469 qint64 readBytes;
470 if (address || port) {
472 readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
474 if (address)
475 *address = header.senderAddress;
476 if (port)
477 *port = header.senderPort;
478 } else {
479 readBytes = d->socketEngine->readDatagram(data, maxSize);
480 }
481
482 d->hasPendingData = false;
483 d->hasPendingDatagram = false;
484 d->socketEngine->setReadNotificationEnabled(true);
485 if (readBytes < 0) {
486 if (readBytes == -2) {
487 // No pending datagram. Treat as a temporary error.
488 d->setErrorAndEmit(QAbstractSocket::TemporaryError,
489 tr("No datagram available for reading"));
490 return -1;
491 }
492 d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
493 }
494 return readBytes;
495}
496
497#endif // QT_NO_UDPSOCKET
498
500
501#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.
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.
The QNetworkDatagram class provides the data and metadata of a UDP datagram.
The QNetworkInterface class provides a listing of the host's IP addresses and network interfaces.
\inmodule QtCore
Definition qobject.h:103
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)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputPortEXT port
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
GLenum GLsizei GLuint GLint * bytesWritten
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:48
long long qint64
Definition qtypes.h:60
#define QT_CHECK_BOUND(function, a)