Merge the multiple implementations of getting the local hostname
This commit moves the functionality from QtNetwork's QHostInfo to QtCore. Note that due to Windows ws2_32.dll's quirky behavior of requiring WSAStartup before calling gethostname, this change required moving the initialization to QtCore too. On Linux systems, gethostname() gets the name from uname(), so we bypass the middle man and save one memcpy. Change-Id: I27eaacb532114dd188c4ffff13d32655a6301346 Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com> Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
2366ca059e
commit
01d0b1d6e3
@ -65,6 +65,20 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINRT
|
||||
#include <wrl.h>
|
||||
#include <windows.networking.h>
|
||||
#include <windows.networking.sockets.h>
|
||||
#include <windows.networking.connectivity.h>
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Foundation::Collections;
|
||||
using namespace ABI::Windows::Networking;
|
||||
using namespace ABI::Windows::Networking::Connectivity;
|
||||
using namespace ABI::Windows::Networking::Sockets;
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
|
||||
# include <envLib.h>
|
||||
#endif
|
||||
@ -90,6 +104,10 @@
|
||||
#include <private/qcore_unix_p.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_BSD4
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include "archdetect.cpp"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -1887,6 +1905,36 @@ QT_END_INCLUDE_NAMESPACE
|
||||
|
||||
#ifndef Q_OS_WINRT
|
||||
|
||||
# ifndef QT_BOOTSTRAPPED
|
||||
class QWindowsSockInit
|
||||
{
|
||||
public:
|
||||
QWindowsSockInit();
|
||||
~QWindowsSockInit();
|
||||
int version;
|
||||
};
|
||||
|
||||
QWindowsSockInit::QWindowsSockInit()
|
||||
: version(0)
|
||||
{
|
||||
//### should we try for 2.2 on all platforms ??
|
||||
WSAData wsadata;
|
||||
|
||||
// IPv6 requires Winsock v2.0 or better.
|
||||
if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
|
||||
qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
|
||||
} else {
|
||||
version = 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
QWindowsSockInit::~QWindowsSockInit()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
|
||||
# endif // QT_BOOTSTRAPPED
|
||||
|
||||
# ifndef Q_OS_WINCE
|
||||
|
||||
// Determine Windows versions >= 8 by querying the version of kernel32.dll.
|
||||
@ -2775,6 +2823,82 @@ QString QSysInfo::prettyProductName()
|
||||
return unknownText();
|
||||
}
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
/*!
|
||||
\since 5.6
|
||||
|
||||
Returns this machine's host name, if one is configured. Note that hostnames
|
||||
are not guaranteed to be globally unique, especially if they were
|
||||
configured automatically.
|
||||
|
||||
This function does not guarantee the returned host name is a Fully
|
||||
Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the
|
||||
returned name to an FQDN.
|
||||
|
||||
This function returns the same as QHostInfo::localHostName().
|
||||
|
||||
\sa QHostInfo::localDomainName
|
||||
*/
|
||||
QString QSysInfo::machineHostName()
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
// gethostname(3) on Linux just calls uname(2), so do it ourselves
|
||||
// and avoid a memcpy
|
||||
struct utsname u;
|
||||
if (uname(&u) == 0)
|
||||
return QString::fromLocal8Bit(u.nodename);
|
||||
#elif defined(Q_OS_WINRT)
|
||||
ComPtr<INetworkInformationStatics> statics;
|
||||
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
|
||||
|
||||
ComPtr<IVectorView<HostName *>> hostNames;
|
||||
statics->GetHostNames(&hostNames);
|
||||
if (!hostNames)
|
||||
return QString();
|
||||
|
||||
unsigned int size;
|
||||
hostNames->get_Size(&size);
|
||||
if (size == 0)
|
||||
return QString();
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
ComPtr<IHostName> hostName;
|
||||
hostNames->GetAt(i, &hostName);
|
||||
HostNameType type;
|
||||
hostName->get_Type(&type);
|
||||
if (type != HostNameType_DomainName)
|
||||
continue;
|
||||
|
||||
HString name;
|
||||
hostName->get_CanonicalName(name.GetAddressOf());
|
||||
UINT32 length;
|
||||
PCWSTR rawString = name.GetRawBuffer(&length);
|
||||
return QString::fromWCharArray(rawString, length);
|
||||
}
|
||||
ComPtr<IHostName> firstHost;
|
||||
hostNames->GetAt(0, &firstHost);
|
||||
|
||||
HString name;
|
||||
firstHost->get_CanonicalName(name.GetAddressOf());
|
||||
UINT32 length;
|
||||
PCWSTR rawString = name.GetRawBuffer(&length);
|
||||
return QString::fromWCharArray(rawString, length);
|
||||
#else
|
||||
# ifdef Q_OS_WIN
|
||||
// Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
|
||||
winsockInit();
|
||||
# endif
|
||||
|
||||
char hostName[512];
|
||||
if (gethostname(hostName, sizeof(hostName)) == -1)
|
||||
return QString();
|
||||
hostName[sizeof(hostName) - 1] = '\0';
|
||||
return QString::fromLocal8Bit(hostName);
|
||||
#endif
|
||||
return QString();
|
||||
}
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
/*!
|
||||
\macro void Q_ASSERT(bool test)
|
||||
\relates <QtGlobal>
|
||||
|
@ -186,6 +186,8 @@ public:
|
||||
static QString productType();
|
||||
static QString productVersion();
|
||||
static QString prettyProductName();
|
||||
|
||||
static QString machineHostName();
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -415,10 +415,22 @@ void QHostInfo::setErrorString(const QString &str)
|
||||
/*!
|
||||
\fn QString QHostInfo::localHostName()
|
||||
|
||||
Returns the host name of this machine.
|
||||
Returns this machine's host name, if one is configured. Note that hostnames
|
||||
are not guaranteed to be globally unique, especially if they were
|
||||
configured automatically.
|
||||
|
||||
\sa hostName()
|
||||
This function does not guarantee the returned host name is a Fully
|
||||
Qualified Domain Name (FQDN). For that, use fromName() to resolve the
|
||||
returned name to an FQDN.
|
||||
|
||||
This function returns the same as QSysInfo::machineHostName().
|
||||
|
||||
\sa hostName(), localDomainName()
|
||||
*/
|
||||
QString QHostInfo::localHostName()
|
||||
{
|
||||
return QSysInfo::machineHostName();
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QString QHostInfo::localDomainName()
|
||||
|
@ -315,15 +315,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
|
||||
return results;
|
||||
}
|
||||
|
||||
QString QHostInfo::localHostName()
|
||||
{
|
||||
char hostName[512];
|
||||
if (gethostname(hostName, sizeof(hostName)) == -1)
|
||||
return QString();
|
||||
hostName[sizeof(hostName) - 1] = '\0';
|
||||
return QString::fromLocal8Bit(hostName);
|
||||
}
|
||||
|
||||
QString QHostInfo::localDomainName()
|
||||
{
|
||||
#if !defined(Q_OS_VXWORKS) && !defined(Q_OS_ANDROID)
|
||||
|
@ -111,7 +111,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
|
||||
QMutexLocker locker(&qPrivCEMutex);
|
||||
#endif
|
||||
|
||||
QWindowsSockInit winSock;
|
||||
QSysInfo::machineHostName(); // this initializes ws2_32.dll
|
||||
|
||||
// Load res_init on demand.
|
||||
static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false);
|
||||
@ -256,17 +256,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
|
||||
return results;
|
||||
}
|
||||
|
||||
QString QHostInfo::localHostName()
|
||||
{
|
||||
QWindowsSockInit winSock;
|
||||
|
||||
char hostName[512];
|
||||
if (gethostname(hostName, sizeof(hostName)) == -1)
|
||||
return QString();
|
||||
hostName[sizeof(hostName) - 1] = '\0';
|
||||
return QString::fromLocal8Bit(hostName);
|
||||
}
|
||||
|
||||
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -130,45 +130,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
|
||||
return results;
|
||||
}
|
||||
|
||||
QString QHostInfo::localHostName()
|
||||
{
|
||||
ComPtr<INetworkInformationStatics> statics;
|
||||
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
|
||||
|
||||
ComPtr<IVectorView<HostName *>> hostNames;
|
||||
statics->GetHostNames(&hostNames);
|
||||
if (!hostNames)
|
||||
return QString();
|
||||
|
||||
unsigned int size;
|
||||
hostNames->get_Size(&size);
|
||||
if (size == 0)
|
||||
return QString();
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
ComPtr<IHostName> hostName;
|
||||
hostNames->GetAt(i, &hostName);
|
||||
HostNameType type;
|
||||
hostName->get_Type(&type);
|
||||
if (type != HostNameType_DomainName)
|
||||
continue;
|
||||
|
||||
HString name;
|
||||
hostName->get_CanonicalName(name.GetAddressOf());
|
||||
UINT32 length;
|
||||
PCWSTR rawString = name.GetRawBuffer(&length);
|
||||
return QString::fromWCharArray(rawString, length);
|
||||
}
|
||||
ComPtr<IHostName> firstHost;
|
||||
hostNames->GetAt(0, &firstHost);
|
||||
|
||||
HString name;
|
||||
firstHost->get_CanonicalName(name.GetAddressOf());
|
||||
UINT32 length;
|
||||
PCWSTR rawString = name.GetRawBuffer(&length);
|
||||
return QString::fromWCharArray(rawString, length);
|
||||
}
|
||||
|
||||
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -152,10 +152,6 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*! \internal
|
||||
Constructs the private class and initializes all data members.
|
||||
|
||||
On Windows, WSAStartup is called "recursively" for every
|
||||
concurrent QNativeSocketEngine. This is safe, because WSAStartup and
|
||||
WSACleanup are reference counted.
|
||||
*/
|
||||
QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
|
||||
socketDescriptor(-1),
|
||||
@ -163,6 +159,9 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
|
||||
writeNotifier(0),
|
||||
exceptNotifier(0)
|
||||
{
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
QSysInfo::machineHostName(); // this initializes ws2_32.dll
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
|
@ -173,16 +173,6 @@ private:
|
||||
Q_DISABLE_COPY(QNativeSocketEngine)
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
class QWindowsSockInit
|
||||
{
|
||||
public:
|
||||
QWindowsSockInit();
|
||||
~QWindowsSockInit();
|
||||
int version;
|
||||
};
|
||||
#endif
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate
|
||||
@ -196,10 +186,6 @@ public:
|
||||
|
||||
QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QWindowsSockInit winSock;
|
||||
#endif
|
||||
|
||||
enum ErrorString {
|
||||
NonBlockingInitFailedErrorString,
|
||||
BroadcastingInitFailedErrorString,
|
||||
|
@ -320,25 +320,6 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
|
||||
return value;
|
||||
}
|
||||
|
||||
QWindowsSockInit::QWindowsSockInit()
|
||||
: version(0)
|
||||
{
|
||||
//### should we try for 2.2 on all platforms ??
|
||||
WSAData wsadata;
|
||||
|
||||
// IPv6 requires Winsock v2.0 or better.
|
||||
if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
|
||||
qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
|
||||
} else {
|
||||
version = 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
QWindowsSockInit::~QWindowsSockInit()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
// MS Transport Provider IOCTL to control
|
||||
// reporting PORT_UNREACHABLE messages
|
||||
// on UDP sockets via recv/WSARecv/etc.
|
||||
|
@ -134,6 +134,7 @@ int main(int argc, char *argv[])
|
||||
printf("QSysInfo::productType() = %s\n", qPrintable(QSysInfo::productType()));
|
||||
printf("QSysInfo::productVersion() = %s\n", qPrintable(QSysInfo::productVersion()));
|
||||
printf("QSysInfo::prettyProductName() = %s\n", qPrintable(QSysInfo::prettyProductName()));
|
||||
printf("QSysInfo::machineHostName() = %s\n", qPrintable(QSysInfo::machineHostName()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user