QAbstractSocket: fake a bind(QHostAddress::SpecialAddress)

Because this is misleading:

  socket.bind(QHostAddress::AnyIPv4);

The conversion of enum to int has preference over the construction of
QHostAddress from enum, so that ends up calling bind(6), which attempts
to bind to privileged port 6 and just returns with error. Meanwhile,

  socket.bind(QHostAddress::AnyIPv4, 0);

does construct the QHostAddress because that is preferred to converting
the int to the BindMode enum.

Ideally we'd simply add the overload to QAbstractSocket but we can't do
that because QHostAddress depends on QAbstractSocket. So I've added a
Qt7 task to invert that dependency.

Change-Id: I26b8286f61534f88b649fffd166b683266597796
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2021-03-11 13:50:56 -08:00
parent 180f78d126
commit 8614491aa1
5 changed files with 40 additions and 0 deletions

View File

@ -115,6 +115,8 @@ public:
bool setAddress(const QString &address); bool setAddress(const QString &address);
void setAddress(SpecialAddress address); void setAddress(SpecialAddress address);
// ### Qt7: consider moving NetworkLayerProtocol to QHostAddress so we
// don't depend on QAbstractSocket
QAbstractSocket::NetworkLayerProtocol protocol() const; QAbstractSocket::NetworkLayerProtocol protocol() const;
quint32 toIPv4Address(bool *ok = nullptr) const; quint32 toIPv4Address(bool *ok = nullptr) const;
Q_IPV6ADDR toIPv6Address() const; Q_IPV6ADDR toIPv6Address() const;

View File

@ -1604,6 +1604,19 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb
} }
/*! /*!
\fn bool QAbstractSocket::bind(QHostAddress::SpecialAddress addr, quint16 port, BindMode mode)
\since 6.2
\overload
Binds to the special address \a addr on port \a port, using the BindMode \a
mode.
By default, the socket is bound using the DefaultForPlatform BindMode.
If a port is not specified, a random port is chosen.
*/
/*!
\fn bool QAbstractSocket::bind(quint16 port, BindMode mode)
\since 5.0 \since 5.0
\overload \overload
@ -1612,10 +1625,12 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb
By default, the socket is bound using the DefaultForPlatform BindMode. By default, the socket is bound using the DefaultForPlatform BindMode.
If a port is not specified, a random port is chosen. If a port is not specified, a random port is chosen.
*/ */
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
bool QAbstractSocket::bind(quint16 port, BindMode mode) bool QAbstractSocket::bind(quint16 port, BindMode mode)
{ {
return bind(QHostAddress::Any, port, mode); return bind(QHostAddress::Any, port, mode);
} }
#endif
/*! /*!
Returns \c true if the socket is valid and ready for use; otherwise Returns \c true if the socket is valid and ready for use; otherwise

View File

@ -148,7 +148,15 @@ public:
virtual bool bind(const QHostAddress &address, quint16 port = 0, virtual bool bind(const QHostAddress &address, quint16 port = 0,
BindMode mode = DefaultForPlatform); BindMode mode = DefaultForPlatform);
#if QT_VERSION >= QT_VERSION_CHECK(7,0,0) || defined(Q_CLANG_QDOC)
// ### Qt7: this requires that QHostAddress stop depending on QAbstractSocket::NetworkLayerProtocol
bool bind(QHostAddress::SpecialAddress addr, quint16 port = 0, BindMode mode = DefaultForPlatform)
{ return bind(QHostAddress(addr), port, mode); }
bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform)
{ retrurn bind(QHostAddress::Any, port, mode); }
#else
bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform); bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform);
#endif
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol); virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);
void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite); void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite);

View File

@ -42,6 +42,7 @@
#include <QtNetwork/qtnetworkglobal.h> #include <QtNetwork/qtnetworkglobal.h>
#include <QtNetwork/qabstractsocket.h> #include <QtNetwork/qabstractsocket.h>
#include <QtNetwork/qhostaddress.h>
#include <QtCore/qvariant.h> #include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -56,6 +57,13 @@ public:
explicit QTcpSocket(QObject *parent = nullptr); explicit QTcpSocket(QObject *parent = nullptr);
virtual ~QTcpSocket(); virtual ~QTcpSocket();
#if QT_VERSION < QT_VERSION_CHECK(7,0,0) && !defined(Q_CLANG_QDOC)
// ### Qt7: move into QAbstractSocket
using QAbstractSocket::bind;
bool bind(QHostAddress::SpecialAddress addr, quint16 port = 0, BindMode mode = DefaultForPlatform)
{ return bind(QHostAddress(addr), port, mode); }
#endif
protected: protected:
QTcpSocket(QTcpSocketPrivate &dd, QObject *parent = nullptr); QTcpSocket(QTcpSocketPrivate &dd, QObject *parent = nullptr);
QTcpSocket(QAbstractSocket::SocketType socketType, QTcpSocketPrivate &dd, QTcpSocket(QAbstractSocket::SocketType socketType, QTcpSocketPrivate &dd,

View File

@ -60,6 +60,13 @@ public:
explicit QUdpSocket(QObject *parent = nullptr); explicit QUdpSocket(QObject *parent = nullptr);
virtual ~QUdpSocket(); virtual ~QUdpSocket();
#if QT_VERSION < QT_VERSION_CHECK(7,0,0) && !defined(Q_CLANG_QDOC)
// ### Qt7: move into QAbstractSocket
using QAbstractSocket::bind;
bool bind(QHostAddress::SpecialAddress addr, quint16 port = 0, BindMode mode = DefaultForPlatform)
{ return bind(QHostAddress(addr), port, mode); }
#endif
#ifndef QT_NO_NETWORKINTERFACE #ifndef QT_NO_NETWORKINTERFACE
bool joinMulticastGroup(const QHostAddress &groupAddress); bool joinMulticastGroup(const QHostAddress &groupAddress);
bool joinMulticastGroup(const QHostAddress &groupAddress, bool joinMulticastGroup(const QHostAddress &groupAddress,