diff --git a/src/gui/src/win32/DefaultInterfaceIP.h b/src/gui/src/DefaultInterfaceIP.h similarity index 90% rename from src/gui/src/win32/DefaultInterfaceIP.h rename to src/gui/src/DefaultInterfaceIP.h index 2067aeac..a3c14571 100644 --- a/src/gui/src/win32/DefaultInterfaceIP.h +++ b/src/gui/src/DefaultInterfaceIP.h @@ -1,10 +1,10 @@ -#pragma once - -#include - -namespace Debauchee -{ - -std::string default_interface_ip(); - -} +#pragma once + +#include + +namespace Debauchee +{ + +std::string default_interface_ip(); + +} diff --git a/src/gui/src/ZeroconfService.cpp b/src/gui/src/ZeroconfService.cpp index b5060108..66706253 100644 --- a/src/gui/src/ZeroconfService.cpp +++ b/src/gui/src/ZeroconfService.cpp @@ -20,6 +20,7 @@ #include "MainWindow.h" #include "ZeroconfRegister.h" #include "ZeroconfBrowser.h" +#include "DefaultInterfaceIP.h" #include #include @@ -30,7 +31,6 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include -#include "win32/DefaultInterfaceIP.h" #else #include #endif @@ -119,29 +119,6 @@ void ZeroconfService::errorHandle(DNSServiceErrorType errorCode) tr("Error code: %1.").arg(errorCode)); } -QString ZeroconfService::getLocalIPAddresses() -{ -#ifdef _WIN32 - return QString::fromStdString(Debauchee::default_interface_ip()); -#else - const QString NonEthernetMAC = "00:00:00:00:00:00"; - foreach(const auto qni, QNetworkInterface::allInterfaces()) { - // weed out loopback, inactive, and non-ethernet interfaces - if (!qni.flags().testFlag(QNetworkInterface::IsLoopBack) && - qni.flags().testFlag(QNetworkInterface::IsUp) && - qni.hardwareAddress() != NonEthernetMAC) { - foreach(const auto address, qni.allAddresses()) { - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - // use the first address we find - return address.toString(); - } - } - } - } - return ""; -#endif -} - bool ZeroconfService::registerService(bool server) { bool result = true; @@ -156,7 +133,7 @@ bool ZeroconfService::registerService(bool server) else { m_pZeroconfRegister = new ZeroconfRegister(this); if (server) { - QString localIP = getLocalIPAddresses(); + QString localIP = QString::fromStdString(Debauchee::default_interface_ip()); if (localIP.isEmpty()) { QMessageBox::warning(m_pMainWindow, tr("Barrier"), tr("Failed to get local IP address. " diff --git a/src/gui/src/ZeroconfService.h b/src/gui/src/ZeroconfService.h index 929cd055..8a3b8beb 100644 --- a/src/gui/src/ZeroconfService.h +++ b/src/gui/src/ZeroconfService.h @@ -42,7 +42,6 @@ private slots: void errorHandle(DNSServiceErrorType errorCode); private: - QString getLocalIPAddresses(); bool registerService(bool server); private: diff --git a/src/gui/src/unix/DefaultInterfaceIP.cpp b/src/gui/src/unix/DefaultInterfaceIP.cpp new file mode 100644 index 00000000..b276b202 --- /dev/null +++ b/src/gui/src/unix/DefaultInterfaceIP.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include +#include "SocketResource.h" +#include "IfAddrsResource.h" + +namespace Debauchee +{ + +static bool is_wireless(const char * ifname) +{ + if (ifname) { + SocketResource fd(AF_INET, SOCK_STREAM, 0); + if (fd.is_valid()) { + struct iwreq req { 0 }; + ::strncpy(req.ifr_name, ifname, IFNAMSIZ - 1); + return ioctl(fd, SIOCGIWMODE, req) >= 0; + } + } + return false; +} + +std::string default_interface_ip() +{ + std::string wirelessAddress; + IfAddrsResource ifa; + if (ifa.is_valid()) { + for (struct ifaddrs * next = ifa; next; next = next->ifa_next) { + auto sain = (struct sockaddr_in *)next->ifa_addr; + if (!sain || sain->sin_family != AF_INET || + !(next->ifa_flags & IFF_RUNNING) || + (next->ifa_flags & IFF_LOOPBACK) + ) { + continue; + } + std::string address = inet_ntoa(sain->sin_addr); + // take first wired address right away + if (!is_wireless(next->ifa_name)) { + return address; + } + // save first wireless address to be used if we don't find a wired one + if (wirelessAddress.empty()) { + wirelessAddress = address; + } + } + } + return wirelessAddress; +} + +} + diff --git a/src/gui/src/unix/IfAddrsResource.h b/src/gui/src/unix/IfAddrsResource.h new file mode 100644 index 00000000..57c1a2ba --- /dev/null +++ b/src/gui/src/unix/IfAddrsResource.h @@ -0,0 +1,32 @@ +#include +#include + +namespace Debauchee +{ + +class IfAddrsResource +{ +public: + explicit IfAddrsResource() : + _valid(getifaddrs(&_ifa) == 0) + { + } + + ~IfAddrsResource() + { + if (_valid) { + freeifaddrs(_ifa); + } + } + + bool is_valid() const { return _valid; } + + operator struct ifaddrs * () const { return _ifa; } + +private: + bool _valid; + struct ifaddrs * _ifa; +}; + +} + diff --git a/src/gui/src/unix/SocketResource.h b/src/gui/src/unix/SocketResource.h new file mode 100644 index 00000000..bff23e44 --- /dev/null +++ b/src/gui/src/unix/SocketResource.h @@ -0,0 +1,31 @@ +#include +#include + +namespace Debauchee +{ + +class SocketResource +{ +public: + explicit SocketResource(int domain, int type, int protocol) : + _fd(socket(domain, type, protocol)) + { + } + + ~SocketResource() + { + if (is_valid()) { + close(_fd); + } + } + + bool is_valid() const { return _fd >= 0; } + + operator int() const { return _fd; } + +private: + int _fd; +}; + +} +