diff --git a/src/libs/utils/tcpportsgatherer.cpp b/src/libs/utils/tcpportsgatherer.cpp index 447af431c02..9fefe090786 100644 --- a/src/libs/utils/tcpportsgatherer.cpp +++ b/src/libs/utils/tcpportsgatherer.cpp @@ -30,6 +30,8 @@ #include "tcpportsgatherer.h" #include "qtcassert.h" +#include + #include #include #include @@ -71,15 +73,15 @@ namespace Internal { class TcpPortsGathererPrivate { public: - TcpPortsGathererPrivate(TcpPortsGatherer::ProtocolFlags protocolFlags) - : protocolFlags(protocolFlags) {} + TcpPortsGathererPrivate() + : protocol(QAbstractSocket::UnknownNetworkLayerProtocol) {} - TcpPortsGatherer::ProtocolFlags protocolFlags; - PortList usedPorts; + QAbstractSocket::NetworkLayerProtocol protocol; + QSet usedPorts; - void updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags); - void updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags); - void updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags); + void updateWin(); + void updateLinux(); + void updateNetstat(); }; #ifdef Q_OS_WIN @@ -114,41 +116,51 @@ QSet usedTcpPorts(ULONG (__stdcall *Func)(Table*, PULONG, BOOL)) } #endif -void TcpPortsGathererPrivate::updateWin(TcpPortsGatherer::ProtocolFlags protocolFlags) +void TcpPortsGathererPrivate::updateWin() { #ifdef Q_OS_WIN QSet ports; - if (protocolFlags & TcpPortsGatherer::IPv4Protocol) + if (protocol == QAbstractSocket::IPv4Protocol) { ports.unite(usedTcpPorts(GetTcpTable)); + } else { + //Dynamically load symbol for GetTcp6Table for systems that dont have support for IPV6, + //eg Windows XP + typedef ULONG (__stdcall *GetTcp6TablePtr)(PMIB_TCP6TABLE, PULONG, BOOL); + static GetTcp6TablePtr getTcp6TablePtr = 0; - //Dynamically load symbol for GetTcp6Table for systems that dont have support for IPV6, - //eg Windows XP - typedef ULONG (__stdcall *GetTcp6TablePtr)(PMIB_TCP6TABLE, PULONG, BOOL); - static GetTcp6TablePtr getTcp6TablePtr = 0; + if (!getTcp6TablePtr) + getTcp6TablePtr = (GetTcp6TablePtr)QLibrary::resolve(QLatin1String("Iphlpapi.dll"), + "GetTcp6Table"); - if (!getTcp6TablePtr) - getTcp6TablePtr = (GetTcp6TablePtr)QLibrary::resolve(QLatin1String("Iphlpapi.dll"), - "GetTcp6Table"); - - if (getTcp6TablePtr && (protocolFlags & TcpPortsGatherer::IPv6Protocol)) - ports.unite(usedTcpPorts(getTcp6TablePtr)); + if (getTcp6TablePtr && (protocol == QAbstractSocket::IPv6Protocol)) { + ports.unite(usedTcpPorts(getTcp6TablePtr)); + } else if (protocol == QAbstractSocket::UnknownNetworkLayerProtocol) { + ports.unite(usedTcpPorts(GetTcpTable)); + if (getTcp6TablePtr) + ports.unite(usedTcpPorts(getTcp6TablePtr)); + } + } foreach (int port, ports) { if (!usedPorts.contains(port)) usedPorts.addPort(port); } #endif - Q_UNUSED(protocolFlags); + Q_UNUSED(protocol); } -void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protocolFlags) +void TcpPortsGathererPrivate::updateLinux() { QStringList filePaths; - if (protocolFlags & TcpPortsGatherer::IPv4Protocol) - filePaths.append(QLatin1String("/proc/net/tcp")); - if (protocolFlags & TcpPortsGatherer::IPv6Protocol) - filePaths.append(QLatin1String("/proc/net/tcp6")); + const QString tcpFile = QLatin1String("/proc/net/tcp"); + const QString tcp6File = QLatin1String("/proc/net/tcp6"); + if (protocol == QAbstractSocket::IPv4Protocol) + filePaths << tcpFile; + else if (protocol == QAbstractSocket::IPv6Protocol) + filePaths << tcp6File; + else + filePaths << tcpFile << tcp6File; foreach (const QString &filePath, filePaths) { QFile file(filePath); @@ -172,8 +184,7 @@ void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protoc bool isNumber; quint16 port = pattern.cap(1).toUShort(&isNumber, 16); QTC_ASSERT(isNumber, continue); - if (!usedPorts.contains(port)) - usedPorts.addPort(port); + usedPorts.insert(port); } else { qWarning() << "TcpPortsGatherer: File" << filePath << "has unexpected format."; continue; @@ -183,7 +194,7 @@ void TcpPortsGathererPrivate::updateLinux(TcpPortsGatherer::ProtocolFlags protoc } // Only works with FreeBSD version of netstat like we have on Mac OS X -void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags protocolFlags) +void TcpPortsGathererPrivate::updateNetstat() { QStringList netstatArgs; @@ -191,9 +202,9 @@ void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags prot netstatArgs.append(QLatin1String("-n")); // show network addresses as numbers netstatArgs.append(QLatin1String("-p")); netstatArgs.append(QLatin1String("tcp")); - if (protocolFlags != TcpPortsGatherer::AnyIPProcol) { + if (protocol != QAbstractSocket::UnknownNetworkLayerProtocol) { netstatArgs.append(QLatin1String("-f")); // limit to address family - if (protocolFlags == TcpPortsGatherer::IPv4Protocol) + if (protocol == QAbstractSocket::IPv4Protocol) netstatArgs.append(QLatin1String("inet")); else netstatArgs.append(QLatin1String("inet6")); @@ -227,8 +238,7 @@ void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags prot if (!isNumber) continue; - if (!usedPorts.contains(port)) - usedPorts.addPort(port); + usedPorts.insert(port); } } } @@ -245,10 +255,9 @@ void TcpPortsGathererPrivate::updateNetstat(TcpPortsGatherer::ProtocolFlags prot to select a port for use in a range. */ -TcpPortsGatherer::TcpPortsGatherer(TcpPortsGatherer::ProtocolFlags protocolFlags) - : d(new Internal::TcpPortsGathererPrivate(protocolFlags)) +TcpPortsGatherer::TcpPortsGatherer() + : d(new Internal::TcpPortsGathererPrivate()) { - update(); } TcpPortsGatherer::~TcpPortsGatherer() @@ -256,38 +265,38 @@ TcpPortsGatherer::~TcpPortsGatherer() delete d; } -void TcpPortsGatherer::update() +void TcpPortsGatherer::update(QAbstractSocket::NetworkLayerProtocol protocol) { - d->usedPorts = PortList(); + d->protocol = protocol; + d->usedPorts.clear(); -#if defined(Q_OS_WIN) - d->updateWin(d->protocolFlags); -#elif defined(Q_OS_LINUX) - d->updateLinux(d->protocolFlags); -#else - d->updateNetstat(d->protocolFlags); -#endif + if (Utils::HostOsInfo::isWindowsHost()) + d->updateWin(); + else if (Utils::HostOsInfo::isLinuxHost()) + d->updateLinux(); + else + d->updateNetstat(); } -PortList TcpPortsGatherer::usedPorts() const +QList TcpPortsGatherer::usedPorts() const { - return d->usedPorts; + return d->usedPorts.values(); } /*! Select a port out of \a freePorts that is not yet used. - Returns the port, or 0 if no free port is available. + Returns the port, or -1 if no free port is available. */ -quint16 TcpPortsGatherer::getNextFreePort(PortList *freePorts) +int TcpPortsGatherer::getNextFreePort(PortList *freePorts) const { - QTC_ASSERT(freePorts, return 0); + QTC_ASSERT(freePorts, return -1); while (freePorts->hasMore()) { const int port = freePorts->getNext(); if (!d->usedPorts.contains(port)) return port; } - return 0; + return -1; } } // namespace Utils diff --git a/src/libs/utils/tcpportsgatherer.h b/src/libs/utils/tcpportsgatherer.h index a0b6ea16692..922b618f0c0 100644 --- a/src/libs/utils/tcpportsgatherer.h +++ b/src/libs/utils/tcpportsgatherer.h @@ -32,6 +32,8 @@ #include "portlist.h" +#include + namespace Utils { namespace Internal { class TcpPortsGathererPrivate; @@ -40,20 +42,13 @@ class TcpPortsGathererPrivate; class QTCREATOR_UTILS_EXPORT TcpPortsGatherer { public: - enum NetworkLayerProtocol { - IPv4Protocol = 0x1, - IPv6Protocol = 0x2, - AnyIPProcol = IPv4Protocol | IPv6Protocol - }; - Q_DECLARE_FLAGS(ProtocolFlags, NetworkLayerProtocol) - - TcpPortsGatherer(ProtocolFlags flags); + TcpPortsGatherer(); ~TcpPortsGatherer(); - void update(); + void update(QAbstractSocket::NetworkLayerProtocol protocol); - PortList usedPorts() const; - quint16 getNextFreePort(PortList *port); + QList usedPorts() const; + int getNextFreePort(PortList *port) const; private: Internal::TcpPortsGathererPrivate *d; diff --git a/tests/manual/utils/tcpportsgatherer/main.cpp b/tests/manual/utils/tcpportsgatherer/main.cpp index f20756616c8..7b6c142db0e 100644 --- a/tests/manual/utils/tcpportsgatherer/main.cpp +++ b/tests/manual/utils/tcpportsgatherer/main.cpp @@ -8,23 +8,24 @@ int main() { qDebug() << "Used TCP Ports (IP4):"; - TcpPortsGatherer ip4Ports(TcpPortsGatherer::IPv4Protocol); - qDebug() << ip4Ports.usedPorts().toString(); + TcpPortsGatherer portsGatherer; + portsGatherer.update(QAbstractSocket::IPv4Protocol); + qDebug() << portsGatherer.usedPorts(); qDebug() << "Used TCP Ports (IP6):"; - TcpPortsGatherer ip6Ports(TcpPortsGatherer::IPv6Protocol); - qDebug() << ip6Ports.usedPorts().toString(); + portsGatherer.update(QAbstractSocket::IPv6Protocol); + qDebug() << portsGatherer.usedPorts(); qDebug() << "All Used TCP Ports:"; - TcpPortsGatherer ipPorts(TcpPortsGatherer::AnyIPProcol); - qDebug() << ipPorts.usedPorts().toString(); + portsGatherer.update(QAbstractSocket::UnknownNetworkLayerProtocol); + qDebug() << portsGatherer.usedPorts(); qDebug() << "Getting a few ports ..."; PortList portList = PortList::fromString(QLatin1String("10000-10100")); QStringList ports; for (int i = 0; i < 10; ++i) { - quint16 port = ipPorts.getNextFreePort(&portList); - Q_ASSERT(!ipPorts.usedPorts().contains(port)); + quint16 port = portsGatherer.getNextFreePort(&portList); + Q_ASSERT(!portsGatherer.usedPorts().contains(port)); Q_ASSERT(port >= 10000); Q_ASSERT(port < 10100); QString portStr = QString::number(port); diff --git a/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro index 001b5f41ad6..158505521db 100644 --- a/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro +++ b/tests/manual/utils/tcpportsgatherer/tcpportsgatherer.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = tcpportsgatherer -QT = core gui +QT = core gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += console