Commit 59e76cee authored by Dominik Charousset's avatar Dominik Charousset

Fix build on MinGW, relates #262

parent 5b07ea3e
...@@ -177,7 +177,7 @@ void mv(std::string& lhs, const std::basic_string<WCHAR>& rhs) { ...@@ -177,7 +177,7 @@ void mv(std::string& lhs, const std::basic_string<WCHAR>& rhs) {
std::string get_root_uuid() { std::string get_root_uuid() {
using tchar_str = std::basic_string<TCHAR>; using tchar_str = std::basic_string<TCHAR>;
string uuid; std::string uuid;
TCHAR buf[max_drive_name]; // temporary buffer for volume name TCHAR buf[max_drive_name]; // temporary buffer for volume name
tchar_str drive = TEXT("c:\\"); // string "template" for drive specifier tchar_str drive = TEXT("c:\\"); // string "template" for drive specifier
// walk through legal drive letters, skipping floppies // walk through legal drive letters, skipping floppies
......
...@@ -232,16 +232,16 @@ namespace network { ...@@ -232,16 +232,16 @@ namespace network {
ccall(cc_zero, "listen() failed", listen, listener, 1); ccall(cc_zero, "listen() failed", listen, listener, 1);
// create read-only end of the pipe // create read-only end of the pipe
DWORD flags = 0; DWORD flags = 0;
auto read_fd = ccall(cc_valid_socket, WSASocket, AF_INET, SOCK_STREAM, auto read_fd = ccall(cc_valid_socket, "WSASocket() failed", WSASocket,
0, NULL, 0, flags); AF_INET, SOCK_STREAM, 0, nullptr, 0, flags);
ccall(cc_zero, "connect() failed", connect, read_fd, ccall(cc_zero, "connect() failed", connect, read_fd,
&a.addr, int{sizeof(a.inaddr)}); &a.addr, int{sizeof(a.inaddr)});
// get write-only end of the pipe // get write-only end of the pipe
auto write_fd = ccall(cc_valid_socket, "accept() failed", auto write_fd = ccall(cc_valid_socket, "accept() failed",
accept, listener, NULL, NULL); accept, listener, nullptr, nullptr);
closesocket(listener); closesocket(listener);
guard.disable(); guard.disable();
return {read_fd, write_fd}; return std::make_pair(read_fd, write_fd);
} }
#endif #endif
...@@ -998,6 +998,11 @@ class socket_guard { ...@@ -998,6 +998,11 @@ class socket_guard {
native_socket m_fd; native_socket m_fd;
}; };
#ifdef CAF_WINDOWS
using sa_family_t = short;
using in_port_t = unsigned short;
#endif
in_addr& addr_of(sockaddr_in& what) { in_addr& addr_of(sockaddr_in& what) {
return what.sin_addr; return what.sin_addr;
} }
......
...@@ -19,21 +19,35 @@ ...@@ -19,21 +19,35 @@
#include "caf/io/network/interfaces.hpp" #include "caf/io/network/interfaces.hpp"
#include <netdb.h> #include "caf/config.hpp"
#include <errno.h>
#include <stdlib.h> #include <cerrno>
#include <string.h> #include <cstdlib>
#include <net/if.h> #include <cstring>
#include <unistd.h>
#include <ifaddrs.h> #ifdef CAF_WINDOWS
#include <sys/ioctl.h> # ifndef _WIN32_WINNT
#include <arpa/inet.h> # define _WIN32_WINNT 0x0600
#include <netinet/in.h> # endif
#include <sys/socket.h> # include <iostream>
# include <winsock2.h>
# include <ws2tcpip.h>
# include <iphlpapi.h>
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "iphlpapi.lib")
#else
# include <net/if.h>
# include <unistd.h>
# include <netdb.h>
# include <ifaddrs.h>
# include <sys/ioctl.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# include <sys/socket.h>
#endif
#include <memory> #include <memory>
#include "caf/detail/logging.hpp"
#include "caf/detail/get_mac_addresses.hpp" #include "caf/detail/get_mac_addresses.hpp"
namespace caf { namespace caf {
...@@ -53,19 +67,113 @@ in_addr* fetch_in_addr(sockaddr_in* addr) { ...@@ -53,19 +67,113 @@ in_addr* fetch_in_addr(sockaddr_in* addr) {
return &(addr->sin_addr); return &(addr->sin_addr);
} }
template <class SockaddrType, int Family> template <int Family, class SockAddr>
void add_addr(ifaddrs* first, std::vector<std::string>& res) { void add_addr_as_string(std::vector<std::string>& res, SockAddr* addr) {
auto addr = reinterpret_cast<SockaddrType*>(first->ifa_addr);
auto in_addr = fetch_in_addr(addr); auto in_addr = fetch_in_addr(addr);
char address_buffer[INET6_ADDRSTRLEN + 1]; char address_buffer[INET6_ADDRSTRLEN + 1];
inet_ntop(Family, in_addr, address_buffer, INET6_ADDRSTRLEN); inet_ntop(Family, in_addr, address_buffer, INET6_ADDRSTRLEN);
res.push_back(address_buffer); res.push_back(address_buffer);
} }
#ifdef CAF_WINDOWS
using if_device_ptr = IP_ADAPTER_ADDRESSES*;
const char* if_device_name(if_device_ptr ptr) {
return ptr->AdapterName;
}
template <int Family>
void add_addr(if_device_ptr ptr, std::vector<std::string>& res) {
static_assert(Family == AF_INET || Family == AF_INET6,
"invalid address family");
using addr_type =
typename std::conditional<
Family == AF_INET,
sockaddr_in*,
sockaddr_in6*
>::type;
for (auto i = ptr->FirstUnicastAddress; i != nullptr; i = i->Next) {
if (i->Address.lpSockaddr->sa_family == Family) {
auto addr = reinterpret_cast<addr_type>(i->Address.lpSockaddr);
add_addr_as_string<Family>(res, addr);
}
}
}
template <class F>
void for_each_device(bool include_localhost, F fun) {
ULONG tmp_size = 16 * 1024; // try 16kb buffer first
IP_ADAPTER_ADDRESSES* tmp = nullptr;
constexpr size_t max_tries = 3;
size_t try_nr = 0;
int retval = 0;
do {
if (tmp != nullptr) {
free(tmp);
}
tmp = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(tmp_size));
if (tmp == nullptr) {
throw std::bad_alloc();
}
retval = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX,
nullptr, tmp, &tmp_size);
} while (retval == ERROR_BUFFER_OVERFLOW && ++try_nr < max_tries);
std::unique_ptr<IP_ADAPTER_ADDRESSES, decltype(free)*> ifs{tmp, free};
if (retval != NO_ERROR) {
std::cerr << "Call to GetAdaptersAddresses failed with error: "
<< retval << std::endl;
if (retval == ERROR_NO_DATA) {
std::cerr << "No addresses were found for the requested parameters"
<< std::endl;
} else {
void* msgbuf = nullptr;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, retval,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msgbuf, 0, nullptr)) {
printf("Error: %s", msgbuf);
LocalFree(msgbuf);
}
}
return;
}
for (auto i = ifs.get(); i != nullptr; i = i->Next) {
fun(i);
}
}
#else // ifdef CAF_WINDOWS
// interface address pointer
using if_device_ptr = ifaddrs*;
const char* if_device_name(if_device_ptr ptr) {
return ptr->ifa_name;
}
template <int Family>
void add_addr(if_device_ptr ptr, std::vector<std::string>& res) {
static_assert(Family == AF_INET || Family == AF_INET6,
"invalid address family");
using addr_type =
typename std::conditional<
Family == AF_INET,
sockaddr_in*,
sockaddr_in6*
>::type;
if (ptr->ifa_addr->sa_family != Family) {
return;
}
add_addr_as_string<Family>(res, reinterpret_cast<addr_type>(ptr->ifa_addr));
}
template <class F> template <class F>
void for_each_device(bool include_localhost, F fun) { void for_each_device(bool include_localhost, F fun) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
ifaddrs* tmp = nullptr; if_device_ptr tmp = nullptr;
if (getifaddrs(&tmp) != 0) { if (getifaddrs(&tmp) != 0) {
perror("getifaddrs"); perror("getifaddrs");
return; return;
...@@ -74,30 +182,29 @@ void for_each_device(bool include_localhost, F fun) { ...@@ -74,30 +182,29 @@ void for_each_device(bool include_localhost, F fun) {
for (auto i = ifs.get(); i != nullptr; i = i->ifa_next) { for (auto i = ifs.get(); i != nullptr; i = i->ifa_next) {
auto family = i->ifa_addr->sa_family; auto family = i->ifa_addr->sa_family;
if (include_localhost) { if (include_localhost) {
fun(i, family); fun(i);
} else if (family == AF_INET || family == AF_INET6) { } else if (family == AF_INET || family == AF_INET6) {
auto len = static_cast<socklen_t>(family == AF_INET auto len = static_cast<socklen_t>(family == AF_INET
? sizeof(sockaddr_in) ? sizeof(sockaddr_in)
: sizeof(sockaddr_in6)); : sizeof(sockaddr_in6));
auto ok = getnameinfo(i->ifa_addr, len, host, NI_MAXHOST, nullptr, 0, 0); auto ok = getnameinfo(i->ifa_addr, len, host, NI_MAXHOST, nullptr, 0, 0);
if (ok == 0 && strcmp("localhost", host) != 0) { if (ok == 0 && strcmp("localhost", host) != 0) {
fun(i, family); fun(i);
} }
} }
} }
} }
#endif // ifdef CAF_WINDOWS
interfaces_map interfaces::list_all(bool include_localhost) { interfaces_map interfaces::list_all(bool include_localhost) {
interfaces_map result; interfaces_map result;
for (auto& pair : detail::get_mac_addresses()) { for (auto& pair : detail::get_mac_addresses()) {
result[pair.first][protocol::ethernet].push_back(std::move(pair.second)); result[pair.first][protocol::ethernet].push_back(std::move(pair.second));
} }
for_each_device(include_localhost, [&](ifaddrs* i, int family) { for_each_device(include_localhost, [&](if_device_ptr i) {
if (family == AF_INET) { add_addr<AF_INET>(i, result[if_device_name(i)][protocol::ipv4]);
add_addr<sockaddr_in, AF_INET>(i, result[i->ifa_name][protocol::ipv4]); add_addr<AF_INET6>(i, result[if_device_name(i)][protocol::ipv6]);
} else if (family == AF_INET6) {
add_addr<sockaddr_in6, AF_INET6>(i, result[i->ifa_name][protocol::ipv6]);
}
}); });
return result; return result;
} }
...@@ -108,12 +215,9 @@ interfaces::list_addresses(bool include_localhost) { ...@@ -108,12 +215,9 @@ interfaces::list_addresses(bool include_localhost) {
for (auto& pair : detail::get_mac_addresses()) { for (auto& pair : detail::get_mac_addresses()) {
result[protocol::ethernet].push_back(std::move(pair.second)); result[protocol::ethernet].push_back(std::move(pair.second));
} }
for_each_device(include_localhost, [&](ifaddrs* i, int family) { for_each_device(include_localhost, [&](if_device_ptr i) {
if (family == AF_INET) { add_addr<AF_INET>(i, result[protocol::ipv4]);
add_addr<sockaddr_in, AF_INET>(i, result[protocol::ipv4]); add_addr<AF_INET6>(i, result[protocol::ipv6]);
} else if (family == AF_INET6) {
add_addr<sockaddr_in6, AF_INET6>(i, result[protocol::ipv6]);
}
}); });
return result; return result;
} }
...@@ -128,17 +232,13 @@ std::vector<std::string> interfaces::list_addresses(protocol proc, ...@@ -128,17 +232,13 @@ std::vector<std::string> interfaces::list_addresses(protocol proc,
} }
break; break;
case protocol::ipv4: case protocol::ipv4:
for_each_device(include_localhost, [&](ifaddrs* i, int family) { for_each_device(include_localhost, [&](if_device_ptr i) {
if (family == AF_INET) { add_addr<AF_INET>(i, result);
add_addr<sockaddr_in, AF_INET>(i, result);
}
}); });
break; break;
case protocol::ipv6: case protocol::ipv6:
for_each_device(include_localhost, [&](ifaddrs* i, int family) { for_each_device(include_localhost, [&](if_device_ptr i) {
if (family == AF_INET6) { add_addr<AF_INET6>(i, result);
add_addr<sockaddr_in6, AF_INET6>(i, result);
}
}); });
break; break;
} }
...@@ -148,7 +248,6 @@ std::vector<std::string> interfaces::list_addresses(protocol proc, ...@@ -148,7 +248,6 @@ std::vector<std::string> interfaces::list_addresses(protocol proc,
optional<std::pair<std::string, protocol>> optional<std::pair<std::string, protocol>>
interfaces::native_address(const std::string& host, interfaces::native_address(const std::string& host,
optional<protocol> preferred) { optional<protocol> preferred) {
CAF_LOGF_TRACE(CAF_ARG(host) << ", " << CAF_TSARG(preferred));
addrinfo hint; addrinfo hint;
memset(&hint, 0, sizeof(hint)); memset(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_STREAM; hint.ai_socktype = SOCK_STREAM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment