Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ScanIpIfAddrs.hpp 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * If you would like to incorporate Link into a proprietary software application,
  17. * please contact <link-devs@ableton.com>.
  18. */
  19. #pragma once
  20. #include <ableton/platforms/asio/AsioWrapper.hpp>
  21. #include <ableton/platforms/asio/Util.hpp>
  22. #include <iphlpapi.h>
  23. #include <stdio.h>
  24. #include <vector>
  25. #include <winsock2.h>
  26. #include <ws2tcpip.h>
  27. #pragma comment(lib, "iphlpapi.lib")
  28. #pragma comment(lib, "ws2_32.lib")
  29. namespace ableton
  30. {
  31. namespace platforms
  32. {
  33. namespace windows
  34. {
  35. namespace detail
  36. {
  37. // RAII type to make [get,free]ifaddrs function pairs exception safe
  38. class GetIfAddrs
  39. {
  40. public:
  41. GetIfAddrs()
  42. {
  43. const int MAX_TRIES = 3; // MSFT recommendation
  44. const int WORKING_BUFFER_SIZE = 15000; // MSFT recommendation
  45. DWORD adapter_addrs_buffer_size = WORKING_BUFFER_SIZE;
  46. for (int i = 0; i < MAX_TRIES; i++)
  47. {
  48. adapter_addrs = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addrs_buffer_size);
  49. assert(adapter_addrs);
  50. DWORD error = ::GetAdaptersAddresses(AF_UNSPEC,
  51. GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER
  52. | GAA_FLAG_SKIP_FRIENDLY_NAME,
  53. NULL, adapter_addrs, &adapter_addrs_buffer_size);
  54. if (error == ERROR_SUCCESS)
  55. {
  56. break;
  57. }
  58. // if buffer too small, use new buffer size in next iteration
  59. if (error == ERROR_BUFFER_OVERFLOW)
  60. {
  61. free(adapter_addrs);
  62. adapter_addrs = NULL;
  63. continue;
  64. }
  65. }
  66. }
  67. ~GetIfAddrs()
  68. {
  69. if (adapter_addrs)
  70. free(adapter_addrs);
  71. }
  72. // RAII must not copy
  73. GetIfAddrs(GetIfAddrs&) = delete;
  74. GetIfAddrs& operator=(GetIfAddrs&) = delete;
  75. template <typename Function>
  76. void withIfAddrs(Function f)
  77. {
  78. if (adapter_addrs)
  79. f(*adapter_addrs);
  80. }
  81. private:
  82. IP_ADAPTER_ADDRESSES* adapter_addrs;
  83. IP_ADAPTER_ADDRESSES* adapter;
  84. };
  85. } // namespace detail
  86. struct ScanIpIfAddrs
  87. {
  88. // Scan active network interfaces and return corresponding addresses
  89. // for all ip-based interfaces.
  90. std::vector<::asio::ip::address> operator()()
  91. {
  92. std::vector<::asio::ip::address> addrs;
  93. detail::GetIfAddrs getIfAddrs;
  94. getIfAddrs.withIfAddrs([&addrs](const IP_ADAPTER_ADDRESSES& interfaces) {
  95. const IP_ADAPTER_ADDRESSES* networkInterface;
  96. for (networkInterface = &interfaces; networkInterface;
  97. networkInterface = networkInterface->Next)
  98. {
  99. for (IP_ADAPTER_UNICAST_ADDRESS* address = networkInterface->FirstUnicastAddress;
  100. NULL != address; address = address->Next)
  101. {
  102. auto family = address->Address.lpSockaddr->sa_family;
  103. if (AF_INET == family)
  104. {
  105. // IPv4
  106. SOCKADDR_IN* addr4 =
  107. reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
  108. auto bytes = reinterpret_cast<const char*>(&addr4->sin_addr);
  109. addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes));
  110. }
  111. else if (AF_INET6 == family)
  112. {
  113. SOCKADDR_IN6* addr6 =
  114. reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
  115. auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);
  116. addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes));
  117. }
  118. }
  119. }
  120. });
  121. return addrs;
  122. }
  123. };
  124. } // namespace windows
  125. } // namespace platforms
  126. } // namespace ableton