| 95 | |
| 96 | #ifndef WIN32 |
| 97 | std::error_code bind_to_local_network_interface(const minifi::io::SocketDescriptor fd, const minifi::io::NetworkInterface& interface) { |
| 98 | using ifaddrs_uniq_ptr = std::unique_ptr<ifaddrs, util::ifaddrs_deleter>; |
| 99 | const auto if_list_ptr = []() -> ifaddrs_uniq_ptr { |
| 100 | ifaddrs *list = nullptr; |
| 101 | const auto get_ifa_success = getifaddrs(&list) == 0; |
| 102 | assert(get_ifa_success || !list); |
| 103 | (void)get_ifa_success; // unused in release builds |
| 104 | return ifaddrs_uniq_ptr{ list }; |
| 105 | }(); |
| 106 | if (!if_list_ptr) { return { errno, std::generic_category() }; } |
| 107 | |
| 108 | const auto advance_func = [](const ifaddrs *const p) { return p->ifa_next; }; |
| 109 | const auto predicate = [&interface](const ifaddrs *const item) { |
| 110 | return item->ifa_addr && item->ifa_name && (item->ifa_addr->sa_family == AF_INET || item->ifa_addr->sa_family == AF_INET6) |
| 111 | && item->ifa_name == interface.getInterface(); |
| 112 | }; |
| 113 | const auto *const itemFound = find_if_custom_linked_list(if_list_ptr.get(), advance_func, predicate); |
| 114 | if (itemFound == nullptr) { return std::make_error_code(std::errc::no_such_device_or_address); } |
| 115 | |
| 116 | const socklen_t addrlen = itemFound->ifa_addr->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); |
| 117 | if (bind(fd, itemFound->ifa_addr, addrlen) != 0) { return { errno, std::generic_category() }; } |
| 118 | return {}; |
| 119 | } |
| 120 | #endif /* !WIN32 */ |
| 121 | |
| 122 | std::error_code set_non_blocking(const minifi::io::SocketDescriptor fd) noexcept { |
no test coverage detected