udpClient.cpp (3070B)
1 #include "udpClient.h" 2 3 #include "logging.h" 4 5 #include "../ptypes/pinet.h" 6 7 #ifdef _WIN32 8 #define NOMINMAX 9 #include <Windows.h> 10 #include <iphlpapi.h> 11 #include <ws2tcpip.h> 12 #pragma comment(lib, "Iphlpapi.lib") 13 #elif !defined(ANDROID) 14 #include <ifaddrs.h> 15 #endif 16 17 namespace networkLib 18 { 19 UdpClient::UdpClient(const int _udpPort) : m_port(_udpPort) 20 { 21 getBroadcastAddresses(m_broadcastAddresses); 22 if(m_broadcastAddresses.empty()) 23 m_broadcastAddresses.push_back(0xff'ff'ff'ff); 24 } 25 26 void UdpClient::getBroadcastAddresses(std::vector<uint32_t>& _addresses) 27 { 28 #ifdef _WIN32 29 ULONG bufferSize = 0; 30 if (GetAdaptersInfo(nullptr, &bufferSize) != ERROR_BUFFER_OVERFLOW) 31 return; 32 33 std::vector<BYTE> buffer; 34 buffer.resize(bufferSize, 0); 35 36 if (GetAdaptersInfo(reinterpret_cast<IP_ADAPTER_INFO*>(buffer.data()), &bufferSize) != ERROR_SUCCESS) 37 return; 38 39 const IP_ADAPTER_INFO* adapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(buffer.data()); 40 41 for(; adapterInfo != nullptr; adapterInfo = adapterInfo->Next) 42 { 43 IN_ADDR addrIp; 44 IN_ADDR addrMask; 45 46 inet_pton(AF_INET, adapterInfo->IpAddressList.IpAddress.String, &addrIp); 47 inet_pton(AF_INET, adapterInfo->IpAddressList.IpMask.String, &addrMask); 48 49 const auto broadcastAddr = addrIp.S_un.S_addr | ~addrMask.S_un.S_addr; 50 51 if(!broadcastAddr) 52 continue; 53 54 _addresses.push_back(broadcastAddr); 55 } 56 57 #elif defined(ANDROID) 58 _addresses.push_back(0xff'ff'ff'ff); 59 #else 60 ifaddrs* ifap = nullptr; 61 if (getifaddrs(&ifap) == 0 && ifap) 62 { 63 struct ifaddrs * p = ifap; 64 while(p) 65 { 66 auto toUint32 = [](sockaddr* a) -> uint32_t 67 { 68 if(!a || a->sa_family != AF_INET) 69 return 0; 70 return ((struct sockaddr_in *)a)->sin_addr.s_addr; 71 }; 72 73 const auto ifaAddr = toUint32(p->ifa_addr); 74 const auto maskAddr = toUint32(p->ifa_netmask); 75 76 if (ifaAddr > 0) 77 { 78 const auto mask = ifaAddr | ~maskAddr; 79 if(mask) 80 _addresses.push_back(mask); 81 } 82 p = p->ifa_next; 83 } 84 freeifaddrs(ifap); 85 } 86 #endif 87 } 88 89 void UdpClient::threadLoopFunc() 90 { 91 try 92 { 93 const auto& req = getRequestPacket(); 94 95 for (const auto broadcastAddress : m_broadcastAddresses) 96 { 97 ptypes::ipmessage msg(ptypes::ipaddress((ptypes::ulong)broadcastAddress), m_port); 98 msg.send(reinterpret_cast<const char*>(req.data()), static_cast<int>(req.size())); 99 std::vector<uint8_t> buffer; 100 buffer.resize(getMaxUdpResponseSize()); 101 102 // wait for answer 103 while (msg.waitfor(250)) 104 { 105 ptypes::ipaddress addr; 106 107 const auto count = msg.receive(reinterpret_cast<char*>(buffer.data()), static_cast<int>(buffer.size()), addr); 108 109 if(!count) 110 continue; 111 112 buffer.resize(count); 113 114 const auto host = std::string(ptypes::iptostring(addr)); 115 116 if(validateResponse(host, buffer)) 117 { 118 exit(true); 119 break; 120 } 121 } 122 123 if(exit()) 124 break; 125 } 126 } 127 catch(ptypes::exception* e) // NOLINT(misc-throw-by-value-catch-by-reference) 128 { 129 LOGNET(LogLevel::Warning, "Network error: " << static_cast<const char*>(e->get_message())); 130 } 131 } 132 }