📄 qhostaddress.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtNetwork module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qdebug.h"#include "qhostaddress.h"#include "qplatformdefs.h"#include "qstringlist.h"#ifndef QT_NO_DATASTREAM#include <qdatastream.h>#endif#ifdef QT_LSB# include <arpa/inet.h>#endif#define QT_ENSURE_PARSED(a) \ do { \ if (!(a)->d->isParsed) \ (a)->d->parse(); \ } while (0)#ifdef Q_OS_WIN# if !defined (QT_NO_IPV6)// sockaddr_in6 size changed between old and new SDK// Only the new version is the correct one, so always// use this structure.struct qt_in6_addr { u_char qt_s6_addr[16];};typedef struct { short sin6_family; /* AF_INET6 */ u_short sin6_port; /* Transport level port number */ u_long sin6_flowinfo; /* IPv6 flow information */ struct qt_in6_addr sin6_addr; /* IPv6 address */ u_long sin6_scope_id; /* set of interfaces for a scope */} qt_sockaddr_in6;# elsetypedef void * qt_sockaddr_in6 ;# endif# ifndef AF_INET6# define AF_INET6 23 /* Internetwork Version 6 */# endif#else#define qt_sockaddr_in6 sockaddr_in6#define qt_s6_addr s6_addr#endifclass QHostAddressPrivate{public: QHostAddressPrivate(); void setAddress(quint32 a_ = 0); void setAddress(const quint8 *a_); void setAddress(const Q_IPV6ADDR &a_); bool parse(); void clear();private: quint32 a; // IPv4 address Q_IPV6ADDR a6; // IPv6 address QAbstractSocket::NetworkLayerProtocol protocol; QString ipString; bool isParsed; QString scopeId; friend class QHostAddress;};QHostAddressPrivate::QHostAddressPrivate() : a(0), protocol(QAbstractSocket::UnknownNetworkLayerProtocol), isParsed(true){ memset(&a6, 0, sizeof(a6));}void QHostAddressPrivate::setAddress(quint32 a_){ a = a_; protocol = QAbstractSocket::IPv4Protocol; isParsed = true;}void QHostAddressPrivate::setAddress(const quint8 *a_){ for (int i = 0; i < 16; i++) a6[i] = a_[i]; protocol = QAbstractSocket::IPv6Protocol; isParsed = true;}void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_){ a6 = a_; a = 0; protocol = QAbstractSocket::IPv6Protocol; isParsed = true;}static bool parseIp4(const QString& address, quint32 *addr){ QStringList ipv4 = address.split(QLatin1String(".")); if (ipv4.count() != 4) return false; quint32 ipv4Address = 0; for (int i = 0; i < 4; ++i) { bool ok = false; uint byteValue = ipv4.at(i).toUInt(&ok); if (!ok || byteValue > 255) return false; ipv4Address <<= 8; ipv4Address += byteValue; } *addr = ipv4Address; return true;}static bool parseIp6(const QString &address, quint8 *addr, QString *scopeId){ QString tmp = address; int scopeIdPos = tmp.lastIndexOf(QLatin1Char('%')); if (scopeIdPos != -1) { *scopeId = tmp.mid(scopeIdPos + 1); tmp.chop(tmp.size() - scopeIdPos); } else { scopeId->clear(); } QStringList ipv6 = tmp.split(QLatin1String(":")); int count = ipv6.count(); if (count < 3 || count > 8) return false; int mc = 16; int fillCount = 9 - count; // number of 0 words to fill in the middle for (int i = count - 1; i >= 0; --i) { if (mc <= 0) return false; if (ipv6.at(i).isEmpty()) { if (i == count - 1) { // special case: ":" is last character if (!ipv6.at(i - 1).isEmpty()) return false; addr[--mc] = 0; addr[--mc] = 0; } else if (i == 0) { // special case: ":" is first character if (!ipv6.at(i + 1).isEmpty()) return false; addr[--mc] = 0; addr[--mc] = 0; } else { for (int j = 0; j < fillCount; ++j) { if (mc <= 0) return false; addr[--mc] = 0; addr[--mc] = 0; } } } else { bool ok = false; uint byteValue = ipv6.at(i).toUInt(&ok, 16); if (ok && byteValue <= 0xffff) { addr[--mc] = byteValue & 0xff; addr[--mc] = (byteValue >> 8) & 0xff; } else { if (i != count - 1) return false; // parse the ipv4 part of a mixed type quint32 maybeIp4; if (!parseIp4(ipv6.at(i), &maybeIp4)) return false; addr[--mc] = maybeIp4 & 0xff; addr[--mc] = (maybeIp4 >> 8) & 0xff; addr[--mc] = (maybeIp4 >> 16) & 0xff; addr[--mc] = (maybeIp4 >> 24) & 0xff; --fillCount; } } } return true;}bool QHostAddressPrivate::parse(){ isParsed = true; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; QString a = ipString.simplified(); // All IPv6 addresses contain a ':', and may contain a '.'. if (a.contains(QLatin1Char(':'))) { quint8 maybeIp6[16]; if (parseIp6(a, maybeIp6, &scopeId)) { setAddress(maybeIp6); protocol = QAbstractSocket::IPv6Protocol; return true; } } // All IPv4 addresses contain a '.'. if (a.contains(QLatin1Char('.'))) { quint32 maybeIp4 = 0; if (parseIp4(a, &maybeIp4)) { setAddress(maybeIp4); protocol = QAbstractSocket::IPv4Protocol; return true; } } return false;}void QHostAddressPrivate::clear(){ a = 0; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; isParsed = true; memset(&a6, 0, sizeof(a6));}/*! \class QHostAddress \brief The QHostAddress class provides an IP address. \ingroup io \module network This class holds an IPv4 or IPv6 address in a platform- and protocol-independent manner. QHostAddress is normally used with the QTcpSocket, QTcpServer, and QUdpSocket to connect to a host or to set up a server. A host address is set with setAddress(), checked for its type using isIPv4Address() or isIPv6Address(), and retrieved with toIPv4Address(), toIPv6Address(), or toString(). The class also supports common predefined addresses: \l Null, \l LocalHost, \l LocalHostIPv6, \l Broadcast, and \l Any. \sa QTcpSocket, QTcpServer, QUdpSocket*//*! \enum QHostAddress::SpecialAddress \value Null The null address object. Equivalent to QHostAddress(). \value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1"). \value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1"). \value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255"). \value Any The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::").*//*! Constructs a host address object with the IP address 0.0.0.0. \sa clear()*/QHostAddress::QHostAddress() : d(new QHostAddressPrivate){}/*! Constructs a host address object with the IPv4 address \a ip4Addr.*/QHostAddress::QHostAddress(quint32 ip4Addr) : d(new QHostAddressPrivate){ setAddress(ip4Addr);}/*! Constructs a host address object with the IPv6 address \a ip6Addr. \a ip6Addr must be a 16-byte array in network byte order (big endian).*/QHostAddress::QHostAddress(quint8 *ip6Addr) : d(new QHostAddressPrivate){ setAddress(ip6Addr);}/*! Constructs a host address object with the IPv6 address \a ip6Addr.*/QHostAddress::QHostAddress(const Q_IPV6ADDR &ip6Addr) : d(new QHostAddressPrivate){ setAddress(ip6Addr);}/*! Constructs an IPv4 or IPv6 address based on the string \a address (e.g., "127.0.0.1"). \sa setAddress()*/QHostAddress::QHostAddress(const QString &address) : d(new QHostAddressPrivate){ d->ipString = address; d->isParsed = false;}/*! \fn QHostAddress::QHostAddress(const sockaddr *sockaddr) Constructs an IPv4 or IPv6 address using the address specified by the native structure \a sockaddr. \sa setAddress()*/QHostAddress::QHostAddress(const struct sockaddr *sockaddr) : d(new QHostAddressPrivate){ if (sockaddr->sa_family == AF_INET) setAddress(htonl(((sockaddr_in *)sockaddr)->sin_addr.s_addr));#ifndef QT_NO_IPV6 else if (sockaddr->sa_family == AF_INET6) setAddress(((qt_sockaddr_in6 *)sockaddr)->sin6_addr.qt_s6_addr);#endif}/*! Constructs a copy of the given \a address.*/QHostAddress::QHostAddress(const QHostAddress &address) : d(new QHostAddressPrivate(*address.d)){}/*! Constructs a QHostAddress object for \a address.*/QHostAddress::QHostAddress(SpecialAddress address) : d(new QHostAddressPrivate){ switch (address) { case Null: break; case Broadcast: setAddress(QLatin1String("255.255.255.255")); break; case LocalHost: setAddress(QLatin1String("127.0.0.1")); break; case LocalHostIPv6: setAddress(QLatin1String("::1")); break; case Any: setAddress(QLatin1String("0.0.0.0")); break; case AnyIPv6: setAddress(QLatin1String("::")); break; }}/*! Destroys the host address object.*/QHostAddress::~QHostAddress(){ delete d;}/*! Assigns another host \a address to this object, and returns a reference
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -