QtBase  v6.3.1
qudpsocket.cpp
Go to the documentation of this file.
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 
100 #include "qudpsocket.h"
101 #include "qhostaddress.h"
102 #include "qnetworkdatagram.h"
103 #include "qnetworkinterface.h"
104 #include "qabstractsocket_p.h"
105 
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 
117 {
118  Q_DECLARE_PUBLIC(QUdpSocket)
119 
120  bool doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
121  const QHostAddress &remoteAddress);
122 public:
123  inline bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
124  { return doEnsureInitialized(bindAddress, bindPort, QHostAddress()); }
125 
126  inline bool ensureInitialized(const QHostAddress &remoteAddress)
127  { return doEnsureInitialized(QHostAddress(), 0, remoteAddress); }
128 };
129 
130 bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
131  const QHostAddress &remoteAddress)
132 {
133  const QHostAddress *address = &bindAddress;
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(remoteAddress.toString(), bindPort);
143  if (!initSocketLayer(address->protocol()))
144  return false;
145  }
146 
147  return true;
148 }
149 
158  : QAbstractSocket(UdpSocket, *new QUdpSocketPrivate, parent)
159 {
160  d_func()->isBuffered = false;
161 }
162 
169 {
170 }
171 
172 #ifndef QT_NO_NETWORKINTERFACE
173 
195 {
196  return joinMulticastGroup(groupAddress, QNetworkInterface());
197 }
198 
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 
232 {
233  return leaveMulticastGroup(groupAddress, QNetworkInterface());
234 }
235 
249  const QNetworkInterface &iface)
250 {
251  QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false);
252  return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface);
253 }
254 
268 {
269  Q_D(const QUdpSocket);
270  QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface());
271  return d->socketEngine->multicastInterface();
272 }
273 
285 {
286  Q_D(QUdpSocket);
287  if (!isValid()) {
288  qWarning("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 
303 {
304  QT_CHECK_BOUND("QUdpSocket::hasPendingDatagrams()", false);
305  return d_func()->socketEngine->hasPendingDatagrams();
306 }
307 
315 {
316  QT_CHECK_BOUND("QUdpSocket::pendingDatagramSize()", -1);
317  return d_func()->socketEngine->pendingDatagramSize();
318 }
319 
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(QHostAddress::Any, 0, address))
350  return -1;
351  if (state() == UnconnectedState)
352  bind();
353 
354  qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
355  d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
356 
357  if (sent >= 0) {
358  emit bytesWritten(sent);
359  } else {
360  if (sent == -2) {
361  // Socket engine reports EAGAIN. Treat as a temporary error.
362  d->setErrorAndEmit(QAbstractSocket::TemporaryError,
363  tr("Unable to send a datagram"));
364  return -1;
365  }
366  d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
367  }
368  return sent;
369 }
370 
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(),
414  datagram.destinationPort());
415 #endif
416  if (!d->doEnsureInitialized(QHostAddress::Any, 0, datagram.destinationAddress()))
417  return -1;
418  if (state() == UnconnectedState)
419  bind();
420 
421  qint64 sent = d->socketEngine->writeDatagram(datagram.d->data,
422  datagram.d->data.size(),
423  datagram.d->header);
424  d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
425 
426  if (sent >= 0) {
427  emit bytesWritten(sent);
428  } else {
429  d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
430  }
431  return sent;
432 }
433 
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 
466  qint64 readBytes = d->socketEngine->readDatagram(result.d->data.data(), maxSize, &result.d->header,
468  d->hasPendingData = false;
469  d->socketEngine->setReadNotificationEnabled(true);
470  if (readBytes < 0) {
471  d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
472  readBytes = 0;
473  }
474 
475  result.d->data.truncate(readBytes);
476  return result;
477 }
478 
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) {
507  readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
509  if (address)
510  *address = header.senderAddress;
511  if (port)
512  *port = header.senderPort;
513  } else {
514  readBytes = d->socketEngine->readDatagram(data, 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(QAbstractSocket::TemporaryError,
523  tr("No datagram available for reading"));
524  return -1;
525  }
526  d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
527  }
528  return readBytes;
529 }
530 
531 #endif // QT_NO_UDPSOCKET
532 
virtual bool isValid() const =0
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
SocketState state() const
QAbstractSocketEngine * socketEngine
void resolveProxy(const QString &hostName, quint16 port)
bool initSocketLayer(QAbstractSocket::NetworkLayerProtocol protocol)
qsizetype size() const noexcept
Definition: qbytearray.h:470
const char * constData() const noexcept
Definition: qbytearray.h:144
The QHostAddress class provides an IP address.\inmodule QtNetwork.
Definition: qhostaddress.h:74
QString toString() const
NetworkLayerProtocol protocol() const
void bytesWritten(qint64 bytes)
The QNetworkDatagram class provides the data and metadata of a UDP datagram.
QHostAddress destinationAddress() const
int destinationPort() const
The QNetworkInterface class provides a listing of the host's IP addresses and network interfaces.
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QByteArray toLatin1() const &
Definition: qstring.h:745
The QUdpSocket class provides a UDP socket.
Definition: qudpsocket.h:57
bool leaveMulticastGroup(const QHostAddress &groupAddress)
Definition: qudpsocket.cpp:231
bool joinMulticastGroup(const QHostAddress &groupAddress)
Definition: qudpsocket.cpp:194
QNetworkDatagram receiveDatagram(qint64 maxSize=-1)
Definition: qudpsocket.cpp:451
QNetworkInterface multicastInterface() const
Definition: qudpsocket.cpp:267
bool hasPendingDatagrams() const
Definition: qudpsocket.cpp:302
virtual ~QUdpSocket()
Definition: qudpsocket.cpp:168
qint64 writeDatagram(const QNetworkDatagram &datagram)
Definition: qudpsocket.cpp:406
void setMulticastInterface(const QNetworkInterface &iface)
Definition: qudpsocket.cpp:284
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host=nullptr, quint16 *port=nullptr)
Definition: qudpsocket.cpp:494
qint64 pendingDatagramSize() const
Definition: qudpsocket.cpp:314
QUdpSocket(QObject *parent=nullptr)
Definition: qudpsocket.cpp:157
bool ensureInitialized(const QHostAddress &bindAddress, quint16 bindPort)
Definition: qudpsocket.cpp:123
bool ensureInitialized(const QHostAddress &remoteAddress)
Definition: qudpsocket.cpp:126
constexpr Initialization Uninitialized
Definition: qnamespace.h:1613
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputPortEXT port
unsigned short quint16
Definition: qglobal.h:286
long long qint64
Definition: qglobal.h:298
#define qDebug
[1]
Definition: qlogging.h:177
#define qWarning
Definition: qlogging.h:179
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint64EXT address
Definition: qopenglext.h:11428
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
#define tr(X)
#define emit
Definition: qtmetamacros.h:85
#define QT_CHECK_BOUND(function, a)
Definition: qudpsocket.cpp:110
QHttpRequestHeader header("GET", QUrl::toPercentEncoding("/index.html"))
[1]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent