gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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 }