From c758482ece08e7b393e343464bf9a2c2d74bf34f Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 22 Feb 2015 10:51:16 +0100 Subject: cNetwork: Added EnumLocalIPAddresses() function. --- src/Bindings/ManualBindings_Network.cpp | 35 +++++++-- src/OSSupport/CMakeLists.txt | 1 + src/OSSupport/Network.h | 3 + src/OSSupport/NetworkInterfaceEnum.cpp | 129 ++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 src/OSSupport/NetworkInterfaceEnum.cpp (limited to 'src') diff --git a/src/Bindings/ManualBindings_Network.cpp b/src/Bindings/ManualBindings_Network.cpp index a628eb9ca..628cda7f0 100644 --- a/src/Bindings/ManualBindings_Network.cpp +++ b/src/Bindings/ManualBindings_Network.cpp @@ -129,6 +129,30 @@ static int tolua_cNetwork_CreateUDPEndpoint(lua_State * L) +/** Binds cNetwork::EnumLocalIPAddresses */ +static int tolua_cNetwork_EnumLocalIPAddresses(lua_State * L) +{ + // Function signature: + // cNetwork:EnumLocalIPAddresses() -> {string, ...} + + cLuaState S(L); + if ( + !S.CheckParamUserTable(1, "cNetwork") || + !S.CheckParamEnd(2) + ) + { + return 0; + } + + // Push the enumerated addresses: + S.Push(cNetwork::EnumLocalIPAddresses()); + return 1; +} + + + + + /** Binds cNetwork::HostnameToIP */ static int tolua_cNetwork_HostnameToIP(lua_State * L) { @@ -903,11 +927,12 @@ void ManualBindings::BindNetwork(lua_State * tolua_S) // Fill in the functions (alpha-sorted): tolua_beginmodule(tolua_S, "cNetwork"); - tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); - tolua_function(tolua_S, "CreateUDPEndpoint", tolua_cNetwork_CreateUDPEndpoint); - tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); - tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); - tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); + tolua_function(tolua_S, "Connect", tolua_cNetwork_Connect); + tolua_function(tolua_S, "CreateUDPEndpoint", tolua_cNetwork_CreateUDPEndpoint); + tolua_function(tolua_S, "EnumLocalIPAddresses", tolua_cNetwork_EnumLocalIPAddresses); + tolua_function(tolua_S, "HostnameToIP", tolua_cNetwork_HostnameToIP); + tolua_function(tolua_S, "IPToHostname", tolua_cNetwork_IPToHostname); + tolua_function(tolua_S, "Listen", tolua_cNetwork_Listen); tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cServerHandle"); diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt index 81b37ef0e..0d3c9a63e 100644 --- a/src/OSSupport/CMakeLists.txt +++ b/src/OSSupport/CMakeLists.txt @@ -13,6 +13,7 @@ SET (SRCS HostnameLookup.cpp IPLookup.cpp IsThread.cpp + NetworkInterfaceEnum.cpp NetworkSingleton.cpp Semaphore.cpp ServerHandleImpl.cpp diff --git a/src/OSSupport/Network.h b/src/OSSupport/Network.h index 5dd596223..95a935bbe 100644 --- a/src/OSSupport/Network.h +++ b/src/OSSupport/Network.h @@ -318,6 +318,9 @@ public: If a_Port is 0, the OS is free to assign any port number it likes to the endpoint. Returns the endpoint object that can be interacted with. */ static cUDPEndpointPtr CreateUDPEndpoint(UInt16 a_Port, cUDPEndpoint::cCallbacks & a_Callbacks); + + /** Returns all local IP addresses for network interfaces currently available. */ + static AStringVector EnumLocalIPAddresses(void); }; diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp new file mode 100644 index 000000000..675769065 --- /dev/null +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -0,0 +1,129 @@ + +// NetworkInterfaceEnum.cpp + +// Implements the cNetwork::EnumLocalIPAddresses() interface enumeration function + +#include "Globals.h" +#include "Network.h" +#include "event2/util.h" +#ifdef _WIN32 + #include + #pragma comment(lib, "IPHLPAPI.lib") +#else // _WIN32 +#endif // else _WIN32 + + + + + +#ifdef SELF_TEST + +static class cEnumIPAddressTest +{ +public: + cEnumIPAddressTest(void) + { + printf("Enumerating all IP addresses...\n"); + auto IPs = cNetwork::EnumLocalIPAddresses(); + for (auto & ip: IPs) + { + printf(" %s\n", ip.c_str()); + } + printf("done.\n"); + } +} g_EnumIPAddressTest; + +#endif // SELF_TEST + + + + + +#ifdef _WIN32 + +/** Converts the SOCKET_ADDRESS structure received from the OS into an IP address string. */ +static AString PrintAddress(SOCKET_ADDRESS & a_Addr) +{ + char IP[128]; + switch (a_Addr.lpSockaddr->sa_family) + { + case AF_INET: + { + auto sin = reinterpret_cast(a_Addr.lpSockaddr); + evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin_addr), IP, sizeof(IP)); + break; + } + case AF_INET6: + { + auto sin = reinterpret_cast(a_Addr.lpSockaddr); + evutil_inet_ntop(a_Addr.lpSockaddr->sa_family, &(sin->sin6_addr), IP, sizeof(IP)); + break; + } + default: + { + IP[0] = 0; + break; + } + } + return AString(IP); +} + +#endif // _WIN32 + + + + + +AStringVector cNetwork::EnumLocalIPAddresses(void) +{ + AStringVector res; + + #ifdef _WIN32 + + // Query the OS for all adapters' addresses: + char buffer[64 KiB]; // A buffer backing the address list + PIP_ADAPTER_ADDRESSES pAddresses = reinterpret_cast(&buffer); + ULONG outBufLen = sizeof(buffer); + DWORD dwRetVal = GetAdaptersAddresses( + AF_UNSPEC, + GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME, nullptr, + pAddresses, &outBufLen + ); + if (dwRetVal != ERROR_SUCCESS) + { + LOG("GetAdaptersAddresses() failed: %u", dwRetVal); + return res; + } + + // Enumerate all active adapters + for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next) + { + if (pCurrAddresses->OperStatus != 1) + { + // Adapter not active, skip it: + continue; + } + + // Collect all IP addresses on this adapter: + for (auto pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next) + { + auto Address = PrintAddress(pUnicast->Address); + if (!Address.empty()) + { + res.push_back(Address); + } + } // for pUnicast + } // for pCurrAddresses + + #else // _WIN32 + + // TODO: Enumerate network interfaces on Linux + + #endif // else _WIN32 + + return res; +} + + + + -- cgit v1.2.3 From 1551e29f00f74520f035fb6425ce09a80c965bcb Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 22 Feb 2015 18:52:49 +0100 Subject: Network: Replaced magic number with named constant. --- src/OSSupport/NetworkInterfaceEnum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp index 675769065..38d946393 100644 --- a/src/OSSupport/NetworkInterfaceEnum.cpp +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -98,7 +98,7 @@ AStringVector cNetwork::EnumLocalIPAddresses(void) // Enumerate all active adapters for (auto pCurrAddresses = pAddresses; pCurrAddresses != nullptr; pCurrAddresses = pCurrAddresses->Next) { - if (pCurrAddresses->OperStatus != 1) + if (pCurrAddresses->OperStatus != IfOperStatusUp) { // Adapter not active, skip it: continue; -- cgit v1.2.3 From 20da3d34a51afb15145c9a02710a7a627163cd23 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 8 Mar 2015 16:54:44 +0000 Subject: Potential Linux implementation --- src/OSSupport/NetworkInterfaceEnum.cpp | 58 +++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp index 38d946393..94edd3bfb 100644 --- a/src/OSSupport/NetworkInterfaceEnum.cpp +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -10,6 +10,10 @@ #include #pragma comment(lib, "IPHLPAPI.lib") #else // _WIN32 + #include + #include + #include + #include #endif // else _WIN32 @@ -29,7 +33,7 @@ public: { printf(" %s\n", ip.c_str()); } - printf("done.\n"); + printf("Done.\n"); } } g_EnumIPAddressTest; @@ -65,10 +69,36 @@ static AString PrintAddress(SOCKET_ADDRESS & a_Addr) break; } } - return AString(IP); + return IP; } -#endif // _WIN32 +#else // _WIN32 + +static AString PrintAddress(ifaddrs * InterfaceAddress) +{ + switch (InterfaceAddress->ifa_addr->sa_family) + { + case AF_INET: + { // IPv4 + char AddressBuffer[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(reinterpret_cast(reinterpret_cast(InterfaceAddress->ifa_addr))->sin_addr), AddressBuffer, INET_ADDRSTRLEN); + return AddressBuffer; + } + case AF_INET6: + { // IPv6 + char AddressBuffer[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &(reinterpret_cast(reinterpret_cast(InterfaceAddress->ifa_addr))->sin6_addr), AddressBuffer, INET6_ADDRSTRLEN); + return AddressBuffer; + } + default: + { + LOG("Unknown address family: %i", InterfaceAddress->ifa_addr->sa_family); + return ""; + } + } +} + +#endif // else _WIN32 @@ -117,7 +147,27 @@ AStringVector cNetwork::EnumLocalIPAddresses(void) #else // _WIN32 - // TODO: Enumerate network interfaces on Linux + struct ifaddrs * ifAddrStruct = nullptr; + getifaddrs(&ifAddrStruct); + + for (auto ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == nullptr) + { + continue; + } + + auto Address = PrintAddress(ifa); + if (!Address.empty()) + { + res.emplace_back(Address); + } + } + + if (ifAddrStruct != nullptr) + { + freeifaddrs(ifAddrStruct); + } #endif // else _WIN32 -- cgit v1.2.3 From 4ffaace3849d9b084a8904aa6dbba50fa06bebd3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 10 Mar 2015 22:25:53 +0000 Subject: Use std::memcpy to fix alignment As suggested by @madmaxoft --- src/OSSupport/NetworkInterfaceEnum.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/OSSupport/NetworkInterfaceEnum.cpp b/src/OSSupport/NetworkInterfaceEnum.cpp index 94edd3bfb..c4af1e93c 100644 --- a/src/OSSupport/NetworkInterfaceEnum.cpp +++ b/src/OSSupport/NetworkInterfaceEnum.cpp @@ -81,13 +81,19 @@ static AString PrintAddress(ifaddrs * InterfaceAddress) case AF_INET: { // IPv4 char AddressBuffer[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(reinterpret_cast(reinterpret_cast(InterfaceAddress->ifa_addr))->sin_addr), AddressBuffer, INET_ADDRSTRLEN); + sockaddr_in InternetSocket; + + std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket)); + inet_ntop(AF_INET, &InternetSocket.sin_addr, AddressBuffer, INET_ADDRSTRLEN); return AddressBuffer; } case AF_INET6: { // IPv6 char AddressBuffer[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(reinterpret_cast(reinterpret_cast(InterfaceAddress->ifa_addr))->sin6_addr), AddressBuffer, INET6_ADDRSTRLEN); + sockaddr_in6 InternetSocket; + + std::memcpy(&InternetSocket, InterfaceAddress->ifa_addr, sizeof(InternetSocket)); + inet_ntop(AF_INET6, &InternetSocket.sin6_addr, AddressBuffer, INET6_ADDRSTRLEN); return AddressBuffer; } default: -- cgit v1.2.3